From c38a6122c95132d3468a2bbadefac5c0dbaf28a1 Mon Sep 17 00:00:00 2001 From: nobody Date: Tue, 9 Dec 2003 01:57:09 +0000 Subject: This commit was manufactured by cvs2svn to create tag 'GGV_2_6_2'. svn path=/tags/GGV_2_6_2/; revision=23746 --- camel/.cvsignore | 13 - camel/CODING.STYLE | 19 - camel/ChangeLog | 1488 -- camel/ChangeLog.pre-1-4 | 22083 ------------------- camel/Makefile.am | 296 - camel/README | 54 - camel/README.COPYRIGHT | 46 - camel/README.HACKING | 14 - camel/README.mt | 171 - camel/broken-date-parser.c | 532 - camel/broken-date-parser.h | 33 - camel/camel-address.c | 240 - camel/camel-address.h | 79 - camel/camel-arg.c | 130 - camel/camel-arg.h | 119 - camel/camel-block-file.c | 1181 - camel/camel-block-file.h | 144 - camel/camel-certdb.c | 665 - camel/camel-certdb.h | 154 - camel/camel-charset-map-private.h | 621 - camel/camel-charset-map.c | 352 - camel/camel-charset-map.h | 51 - camel/camel-cipher-context.c | 585 - camel/camel-cipher-context.h | 174 - camel/camel-data-cache.c | 421 - camel/camel-data-cache.h | 98 - camel/camel-data-wrapper.c | 389 - camel/camel-data-wrapper.h | 105 - camel/camel-digest-folder.c | 396 - camel/camel-digest-folder.h | 52 - camel/camel-digest-store.c | 203 - camel/camel-digest-store.h | 59 - camel/camel-digest-summary.c | 90 - camel/camel-digest-summary.h | 62 - camel/camel-disco-diary.c | 436 - camel/camel-disco-diary.h | 98 - camel/camel-disco-folder.c | 399 - camel/camel-disco-folder.h | 121 - camel/camel-disco-store.c | 373 - camel/camel-disco-store.h | 125 - camel/camel-exception-list.def | 37 - camel/camel-exception.c | 306 - camel/camel-exception.h | 87 - camel/camel-file-utils.c | 546 - camel/camel-file-utils.h | 63 - camel/camel-filter-driver.c | 1473 -- camel/camel-filter-driver.h | 119 - camel/camel-filter-search.c | 703 - camel/camel-filter-search.h | 54 - camel/camel-folder-search.c | 1174 - camel/camel-folder-search.h | 133 - camel/camel-folder-summary.c | 2831 --- camel/camel-folder-summary.h | 350 - camel/camel-folder-thread.c | 861 - camel/camel-folder-thread.h | 75 - camel/camel-folder.c | 2161 -- camel/camel-folder.h | 348 - camel/camel-gpg-context.c | 1794 -- camel/camel-gpg-context.h | 64 - camel/camel-html-parser.c | 807 - camel/camel-html-parser.h | 78 - camel/camel-http-stream.c | 583 - camel/camel-http-stream.h | 105 - camel/camel-i18n.h | 62 - camel/camel-iconv.c | 646 - camel/camel-iconv.h | 50 - camel/camel-index-control.c | 213 - camel/camel-index.c | 396 - camel/camel-index.h | 165 - camel/camel-internet-address.c | 551 - camel/camel-internet-address.h | 65 - camel/camel-junk-plugin.c | 75 - camel/camel-junk-plugin.h | 59 - camel/camel-lock-client.c | 321 - camel/camel-lock-client.h | 41 - camel/camel-lock-helper.c | 390 - camel/camel-lock-helper.h | 69 - camel/camel-lock.c | 425 - camel/camel-lock.h | 63 - camel/camel-medium.c | 332 - camel/camel-medium.h | 97 - camel/camel-mime-filter-basic.c | 291 - camel/camel-mime-filter-basic.h | 71 - camel/camel-mime-filter-bestenc.c | 300 - camel/camel-mime-filter-bestenc.h | 101 - camel/camel-mime-filter-canon.c | 239 - camel/camel-mime-filter-canon.h | 65 - camel/camel-mime-filter-charset.c | 277 - camel/camel-mime-filter-charset.h | 62 - camel/camel-mime-filter-crlf.c | 172 - camel/camel-mime-filter-crlf.h | 73 - camel/camel-mime-filter-enriched.c | 591 - camel/camel-mime-filter-enriched.h | 67 - camel/camel-mime-filter-from.c | 217 - camel/camel-mime-filter-from.h | 57 - camel/camel-mime-filter-html.c | 200 - camel/camel-mime-filter-html.h | 57 - camel/camel-mime-filter-index.c | 157 - camel/camel-mime-filter-index.h | 65 - camel/camel-mime-filter-linewrap.c | 147 - camel/camel-mime-filter-linewrap.h | 60 - camel/camel-mime-filter-save.c | 115 - camel/camel-mime-filter-save.h | 61 - camel/camel-mime-filter-tohtml.c | 447 - camel/camel-mime-filter-tohtml.h | 82 - camel/camel-mime-filter-windows.c | 180 - camel/camel-mime-filter-windows.h | 65 - camel/camel-mime-filter.c | 256 - camel/camel-mime-filter.h | 94 - camel/camel-mime-message.c | 963 - camel/camel-mime-message.h | 140 - camel/camel-mime-parser.c | 1982 -- camel/camel-mime-parser.h | 146 - camel/camel-mime-part-utils.c | 137 - camel/camel-mime-part-utils.h | 44 - camel/camel-mime-part.c | 912 - camel/camel-mime-part.h | 115 - camel/camel-mime-utils.c | 4346 ---- camel/camel-mime-utils.h | 273 - camel/camel-movemail.c | 542 - camel/camel-movemail.h | 44 - camel/camel-multipart-encrypted.c | 273 - camel/camel-multipart-encrypted.h | 83 - camel/camel-multipart-signed.c | 763 - camel/camel-multipart-signed.h | 108 - camel/camel-multipart.c | 589 - camel/camel-multipart.h | 104 - camel/camel-news-address.c | 65 - camel/camel-news-address.h | 56 - camel/camel-object.c | 1834 -- camel/camel-object.h | 290 - camel/camel-operation.c | 687 - camel/camel-operation.h | 74 - camel/camel-partition-table.c | 998 - camel/camel-partition-table.h | 152 - camel/camel-private.h | 168 - camel/camel-process.c | 151 - camel/camel-process.h | 44 - camel/camel-provider.c | 192 - camel/camel-provider.h | 201 - camel/camel-sasl-anonymous.c | 152 - camel/camel-sasl-anonymous.h | 70 - camel/camel-sasl-cram-md5.c | 142 - camel/camel-sasl-cram-md5.h | 59 - camel/camel-sasl-digest-md5.c | 898 - camel/camel-sasl-digest-md5.h | 62 - camel/camel-sasl-gssapi.c | 340 - camel/camel-sasl-gssapi.h | 64 - camel/camel-sasl-kerberos4.c | 224 - camel/camel-sasl-kerberos4.h | 62 - camel/camel-sasl-login.c | 134 - camel/camel-sasl-login.h | 61 - camel/camel-sasl-ntlm.c | 706 - camel/camel-sasl-ntlm.h | 57 - camel/camel-sasl-plain.c | 104 - camel/camel-sasl-plain.h | 59 - camel/camel-sasl-popb4smtp.c | 151 - camel/camel-sasl-popb4smtp.h | 59 - camel/camel-sasl.c | 285 - camel/camel-sasl.h | 78 - camel/camel-search-private.c | 684 - camel/camel-search-private.h | 82 - camel/camel-seekable-stream.c | 202 - camel/camel-seekable-stream.h | 87 - camel/camel-seekable-substream.c | 302 - camel/camel-seekable-substream.h | 68 - camel/camel-service.c | 958 - camel/camel-service.h | 155 - camel/camel-session.c | 901 - camel/camel-session.h | 217 - camel/camel-smime-context.c | 1061 - camel/camel-smime-context.h | 79 - camel/camel-store-summary.c | 928 - camel/camel-store-summary.h | 176 - camel/camel-store.c | 1228 -- camel/camel-store.h | 242 - camel/camel-stream-buffer.c | 471 - camel/camel-stream-buffer.h | 106 - camel/camel-stream-filter.c | 406 - camel/camel-stream-filter.h | 63 - camel/camel-stream-fs.c | 304 - camel/camel-stream-fs.h | 74 - camel/camel-stream-mem.c | 248 - camel/camel-stream-mem.h | 74 - camel/camel-stream-null.c | 91 - camel/camel-stream-null.h | 57 - camel/camel-stream-process.c | 273 - camel/camel-stream-process.h | 59 - camel/camel-stream.c | 281 - camel/camel-stream.h | 90 - camel/camel-string-utils.c | 110 - camel/camel-string-utils.h | 47 - camel/camel-tcp-stream-openssl.c | 954 - camel/camel-tcp-stream-raw.c | 562 - camel/camel-tcp-stream-raw.h | 64 - camel/camel-tcp-stream-ssl.c | 1211 - camel/camel-tcp-stream-ssl.h | 75 - camel/camel-tcp-stream.c | 249 - camel/camel-tcp-stream.h | 140 - camel/camel-text-index.c | 1948 -- camel/camel-text-index.h | 114 - camel/camel-transport.c | 141 - camel/camel-transport.h | 82 - camel/camel-types.h | 83 - camel/camel-uid-cache.c | 334 - camel/camel-uid-cache.h | 60 - camel/camel-url-scanner.c | 450 - camel/camel-url-scanner.h | 73 - camel/camel-url.c | 584 - camel/camel-url.h | 90 - camel/camel-utf8.c | 400 - camel/camel-utf8.h | 41 - camel/camel-vee-folder.c | 1683 -- camel/camel-vee-folder.h | 84 - camel/camel-vee-store.c | 324 - camel/camel-vee-store.h | 60 - camel/camel-vtrash-folder.c | 209 - camel/camel-vtrash-folder.h | 63 - camel/camel.c | 115 - camel/camel.h | 91 - camel/devel-docs/camel-index.txt | 407 - camel/devel-docs/camel_data_wrapper.dia | Bin 3062 -> 0 bytes camel/devel-docs/camel_parser_states.dia | Bin 2505 -> 0 bytes camel/devel-docs/camel_stream.dia | Bin 2669 -> 0 bytes camel/providers/.cvsignore | 2 - camel/providers/Makefile.am | 12 - camel/providers/imap/.cvsignore | 11 - camel/providers/imap/Makefile.am | 48 - camel/providers/imap/camel-imap-command.c | 822 - camel/providers/imap/camel-imap-command.h | 80 - camel/providers/imap/camel-imap-folder.c | 2729 --- camel/providers/imap/camel-imap-folder.h | 90 - camel/providers/imap/camel-imap-message-cache.c | 527 - camel/providers/imap/camel-imap-message-cache.h | 111 - camel/providers/imap/camel-imap-private.h | 76 - camel/providers/imap/camel-imap-provider.c | 158 - camel/providers/imap/camel-imap-search.c | 499 - camel/providers/imap/camel-imap-search.h | 62 - camel/providers/imap/camel-imap-store-summary.c | 619 - camel/providers/imap/camel-imap-store-summary.h | 102 - camel/providers/imap/camel-imap-store.c | 2845 --- camel/providers/imap/camel-imap-store.h | 148 - camel/providers/imap/camel-imap-summary.c | 255 - camel/providers/imap/camel-imap-summary.h | 79 - camel/providers/imap/camel-imap-types.h | 39 - camel/providers/imap/camel-imap-utils.c | 1261 -- camel/providers/imap/camel-imap-utils.h | 95 - camel/providers/imap/camel-imap-wrapper.c | 185 - camel/providers/imap/camel-imap-wrapper.h | 70 - camel/providers/imap/libcamelimap.urls | 1 - camel/providers/imapp/.cvsignore | 11 - camel/providers/imapp/Makefile.am | 45 - camel/providers/imapp/camel-imapp-driver.c | 771 - camel/providers/imapp/camel-imapp-driver.h | 81 - camel/providers/imapp/camel-imapp-engine.c | 1180 - camel/providers/imapp/camel-imapp-engine.h | 155 - camel/providers/imapp/camel-imapp-exception.h | 35 - camel/providers/imapp/camel-imapp-fetch-stream.c | 183 - camel/providers/imapp/camel-imapp-fetch-stream.h | 47 - camel/providers/imapp/camel-imapp-folder.c | 269 - camel/providers/imapp/camel-imapp-folder.h | 66 - camel/providers/imapp/camel-imapp-provider.c | 97 - camel/providers/imapp/camel-imapp-store-summary.c | 616 - camel/providers/imapp/camel-imapp-store-summary.h | 102 - camel/providers/imapp/camel-imapp-store.c | 1006 - camel/providers/imapp/camel-imapp-store.h | 77 - camel/providers/imapp/camel-imapp-stream.c | 761 - camel/providers/imapp/camel-imapp-stream.h | 90 - camel/providers/imapp/camel-imapp-summary.c | 166 - camel/providers/imapp/camel-imapp-summary.h | 65 - camel/providers/imapp/camel-imapp-utils.c | 1339 -- camel/providers/imapp/camel-imapp-utils.h | 145 - camel/providers/imapp/libcamelimapp.urls | 1 - camel/providers/local/.cvsignore | 11 - camel/providers/local/Makefile.am | 61 - camel/providers/local/camel-local-folder.c | 646 - camel/providers/local/camel-local-folder.h | 109 - camel/providers/local/camel-local-private.h | 53 - camel/providers/local/camel-local-provider.c | 222 - camel/providers/local/camel-local-store.c | 442 - camel/providers/local/camel-local-store.h | 68 - camel/providers/local/camel-local-summary.c | 614 - camel/providers/local/camel-local-summary.h | 88 - camel/providers/local/camel-maildir-folder.c | 245 - camel/providers/local/camel-maildir-folder.h | 58 - camel/providers/local/camel-maildir-store.c | 416 - camel/providers/local/camel-maildir-store.h | 55 - camel/providers/local/camel-maildir-summary.c | 807 - camel/providers/local/camel-maildir-summary.h | 84 - camel/providers/local/camel-mbox-folder.c | 549 - camel/providers/local/camel-mbox-folder.h | 62 - camel/providers/local/camel-mbox-store.c | 753 - camel/providers/local/camel-mbox-store.h | 58 - camel/providers/local/camel-mbox-summary.c | 1029 - camel/providers/local/camel-mbox-summary.h | 75 - camel/providers/local/camel-mh-folder.c | 231 - camel/providers/local/camel-mh-folder.h | 58 - camel/providers/local/camel-mh-store.c | 533 - camel/providers/local/camel-mh-store.h | 60 - camel/providers/local/camel-mh-summary.c | 420 - camel/providers/local/camel-mh-summary.h | 53 - camel/providers/local/camel-spool-folder.c | 186 - camel/providers/local/camel-spool-folder.h | 64 - camel/providers/local/camel-spool-store.c | 483 - camel/providers/local/camel-spool-store.h | 69 - camel/providers/local/camel-spool-summary.c | 344 - camel/providers/local/camel-spool-summary.h | 69 - camel/providers/local/libcamellocal.urls | 5 - camel/providers/nntp/.cvsignore | 12 - camel/providers/nntp/Makefile.am | 36 - camel/providers/nntp/camel-nntp-auth.c | 92 - camel/providers/nntp/camel-nntp-auth.h | 42 - camel/providers/nntp/camel-nntp-folder.c | 405 - camel/providers/nntp/camel-nntp-folder.h | 72 - camel/providers/nntp/camel-nntp-grouplist.c | 219 - camel/providers/nntp/camel-nntp-grouplist.h | 48 - camel/providers/nntp/camel-nntp-newsrc.c | 651 - camel/providers/nntp/camel-nntp-newsrc.h | 34 - camel/providers/nntp/camel-nntp-private.h | 64 - camel/providers/nntp/camel-nntp-provider.c | 113 - camel/providers/nntp/camel-nntp-resp-codes.h | 55 - camel/providers/nntp/camel-nntp-store.c | 576 - camel/providers/nntp/camel-nntp-store.h | 92 - camel/providers/nntp/camel-nntp-stream.c | 462 - camel/providers/nntp/camel-nntp-stream.h | 66 - camel/providers/nntp/camel-nntp-summary.c | 584 - camel/providers/nntp/camel-nntp-summary.h | 67 - camel/providers/nntp/camel-nntp-types.h | 33 - camel/providers/nntp/camel-nntp-utils.c | 299 - camel/providers/nntp/camel-nntp-utils.h | 41 - camel/providers/nntp/libcamelnntp.urls | 2 - camel/providers/nntp/test-newsrc.c | 10 - camel/providers/pop3/.cvsignore | 10 - camel/providers/pop3/Makefile.am | 38 - camel/providers/pop3/camel-pop3-engine.c | 382 - camel/providers/pop3/camel-pop3-engine.h | 134 - camel/providers/pop3/camel-pop3-folder.c | 558 - camel/providers/pop3/camel-pop3-folder.h | 77 - camel/providers/pop3/camel-pop3-provider.c | 108 - camel/providers/pop3/camel-pop3-store.c | 657 - camel/providers/pop3/camel-pop3-store.h | 79 - camel/providers/pop3/camel-pop3-stream.c | 471 - camel/providers/pop3/camel-pop3-stream.h | 69 - camel/providers/pop3/libcamelpop3.urls | 1 - camel/providers/sendmail/.cvsignore | 11 - camel/providers/sendmail/Makefile.am | 28 - camel/providers/sendmail/camel-sendmail-provider.c | 63 - .../providers/sendmail/camel-sendmail-transport.c | 262 - .../providers/sendmail/camel-sendmail-transport.h | 63 - camel/providers/sendmail/libcamelsendmail.urls | 1 - camel/providers/smtp/.cvsignore | 10 - camel/providers/smtp/Makefile.am | 35 - camel/providers/smtp/camel-smtp-provider.c | 65 - camel/providers/smtp/camel-smtp-transport.c | 1455 -- camel/providers/smtp/camel-smtp-transport.h | 89 - camel/providers/smtp/libcamelsmtp.urls | 1 - camel/tests/.cvsignore | 7 - camel/tests/Makefile.am | 3 - camel/tests/README | 44 - camel/tests/data/camel-test.gpg.pub | 24 - camel/tests/data/camel-test.gpg.sec | 33 - camel/tests/data/gendoc.pl | 65 - camel/tests/data/genline.pl | 72 - camel/tests/data/getaddr.pl | 32 - camel/tests/data/messages/.cvsignore | 1 - camel/tests/folder/.cvsignore | 21 - camel/tests/folder/Makefile.am | 28 - camel/tests/folder/README | 12 - camel/tests/folder/test1.c | 50 - camel/tests/folder/test10.c | 103 - camel/tests/folder/test2.c | 58 - camel/tests/folder/test3.c | 339 - camel/tests/folder/test4.c | 53 - camel/tests/folder/test5.c | 53 - camel/tests/folder/test6.c | 56 - camel/tests/folder/test7.c | 55 - camel/tests/folder/test8.c | 205 - camel/tests/folder/test9.c | 229 - camel/tests/lib/.cvsignore | 12 - camel/tests/lib/Makefile.am | 22 - camel/tests/lib/address-data.h | 93 - camel/tests/lib/addresses.c | 54 - camel/tests/lib/addresses.h | 5 - camel/tests/lib/camel-test.c | 355 - camel/tests/lib/camel-test.h | 68 - camel/tests/lib/folders.c | 568 - camel/tests/lib/folders.h | 20 - camel/tests/lib/messages.c | 290 - camel/tests/lib/messages.h | 15 - camel/tests/lib/session.c | 44 - camel/tests/lib/session.h | 19 - camel/tests/lib/streams.c | 244 - camel/tests/lib/streams.h | 12 - camel/tests/message/.cvsignore | 15 - camel/tests/message/Makefile.am | 25 - camel/tests/message/README | 9 - camel/tests/message/test1.c | 201 - camel/tests/message/test2.c | 326 - camel/tests/message/test3.c | 199 - camel/tests/message/test4.c | 129 - camel/tests/mime-filter/.cvsignore | 8 - camel/tests/mime-filter/Makefile.am | 36 - camel/tests/mime-filter/charset-gb2312.0.in | 448 - camel/tests/mime-filter/charset-gb2312.0.out | 448 - camel/tests/mime-filter/charset-iso-2022-jp.0.in | 5 - camel/tests/mime-filter/charset-iso-2022-jp.0.out | 5 - camel/tests/mime-filter/crlf-1.in | 19 - camel/tests/mime-filter/crlf-1.out | 19 - camel/tests/mime-filter/data/html.0.in | 10 - camel/tests/mime-filter/data/html.0.out | 10 - camel/tests/mime-filter/data/html.1.in | 10 - camel/tests/mime-filter/data/html.1.out | 10 - camel/tests/mime-filter/test-charset.c | 140 - camel/tests/mime-filter/test-crlf.c | 160 - camel/tests/mime-filter/test-tohtml.c | 132 - camel/tests/misc/.cvsignore | 14 - camel/tests/misc/Makefile.am | 27 - camel/tests/misc/README | 4 - camel/tests/misc/split.c | 113 - camel/tests/misc/url.c | 123 - camel/tests/misc/utf7.c | 106 - camel/tests/smime/.cvsignore | 5 - camel/tests/smime/Makefile.am | 24 - camel/tests/smime/README | 2 - camel/tests/smime/pgp-mime.c | 214 - camel/tests/smime/pgp.c | 246 - camel/tests/smime/pkcs7.c | 178 - camel/tests/stream/.cvsignore | 14 - camel/tests/stream/Makefile.am | 25 - camel/tests/stream/README | 4 - camel/tests/stream/test1.c | 119 - camel/tests/stream/test2.c | 53 - camel/tests/stream/test3.c | 104 - 433 files changed, 140229 deletions(-) delete mode 100644 camel/.cvsignore delete mode 100644 camel/CODING.STYLE delete mode 100644 camel/ChangeLog delete mode 100644 camel/ChangeLog.pre-1-4 delete mode 100644 camel/Makefile.am delete mode 100644 camel/README delete mode 100644 camel/README.COPYRIGHT delete mode 100644 camel/README.HACKING delete mode 100644 camel/README.mt delete mode 100644 camel/broken-date-parser.c delete mode 100644 camel/broken-date-parser.h delete mode 100644 camel/camel-address.c delete mode 100644 camel/camel-address.h delete mode 100644 camel/camel-arg.c delete mode 100644 camel/camel-arg.h delete mode 100644 camel/camel-block-file.c delete mode 100644 camel/camel-block-file.h delete mode 100644 camel/camel-certdb.c delete mode 100644 camel/camel-certdb.h delete mode 100644 camel/camel-charset-map-private.h delete mode 100644 camel/camel-charset-map.c delete mode 100644 camel/camel-charset-map.h delete mode 100644 camel/camel-cipher-context.c delete mode 100644 camel/camel-cipher-context.h delete mode 100644 camel/camel-data-cache.c delete mode 100644 camel/camel-data-cache.h delete mode 100644 camel/camel-data-wrapper.c delete mode 100644 camel/camel-data-wrapper.h delete mode 100644 camel/camel-digest-folder.c delete mode 100644 camel/camel-digest-folder.h delete mode 100644 camel/camel-digest-store.c delete mode 100644 camel/camel-digest-store.h delete mode 100644 camel/camel-digest-summary.c delete mode 100644 camel/camel-digest-summary.h delete mode 100644 camel/camel-disco-diary.c delete mode 100644 camel/camel-disco-diary.h delete mode 100644 camel/camel-disco-folder.c delete mode 100644 camel/camel-disco-folder.h delete mode 100644 camel/camel-disco-store.c delete mode 100644 camel/camel-disco-store.h delete mode 100644 camel/camel-exception-list.def delete mode 100644 camel/camel-exception.c delete mode 100644 camel/camel-exception.h delete mode 100644 camel/camel-file-utils.c delete mode 100644 camel/camel-file-utils.h delete mode 100644 camel/camel-filter-driver.c delete mode 100644 camel/camel-filter-driver.h delete mode 100644 camel/camel-filter-search.c delete mode 100644 camel/camel-filter-search.h delete mode 100644 camel/camel-folder-search.c delete mode 100644 camel/camel-folder-search.h delete mode 100644 camel/camel-folder-summary.c delete mode 100644 camel/camel-folder-summary.h delete mode 100644 camel/camel-folder-thread.c delete mode 100644 camel/camel-folder-thread.h delete mode 100644 camel/camel-folder.c delete mode 100644 camel/camel-folder.h delete mode 100644 camel/camel-gpg-context.c delete mode 100644 camel/camel-gpg-context.h delete mode 100644 camel/camel-html-parser.c delete mode 100644 camel/camel-html-parser.h delete mode 100644 camel/camel-http-stream.c delete mode 100644 camel/camel-http-stream.h delete mode 100644 camel/camel-i18n.h delete mode 100644 camel/camel-iconv.c delete mode 100644 camel/camel-iconv.h delete mode 100644 camel/camel-index-control.c delete mode 100644 camel/camel-index.c delete mode 100644 camel/camel-index.h delete mode 100644 camel/camel-internet-address.c delete mode 100644 camel/camel-internet-address.h delete mode 100644 camel/camel-junk-plugin.c delete mode 100644 camel/camel-junk-plugin.h delete mode 100644 camel/camel-lock-client.c delete mode 100644 camel/camel-lock-client.h delete mode 100644 camel/camel-lock-helper.c delete mode 100644 camel/camel-lock-helper.h delete mode 100644 camel/camel-lock.c delete mode 100644 camel/camel-lock.h delete mode 100644 camel/camel-medium.c delete mode 100644 camel/camel-medium.h delete mode 100644 camel/camel-mime-filter-basic.c delete mode 100644 camel/camel-mime-filter-basic.h delete mode 100644 camel/camel-mime-filter-bestenc.c delete mode 100644 camel/camel-mime-filter-bestenc.h delete mode 100644 camel/camel-mime-filter-canon.c delete mode 100644 camel/camel-mime-filter-canon.h delete mode 100644 camel/camel-mime-filter-charset.c delete mode 100644 camel/camel-mime-filter-charset.h delete mode 100644 camel/camel-mime-filter-crlf.c delete mode 100644 camel/camel-mime-filter-crlf.h delete mode 100644 camel/camel-mime-filter-enriched.c delete mode 100644 camel/camel-mime-filter-enriched.h delete mode 100644 camel/camel-mime-filter-from.c delete mode 100644 camel/camel-mime-filter-from.h delete mode 100644 camel/camel-mime-filter-html.c delete mode 100644 camel/camel-mime-filter-html.h delete mode 100644 camel/camel-mime-filter-index.c delete mode 100644 camel/camel-mime-filter-index.h delete mode 100644 camel/camel-mime-filter-linewrap.c delete mode 100644 camel/camel-mime-filter-linewrap.h delete mode 100644 camel/camel-mime-filter-save.c delete mode 100644 camel/camel-mime-filter-save.h delete mode 100644 camel/camel-mime-filter-tohtml.c delete mode 100644 camel/camel-mime-filter-tohtml.h delete mode 100644 camel/camel-mime-filter-windows.c delete mode 100644 camel/camel-mime-filter-windows.h delete mode 100644 camel/camel-mime-filter.c delete mode 100644 camel/camel-mime-filter.h delete mode 100644 camel/camel-mime-message.c delete mode 100644 camel/camel-mime-message.h delete mode 100644 camel/camel-mime-parser.c delete mode 100644 camel/camel-mime-parser.h delete mode 100644 camel/camel-mime-part-utils.c delete mode 100644 camel/camel-mime-part-utils.h delete mode 100644 camel/camel-mime-part.c delete mode 100644 camel/camel-mime-part.h delete mode 100644 camel/camel-mime-utils.c delete mode 100644 camel/camel-mime-utils.h delete mode 100644 camel/camel-movemail.c delete mode 100644 camel/camel-movemail.h delete mode 100644 camel/camel-multipart-encrypted.c delete mode 100644 camel/camel-multipart-encrypted.h delete mode 100644 camel/camel-multipart-signed.c delete mode 100644 camel/camel-multipart-signed.h delete mode 100644 camel/camel-multipart.c delete mode 100644 camel/camel-multipart.h delete mode 100644 camel/camel-news-address.c delete mode 100644 camel/camel-news-address.h delete mode 100644 camel/camel-object.c delete mode 100644 camel/camel-object.h delete mode 100644 camel/camel-operation.c delete mode 100644 camel/camel-operation.h delete mode 100644 camel/camel-partition-table.c delete mode 100644 camel/camel-partition-table.h delete mode 100644 camel/camel-private.h delete mode 100644 camel/camel-process.c delete mode 100644 camel/camel-process.h delete mode 100644 camel/camel-provider.c delete mode 100644 camel/camel-provider.h delete mode 100644 camel/camel-sasl-anonymous.c delete mode 100644 camel/camel-sasl-anonymous.h delete mode 100644 camel/camel-sasl-cram-md5.c delete mode 100644 camel/camel-sasl-cram-md5.h delete mode 100644 camel/camel-sasl-digest-md5.c delete mode 100644 camel/camel-sasl-digest-md5.h delete mode 100644 camel/camel-sasl-gssapi.c delete mode 100644 camel/camel-sasl-gssapi.h delete mode 100644 camel/camel-sasl-kerberos4.c delete mode 100644 camel/camel-sasl-kerberos4.h delete mode 100644 camel/camel-sasl-login.c delete mode 100644 camel/camel-sasl-login.h delete mode 100644 camel/camel-sasl-ntlm.c delete mode 100644 camel/camel-sasl-ntlm.h delete mode 100644 camel/camel-sasl-plain.c delete mode 100644 camel/camel-sasl-plain.h delete mode 100644 camel/camel-sasl-popb4smtp.c delete mode 100644 camel/camel-sasl-popb4smtp.h delete mode 100644 camel/camel-sasl.c delete mode 100644 camel/camel-sasl.h delete mode 100644 camel/camel-search-private.c delete mode 100644 camel/camel-search-private.h delete mode 100644 camel/camel-seekable-stream.c delete mode 100644 camel/camel-seekable-stream.h delete mode 100644 camel/camel-seekable-substream.c delete mode 100644 camel/camel-seekable-substream.h delete mode 100644 camel/camel-service.c delete mode 100644 camel/camel-service.h delete mode 100644 camel/camel-session.c delete mode 100644 camel/camel-session.h delete mode 100644 camel/camel-smime-context.c delete mode 100644 camel/camel-smime-context.h delete mode 100644 camel/camel-store-summary.c delete mode 100644 camel/camel-store-summary.h delete mode 100644 camel/camel-store.c delete mode 100644 camel/camel-store.h delete mode 100644 camel/camel-stream-buffer.c delete mode 100644 camel/camel-stream-buffer.h delete mode 100644 camel/camel-stream-filter.c delete mode 100644 camel/camel-stream-filter.h delete mode 100644 camel/camel-stream-fs.c delete mode 100644 camel/camel-stream-fs.h delete mode 100644 camel/camel-stream-mem.c delete mode 100644 camel/camel-stream-mem.h delete mode 100644 camel/camel-stream-null.c delete mode 100644 camel/camel-stream-null.h delete mode 100644 camel/camel-stream-process.c delete mode 100644 camel/camel-stream-process.h delete mode 100644 camel/camel-stream.c delete mode 100644 camel/camel-stream.h delete mode 100644 camel/camel-string-utils.c delete mode 100644 camel/camel-string-utils.h delete mode 100644 camel/camel-tcp-stream-openssl.c delete mode 100644 camel/camel-tcp-stream-raw.c delete mode 100644 camel/camel-tcp-stream-raw.h delete mode 100644 camel/camel-tcp-stream-ssl.c delete mode 100644 camel/camel-tcp-stream-ssl.h delete mode 100644 camel/camel-tcp-stream.c delete mode 100644 camel/camel-tcp-stream.h delete mode 100644 camel/camel-text-index.c delete mode 100644 camel/camel-text-index.h delete mode 100644 camel/camel-transport.c delete mode 100644 camel/camel-transport.h delete mode 100644 camel/camel-types.h delete mode 100644 camel/camel-uid-cache.c delete mode 100644 camel/camel-uid-cache.h delete mode 100644 camel/camel-url-scanner.c delete mode 100644 camel/camel-url-scanner.h delete mode 100644 camel/camel-url.c delete mode 100644 camel/camel-url.h delete mode 100644 camel/camel-utf8.c delete mode 100644 camel/camel-utf8.h delete mode 100644 camel/camel-vee-folder.c delete mode 100644 camel/camel-vee-folder.h delete mode 100644 camel/camel-vee-store.c delete mode 100644 camel/camel-vee-store.h delete mode 100644 camel/camel-vtrash-folder.c delete mode 100644 camel/camel-vtrash-folder.h delete mode 100644 camel/camel.c delete mode 100644 camel/camel.h delete mode 100644 camel/devel-docs/camel-index.txt delete mode 100644 camel/devel-docs/camel_data_wrapper.dia delete mode 100644 camel/devel-docs/camel_parser_states.dia delete mode 100644 camel/devel-docs/camel_stream.dia delete mode 100644 camel/providers/.cvsignore delete mode 100644 camel/providers/Makefile.am delete mode 100644 camel/providers/imap/.cvsignore delete mode 100644 camel/providers/imap/Makefile.am delete mode 100644 camel/providers/imap/camel-imap-command.c delete mode 100644 camel/providers/imap/camel-imap-command.h delete mode 100644 camel/providers/imap/camel-imap-folder.c delete mode 100644 camel/providers/imap/camel-imap-folder.h delete mode 100644 camel/providers/imap/camel-imap-message-cache.c delete mode 100644 camel/providers/imap/camel-imap-message-cache.h delete mode 100644 camel/providers/imap/camel-imap-private.h delete mode 100644 camel/providers/imap/camel-imap-provider.c delete mode 100644 camel/providers/imap/camel-imap-search.c delete mode 100644 camel/providers/imap/camel-imap-search.h delete mode 100644 camel/providers/imap/camel-imap-store-summary.c delete mode 100644 camel/providers/imap/camel-imap-store-summary.h delete mode 100644 camel/providers/imap/camel-imap-store.c delete mode 100644 camel/providers/imap/camel-imap-store.h delete mode 100644 camel/providers/imap/camel-imap-summary.c delete mode 100644 camel/providers/imap/camel-imap-summary.h delete mode 100644 camel/providers/imap/camel-imap-types.h delete mode 100644 camel/providers/imap/camel-imap-utils.c delete mode 100644 camel/providers/imap/camel-imap-utils.h delete mode 100644 camel/providers/imap/camel-imap-wrapper.c delete mode 100644 camel/providers/imap/camel-imap-wrapper.h delete mode 100644 camel/providers/imap/libcamelimap.urls delete mode 100644 camel/providers/imapp/.cvsignore delete mode 100644 camel/providers/imapp/Makefile.am delete mode 100644 camel/providers/imapp/camel-imapp-driver.c delete mode 100644 camel/providers/imapp/camel-imapp-driver.h delete mode 100644 camel/providers/imapp/camel-imapp-engine.c delete mode 100644 camel/providers/imapp/camel-imapp-engine.h delete mode 100644 camel/providers/imapp/camel-imapp-exception.h delete mode 100644 camel/providers/imapp/camel-imapp-fetch-stream.c delete mode 100644 camel/providers/imapp/camel-imapp-fetch-stream.h delete mode 100644 camel/providers/imapp/camel-imapp-folder.c delete mode 100644 camel/providers/imapp/camel-imapp-folder.h delete mode 100644 camel/providers/imapp/camel-imapp-provider.c delete mode 100644 camel/providers/imapp/camel-imapp-store-summary.c delete mode 100644 camel/providers/imapp/camel-imapp-store-summary.h delete mode 100644 camel/providers/imapp/camel-imapp-store.c delete mode 100644 camel/providers/imapp/camel-imapp-store.h delete mode 100644 camel/providers/imapp/camel-imapp-stream.c delete mode 100644 camel/providers/imapp/camel-imapp-stream.h delete mode 100644 camel/providers/imapp/camel-imapp-summary.c delete mode 100644 camel/providers/imapp/camel-imapp-summary.h delete mode 100644 camel/providers/imapp/camel-imapp-utils.c delete mode 100644 camel/providers/imapp/camel-imapp-utils.h delete mode 100644 camel/providers/imapp/libcamelimapp.urls delete mode 100644 camel/providers/local/.cvsignore delete mode 100644 camel/providers/local/Makefile.am delete mode 100644 camel/providers/local/camel-local-folder.c delete mode 100644 camel/providers/local/camel-local-folder.h delete mode 100644 camel/providers/local/camel-local-private.h delete mode 100644 camel/providers/local/camel-local-provider.c delete mode 100644 camel/providers/local/camel-local-store.c delete mode 100644 camel/providers/local/camel-local-store.h delete mode 100644 camel/providers/local/camel-local-summary.c delete mode 100644 camel/providers/local/camel-local-summary.h delete mode 100644 camel/providers/local/camel-maildir-folder.c delete mode 100644 camel/providers/local/camel-maildir-folder.h delete mode 100644 camel/providers/local/camel-maildir-store.c delete mode 100644 camel/providers/local/camel-maildir-store.h delete mode 100644 camel/providers/local/camel-maildir-summary.c delete mode 100644 camel/providers/local/camel-maildir-summary.h delete mode 100644 camel/providers/local/camel-mbox-folder.c delete mode 100644 camel/providers/local/camel-mbox-folder.h delete mode 100644 camel/providers/local/camel-mbox-store.c delete mode 100644 camel/providers/local/camel-mbox-store.h delete mode 100644 camel/providers/local/camel-mbox-summary.c delete mode 100644 camel/providers/local/camel-mbox-summary.h delete mode 100644 camel/providers/local/camel-mh-folder.c delete mode 100644 camel/providers/local/camel-mh-folder.h delete mode 100644 camel/providers/local/camel-mh-store.c delete mode 100644 camel/providers/local/camel-mh-store.h delete mode 100644 camel/providers/local/camel-mh-summary.c delete mode 100644 camel/providers/local/camel-mh-summary.h delete mode 100644 camel/providers/local/camel-spool-folder.c delete mode 100644 camel/providers/local/camel-spool-folder.h delete mode 100644 camel/providers/local/camel-spool-store.c delete mode 100644 camel/providers/local/camel-spool-store.h delete mode 100644 camel/providers/local/camel-spool-summary.c delete mode 100644 camel/providers/local/camel-spool-summary.h delete mode 100644 camel/providers/local/libcamellocal.urls delete mode 100644 camel/providers/nntp/.cvsignore delete mode 100644 camel/providers/nntp/Makefile.am delete mode 100644 camel/providers/nntp/camel-nntp-auth.c delete mode 100644 camel/providers/nntp/camel-nntp-auth.h delete mode 100644 camel/providers/nntp/camel-nntp-folder.c delete mode 100644 camel/providers/nntp/camel-nntp-folder.h delete mode 100644 camel/providers/nntp/camel-nntp-grouplist.c delete mode 100644 camel/providers/nntp/camel-nntp-grouplist.h delete mode 100644 camel/providers/nntp/camel-nntp-newsrc.c delete mode 100644 camel/providers/nntp/camel-nntp-newsrc.h delete mode 100644 camel/providers/nntp/camel-nntp-private.h delete mode 100644 camel/providers/nntp/camel-nntp-provider.c delete mode 100644 camel/providers/nntp/camel-nntp-resp-codes.h delete mode 100644 camel/providers/nntp/camel-nntp-store.c delete mode 100644 camel/providers/nntp/camel-nntp-store.h delete mode 100644 camel/providers/nntp/camel-nntp-stream.c delete mode 100644 camel/providers/nntp/camel-nntp-stream.h delete mode 100644 camel/providers/nntp/camel-nntp-summary.c delete mode 100644 camel/providers/nntp/camel-nntp-summary.h delete mode 100644 camel/providers/nntp/camel-nntp-types.h delete mode 100644 camel/providers/nntp/camel-nntp-utils.c delete mode 100644 camel/providers/nntp/camel-nntp-utils.h delete mode 100644 camel/providers/nntp/libcamelnntp.urls delete mode 100644 camel/providers/nntp/test-newsrc.c delete mode 100644 camel/providers/pop3/.cvsignore delete mode 100644 camel/providers/pop3/Makefile.am delete mode 100644 camel/providers/pop3/camel-pop3-engine.c delete mode 100644 camel/providers/pop3/camel-pop3-engine.h delete mode 100644 camel/providers/pop3/camel-pop3-folder.c delete mode 100644 camel/providers/pop3/camel-pop3-folder.h delete mode 100644 camel/providers/pop3/camel-pop3-provider.c delete mode 100644 camel/providers/pop3/camel-pop3-store.c delete mode 100644 camel/providers/pop3/camel-pop3-store.h delete mode 100644 camel/providers/pop3/camel-pop3-stream.c delete mode 100644 camel/providers/pop3/camel-pop3-stream.h delete mode 100644 camel/providers/pop3/libcamelpop3.urls delete mode 100644 camel/providers/sendmail/.cvsignore delete mode 100644 camel/providers/sendmail/Makefile.am delete mode 100644 camel/providers/sendmail/camel-sendmail-provider.c delete mode 100644 camel/providers/sendmail/camel-sendmail-transport.c delete mode 100644 camel/providers/sendmail/camel-sendmail-transport.h delete mode 100644 camel/providers/sendmail/libcamelsendmail.urls delete mode 100644 camel/providers/smtp/.cvsignore delete mode 100644 camel/providers/smtp/Makefile.am delete mode 100644 camel/providers/smtp/camel-smtp-provider.c delete mode 100644 camel/providers/smtp/camel-smtp-transport.c delete mode 100644 camel/providers/smtp/camel-smtp-transport.h delete mode 100644 camel/providers/smtp/libcamelsmtp.urls delete mode 100644 camel/tests/.cvsignore delete mode 100644 camel/tests/Makefile.am delete mode 100644 camel/tests/README delete mode 100644 camel/tests/data/camel-test.gpg.pub delete mode 100644 camel/tests/data/camel-test.gpg.sec delete mode 100755 camel/tests/data/gendoc.pl delete mode 100755 camel/tests/data/genline.pl delete mode 100755 camel/tests/data/getaddr.pl delete mode 100644 camel/tests/data/messages/.cvsignore delete mode 100644 camel/tests/folder/.cvsignore delete mode 100644 camel/tests/folder/Makefile.am delete mode 100644 camel/tests/folder/README delete mode 100644 camel/tests/folder/test1.c delete mode 100644 camel/tests/folder/test10.c delete mode 100644 camel/tests/folder/test2.c delete mode 100644 camel/tests/folder/test3.c delete mode 100644 camel/tests/folder/test4.c delete mode 100644 camel/tests/folder/test5.c delete mode 100644 camel/tests/folder/test6.c delete mode 100644 camel/tests/folder/test7.c delete mode 100644 camel/tests/folder/test8.c delete mode 100644 camel/tests/folder/test9.c delete mode 100644 camel/tests/lib/.cvsignore delete mode 100644 camel/tests/lib/Makefile.am delete mode 100644 camel/tests/lib/address-data.h delete mode 100644 camel/tests/lib/addresses.c delete mode 100644 camel/tests/lib/addresses.h delete mode 100644 camel/tests/lib/camel-test.c delete mode 100644 camel/tests/lib/camel-test.h delete mode 100644 camel/tests/lib/folders.c delete mode 100644 camel/tests/lib/folders.h delete mode 100644 camel/tests/lib/messages.c delete mode 100644 camel/tests/lib/messages.h delete mode 100644 camel/tests/lib/session.c delete mode 100644 camel/tests/lib/session.h delete mode 100644 camel/tests/lib/streams.c delete mode 100644 camel/tests/lib/streams.h delete mode 100644 camel/tests/message/.cvsignore delete mode 100644 camel/tests/message/Makefile.am delete mode 100644 camel/tests/message/README delete mode 100644 camel/tests/message/test1.c delete mode 100644 camel/tests/message/test2.c delete mode 100644 camel/tests/message/test3.c delete mode 100644 camel/tests/message/test4.c delete mode 100644 camel/tests/mime-filter/.cvsignore delete mode 100644 camel/tests/mime-filter/Makefile.am delete mode 100644 camel/tests/mime-filter/charset-gb2312.0.in delete mode 100644 camel/tests/mime-filter/charset-gb2312.0.out delete mode 100644 camel/tests/mime-filter/charset-iso-2022-jp.0.in delete mode 100644 camel/tests/mime-filter/charset-iso-2022-jp.0.out delete mode 100644 camel/tests/mime-filter/crlf-1.in delete mode 100644 camel/tests/mime-filter/crlf-1.out delete mode 100644 camel/tests/mime-filter/data/html.0.in delete mode 100644 camel/tests/mime-filter/data/html.0.out delete mode 100644 camel/tests/mime-filter/data/html.1.in delete mode 100644 camel/tests/mime-filter/data/html.1.out delete mode 100644 camel/tests/mime-filter/test-charset.c delete mode 100644 camel/tests/mime-filter/test-crlf.c delete mode 100644 camel/tests/mime-filter/test-tohtml.c delete mode 100644 camel/tests/misc/.cvsignore delete mode 100644 camel/tests/misc/Makefile.am delete mode 100644 camel/tests/misc/README delete mode 100644 camel/tests/misc/split.c delete mode 100644 camel/tests/misc/url.c delete mode 100644 camel/tests/misc/utf7.c delete mode 100644 camel/tests/smime/.cvsignore delete mode 100644 camel/tests/smime/Makefile.am delete mode 100644 camel/tests/smime/README delete mode 100644 camel/tests/smime/pgp-mime.c delete mode 100644 camel/tests/smime/pgp.c delete mode 100644 camel/tests/smime/pkcs7.c delete mode 100644 camel/tests/stream/.cvsignore delete mode 100644 camel/tests/stream/Makefile.am delete mode 100644 camel/tests/stream/README delete mode 100644 camel/tests/stream/test1.c delete mode 100644 camel/tests/stream/test2.c delete mode 100644 camel/tests/stream/test3.c (limited to 'camel') diff --git a/camel/.cvsignore b/camel/.cvsignore deleted file mode 100644 index 094641c7a6..0000000000 --- a/camel/.cvsignore +++ /dev/null @@ -1,13 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov -camel-lock-helper -camel-index-control \ No newline at end of file diff --git a/camel/CODING.STYLE b/camel/CODING.STYLE deleted file mode 100644 index 58e9c68bbe..0000000000 --- a/camel/CODING.STYLE +++ /dev/null @@ -1,19 +0,0 @@ -Note to hackers ---------------- - -When hacking on camel (and on the gnome mailer in general), -be sure to follow the same coding style as the initial authors. -Please read the file HACKING in gnumeric and follow the -general guidelines explained in it. - -Please take a look at camel source files and try to exactly -imitate the coding style. We are perfectly aware that this -is not the best and unique style, but it is absolutely -mandatory that Camel is homogeneous. If you find the current -coding style to have some weaknesses, please contact the -authors to discuss this matter. - -Thanks. - - Bertrand. - diff --git a/camel/ChangeLog b/camel/ChangeLog deleted file mode 100644 index 94ffcdc39b..0000000000 --- a/camel/ChangeLog +++ /dev/null @@ -1,1488 +0,0 @@ -2003-12-08 Jeffrey Stedfast - - * camel-mime-utils.c (header_decode_rfc2184_param): Revert the - s/is_/camel_mime_is_/ changes or we get really long variable - names. - (header_decode_param): Same. - (header_decode_param_list): Here too. - -2003-12-09 Not Zed - - * providers/smtp/camel-smtp-transport.c (smtp_send_to): encode the - address before sending it out, rather than using the raw/utf8 - version. - - * camel-internet-address.c - (camel_internet_address_encode_address): check for quoting the - local part of the address before outputting it. - (cia_encode_addrspec): quote local part if need be. - (camel_internet_address_encode_address): make folding optional - based on whether inlen is null or not. - - * camel-mime-utils.[ch]: rename is_* to camel_mime_is_* and export - the type functions. - -2003-12-08 Not Zed - - * providers/imap/camel-imap-utils.c (imap_atom_specials): add } to - the atom specials list. This isn't correct, but some busted - servers expect it. Bug #50728. - -2003-12-08 Jeffrey Stedfast - - Fixes bug #51881 - - * providers/local/camel-mbox-store.c (delete_folder): Same. - - * providers/local/camel-local-store.c (delete_folder): Unlink the - cmeta file too. - -2003-12-06 JP Rosevear - - * */Makefile.am: Remove hard coded disable deprecated flags - -2003-12-05 Jeffrey Stedfast - - * camel-gpg-context.c (gpg_ctx_op_start): Properly set the - O_NONBLOCK flag along with any previously set flags. - - * camel-filter-search.c (run_command): Don't set O_NONBLOCK on the - pipe (1. we don't need to, and 2. we should have been setting - O_NONBLOCK|prev_flags but we weren't, and so the pipe got - O_RDONLY|O_NONBLOCK even tho we wanted to write to it). - - * camel-filter-driver.c (pipe_to_system): Same. - -2003-12-04 Radek Doulik - - * camel-folder.c (folder_changed): check recent messages for junk - mail - - * camel-session.c (camel_session_check_junk): new wrapper method - for check_junk flag - (camel_session_set_check_junk): ditto - - * camel-session.h (struct _CamelSession): added check_junk flag - (if to check incoming mail for junk messages) - -2003-12-03 Jeffrey Stedfast - - * camel-store.c (add_special_info): Free fi->path if we are gonna - replace it with the vinfo path. - - * providers/local/camel-mbox-store.c (create_folder): Treat - parent_name == NULL and parent_name == "" the same. - - * camel-store.c (camel_store_get_folder_info): Only add - vTrash/vJunk info's if we've requested the toplevel folder tree, - otherwise we get vTrash/vJunk folders in odd places in the folder - tree. - (add_special_info): Use the provider->url_flags to determine if - the url uses the fragment or not for the path. - -2003-12-02 Not Zed - - * providers/local/camel-local-folder.c (local_setv): remove some - debug printfs. - - ** See bug #51576. - - * camel-url.c (camel_url_decode): robustify url decoding for bad - input, addresses a crash. - - ** See bug #51478. - - * camel-gpg-context.c (gpg_ctx_free): handle the context being - NULL, and exit silently. - -2003-12-01 Jeffrey Stedfast - - * camel-process.c (camel_process_fork): Start at fd = 3. - - * camel-gpg-context.c (gpg_ctx_op_start): Same. - - * camel-filter-driver.c (pipe_to_system): Same. - - * camel-filter-search.c (run_command): Start at fd = 3. - -2003-12-01 Jeffrey Stedfast - - * camel-stream-process.c (do_exec_command): Same. - - * camel-process.c (camel_process_fork): Same. - - * camel-filter-search.c (run_command): Same as below. - - * camel-filter-driver.c (pipe_to_system): Same as below. - - * camel-gpg-context.c (gpg_ctx_op_start): Use fcntl() to set - FD_CLOEXEC on each fd rather than close()ing it. Apparently - Linux's older pthread implementations use sockets and so this - fouls threading up. GO LINUX! GO! - -2003-12-01 Radek Doulik - - * camel-store.c (add_special_info): set SUBSCRIBED and NOINFERIORS - flags to special folders, renamed method from - add_vtrash_or_vjunk_info - (camel_store_get_folder_info): call add_special_info directly - -2003-11-28 Radek Doulik - - * camel-store.c (camel_store_get_folder_info): use old code from - mail-ops to add vtrash/vjunk info - -2003-11-28 David Woodhouse - - * providers/imap/camel-imap-provider.c: Enable GUI option for - 'custom command' connection. - * providers/imap/camel-imap-store.c: Don't g_free strings in - .rodata. It's considered rude. - -2003-11-28 Not Zed - - * camel-mime-utils.c (mail_list_magic[]): Added list-unsubscribe - header match. - -2003-11-26 Not Zed - - * camel-smime-context.c (sm_verify_cmsg): take a stream rather - than a part for the content. - (sm_verify): get the content directly as a stream. - - * camel-multipart-signed.c - (camel_multipart_signed_get_content_stream): new api to get the - content stream which will match the signed version. - -2003-11-26 JP Rosevear - - * Makefile.am: make sure we always dist the smime stuff - -2003-11-26 JP Rosevear - - * Makefile.am (libcamelinclude_HEADERS): conditionally compile - s/mime support - -2003-11-25 Not Zed - - * camel-cipher-context.c (camel_cipher_validity_envelope): change - args to make it suit storing the validity in a tree. - (camel_cipher_validity_init): init the list header. - (camel_cipher_validity_clone): call validity_new so it gets init - properly. - (camel_cipher_validity_free): free any children nodes recursively. - - * camel-cipher-context.h (CamelCipherValidity): added next/prev - and list header. - -2003-11-18 Jeffrey Stedfast - - * camel-session.c (camel_session_finalise): Don't destroy the - providers as it mans we can never ever have more than 1 session - object. See bug #51119 for details. - -2003-11-17 Jeffrey Stedfast - - * providers/local/camel-mbox-store.c (create_folder): Fixed an - exception to give a more meaningful description. - (get_folder_info): We always want to scan at least one level deep. - -2003-11-14 Jeffrey Stedfast - - * providers/local/camel-mbox-store.c (get_folder_info): Handle "" - as a request for a full dirscan as well (not just NULL). Makes it - consistant with other stores. - (scan_dir): Set the fi->flags appropriately. - - * providers/local/camel-mbox-folder.c - (camel_mbox_folder_get_full_path): Removed temporary hack. - -2003-11-14 Not Zed - - * camel-mime-parser.c (SCAN_BUF): oops, put the mempool stuff - back, we don't use e-memory afterall. Damn plane hacking. - -2003-11-13 Not Zed - - * camel-mime-parser.c: Remove mempool code, we use the stuff in - e-util. - (PRESERVE_HEADERS): new compile option, if on, we preserve headers - and folding exactly rather than unfolding all input. THIS BREAKS - EVERYTHING right now, so don't turn it on. - - * camel-gpg-context.c (gpg_decrypt): reset the input memstream - before passing it to the gpg engine. - - * tests/smime/pgp-mime.c (main): redirect /dev/null to stdin so it - doesn't hang waiting for input. - (main): removed from build - this tests multipart/signed - explictly, but now the details of this is handled directly by the - cipher context. - - * tests/smime/pgp.c (main): fixes for api changes. - (main): redirect /dev/null to stdin so it doesn't hang waiting for - input. - - * tests/message/test1.c (main): update for api changes. - - * camel-smime-context.c (sm_verify): look at the content object's - mime type, not the container's type. - -2003-11-11 Not Zed - - * camel-cipher-context.c (camel_cipher_validity_set_valid): take - into account the @valid argument and set validity properly. - (camel_cipher_validity_clone): new method to copy validities. - - * camel-smime-context.c (sm_signing_cmsmessage): removed a todo. - -2003-11-10 Not Zed - - * camel-smime-context.c (sm_verify_cmsg): split out the CMSMessage - verification code so it can be used from enveloped or externally - signed data. - - * camel-cipher-context.c (camel_cipher_verify): only take a - mimepart, internally handle multiparts and the hash. - -2003-11-07 Not Zed - - * camel-cipher-context.c: make ciphervalidity a public structure, - added encrypt status. - (camel_cipher_decrypt): changed to return a ciphervalidity. fixed - implementations. - (camel_cipher_validity_*): Fixed implementations to match new - structure, some of this is now redundant. - -2003-11-06 Not Zed - - * camel-smime-context.c (camel_smime_context_describe_part): - implement. - -2003-11-05 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (connect_to_server): Don't - bother trying to see if the server advertises EHLO. Simply always - try EHLO and fall back to HELO if EHLO fails. Fixes bug #50535. - -2003-11-05 Not Zed - - * camel-smime-context.c (camel_smime_context_describe_part): new - (unfinished) api to peek inside smime parts to tell us whats in - it. - -2003-11-03 Not Zed - - * camel-gpg-context.c (gpg_encrypt): Make this output the - full multipart/encrypted part, not just the encrypted content part. - - * camel-cipher-context.c (camel_cipher_sign): change to output - full mime part, not just a stream. - (camel_cipher_canonical_to_stream): utility function to - canonicalise a mimepart to a stream. - - * camel-smime-context.c (sm_encode_cmsmessage): removed. - (sm_sign): change interface to output a full mime-part, not just a - part of a mime part in multipart/signed mode. - -2003-11-04 Jeffrey Stedfast - - * camel-gpg-context.c (gpg_ctx_parse_status): We might need to - convert the passwd from UTF-8 into the locale charset. Fixes bug - #50485. - -2003-10-31 Not Zed - - * camel-cms-context.[ch]: removed, now redundant. - -2003-10-30 Not Zed - - * camel-smime-context.c (sm_get_passwd): implement something basic. - - * camel-cipher-context.h: Added a note about api inconsistencies. - -2003-10-30 Not Zed - - * camel-multipart-encrypted.c (camel_multipart_encrypted_decrypt): - fix for cipher_decrypt changes. - - * camel-gpg-context.c, camel-cipher-context.c: moved all the init - code to the end to save having to keep forward declarations - around. - (camel_cipher_decrypt): changed to take mimepart input and return - a mimepart. - (gpg_decrypt): fix for changed args. - -2003-10-29 Not Zed - - * camel-smime-context.[ch]: replaced entirely with a new - implementation which inherits from camel-cipher-context, and add - to build. - - * camel-multipart-encrypted.c (camel_multipart_encrypted_encrypt): - fix for cipher_encrypt api changes. - (camel_multipart_encrypted_decrypt): use g_ascii_strcasecmp. - - * camel-gpg-context.c (gpg_encrypt): Fix to handle input/output as - parts not streams - - * camel-cipher-context.c (camel_cipher_encrypt): change to take - mimeparts rather than streams as input/output. And remove the - 'sign' argument, it is implied if userid is supplied. - -2003-10-28 Not Zed - - * tests/smime/pgp.c (main): fix for ciphercontext api changes. - - * camel-multipart-signed.c (camel_multipart_signed_verify): pass - in the part to cipher_verify directly. - (camel_multipart_signed_sign): let the cipher context setup the - part details. - - * camel-gpg-context.c (gpg_sign): put the signature stream into a - mimepart, with appropriate headers/encoding. - (swrite): write out a mimepart rather than a stream. - (gpg_verify): handle changed args. - - * camel-cipher-context.c (camel_cipher_sign): write the signature - to a mimepart rather than a simple stream. - (camel_cipher_verify): take the signature as a mimepart not a - stream. - -2003-10-22 Not Zed - - * camel-utf8.c (camel_ucs2_utf8, camel_utf8_ucs2): helpers for - ucs2 stuff. ucs2 is 16 bit truncated unicode. - -2003-10-28 Jeffrey Stedfast - - * camel-mime-utils.c: We should check List-Post before List-Id - (List-Post has to contain the mailing-list posting address, - whereas List-Id does not.) WAlso moved X-Loop to after List-Id to - make FreeBSD lusers happy. Fixes bug #32297. - -2003-10-28 Jeffrey Stedfast - - * Fixes bug #35083 - - * providers/imap/camel-imap-store.c (connect_to_server): Same - here. - - * providers/pop3/camel-pop3-store.c (connect_to_server): Same as - the smtp changes. - - * providers/smtp/camel-smtp-transport.c (connect_to_server): If - HAVE_SSL is undefined, don't default to raw connections if the - option to connect via ssl is set. Instead set an exception and - return fail. - -2003-10-27 Frederic Crozat - - * camel-mime-utils.c: (camel_header_decode_date): - better detection of broken date to give to broken_date_parser. - -2003-10-24 Jeffrey Stedfast - - * camel-text-index.c (text_index_name_add_buffer): If a word is - longer than CAMEL_TEXT_INDEX_MAX_WORDLEN, then ignore it. This - fixes bug #50096. - -2003-10-23 Jeffrey Stedfast - - * *.c: Removed unneeded CAMEL_OBJECT() casts. - -2003-10-21 Not Zed - - * providers/local/camel-local-folder.c (local_getv, local_setv): - use the right tag name for the index_body arg. - (local_sync): write any persistent metadata - to make it - persistent. - (camel_local_folder_construct): turn off indexing, for now, it - should be done in local_setv. - - * providers/local/camel-local-folder.h: change body_index to a bool - type. - - * camel-object.c (cobject_state_read, cobject_state_write): handle - bool types - (cobject_state_write): make sure we free all arg types. - - * camel-arg.c (camel_argv_build): - (camel_arggetv_build): handle bool type. - - * camel-arg.h: Added BOO (bool) type. - -2003-10-15 Not Zed - - * camel-store.c (camel_folder_info_build): Fix so we output the - tree in sorted depth-first order, rather in reverse. - -2003-10-16 Jeffrey Stedfast - - * camel-sasl-kerberos4.c: Fixed a #include. - -2003-10-10 Not Zed - - * providers/local/camel-local-provider.c: set the url fragment - flag for local providers. - - * camel-provider.h: Move the URL_PART_NEED bits to the high 16 - bits, to allow for easier changes in the future. Added a - URL_PART_FRAGMENT flag for providers that use fragment = folder - path. - -2003-10-09 Jeffrey Stedfast - - * camel-mime-utils.c (header_decode_date): Allow timezone offsets - to be up to 14 hours ahead of UTC. Fixes bug #49357. - - * broken-date-parser.c (get_tzone): Same. - -2003-10-08 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_helo): Removed an - unused variable. - -2003-09-25 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_helo): If the - localhost lookup results in a numeric IPv6 host, use the form - "[IPv6:]" as specified in rfc2821. Fixes bug #46006. - -2003-09-23 Ettore Perazzoli - - * providers/local/camel-local-provider.c: Set the IS_STORAGE bit - in the mbox provider, since it can now contain a hierarchy of - folders. - -2003-09-23 Jeffrey Stedfast - - * providers/local/camel-mbox-store.c (get_folder): If the CREATE - flag is set and the parent .sbd directory does not exist, create - it. - - * camel-mime-utils.c (append_8bit): Don't forget to flush the - iconv conversion. - - * tests/message/test4.c (main): Don't try dot-files. - -2003-09-22 Not Zed - - ** See bug #41610 - - * providers/pop3/camel-pop3-folder.c (cmd_tocache): protect a - divide by 0 for 0 length messages. - -2003-09-22 Not Zed - - * providers/imap/camel-imap-provider.c: Added "offline_sync" - option, which lets you synchronise all mail to local storage - automagically. - - * camel-disco-folder.c (cdf_folder_changed): hook onto the folder - changed single, for all new messages, check that they are online - using another thread, if the offline_sync option has been enabled - for this store. - -2003-09-21 Not Zed - - * camel-session.c (session_thread_destroy): call proper entry - point for freeing the message. - -2003-09-18 Not Zed - - * camel-folder.c (filter_filter): register the filtering process - for progress, and do progress of the filtering process. - -2003-09-17 Not Zed - - * camel.c (camel_init): init camel operation. - - * camel-operation.c (camel_operation_reset): removed, not used, - not worth it. - (camel_operation_mute): new method to stop all status updates - permanently. - (*): Changed to use thread specific data and a list rather than a - hashtable. - (cancel_thread): removed. - (camel_operation_register): return the previously registered op. - -2003-09-22 Jeffrey Stedfast - - * providers/nntp/camel-nntp-store.c (connect_to_server): Fix the - code that creates a new ssl stream to pass the correct arguments - and the proper flags. - - * providers/imapp/camel-imapp-folder.c (imap_sync): Cast the - CamelFolder to a CamelIMAPPFolder to hush some compiler warnings. - - * camel-mime-utils.h: Define a struct _CamelContentDisposition - (allows the imapp code to compile) - - * providers/imapp/camel-imapp-driver.c: #include - -2003-09-18 Jeffrey Stedfast - - * camel-mime-utils.c (camel_transfer_encoding_to_string): New - function to replace the one from camel-mime-part.c - (camel_transfer_encoding_from_string): Same. - (camel_content_transfer_encoding_decode): Renamed from - camel_header_content_encoding_decode(). - - * camel-mime-part.c (camel_mime_part_encoding_to_string): Removed. - (camel_mime_part_encoding_from_string): Removed. - - * camel-data-wrapper.[c,h]: updated for CamelTransferEncoding - namespace changes - - * camel-folder-summary.c: updated for CamelTransferEncoding - namespace changes - - * camel-mime-filter-bestenc.[c,h]: updated for CamelTransferEncoding - namespace changes - - * camel-mime-message.c: updated for CamelTransferEncoding - namespace changes - - * camel-mime-part-utils.c: updated for CamelTransferEncoding - namespace changes - - * camel-multipart-signed.c: updated for CamelTransferEncoding - namespace changes - - * camel-smime-context.c: updated for CamelTransferEncoding - namespace changes - - * providers/imapp/camel-imapp-utils.c: updated for - CamelTransferEncoding namespace changes - - * tests/lib/messages.c: updated for CamelTransferEncoding - namespace changes - - * tests/message/test1.c: updated for CamelTransferEncoding - namespace changes - -2003-09-18 Jeffrey Stedfast - - * camel-mime-utils.[c,h]: namespaced the encoding/decoding - routines. - - * camel-mime-filter-basic.c: updated for namespace changes to the - encoding/decoding routines in camel-mime-utils.c - - * camel-multipart.c: updated for namespace changes to the - encoding/decoding routines in camel-mime-utils.c - - * camel-sasl-digest-md5.c: updated for namespace changes to the - encoding/decoding routines in camel-mime-utils.c - - * camel-sasl.c: updated for namespace changes to the - encoding/decoding routines in camel-mime-utils.c - - * camel-vee-folder.c: updated for namespace changes to the - encoding/decoding routines in camel-mime-utils.c - - * providers/imap/camel-imap-search.c: updated for namespace - changes to the encoding/decoding routines in camel-mime-utils.c - - * providers/pop3/camel-pop3-folder.c: updated for namespace - changes to the encoding/decoding routines in camel-mime-utils.c - -2003-08-26 Jeffrey Stedfast - - * camel-mime-parser.[c,h]: s/HSCAN_/CAMEL_MIME_PARSER_STATE_/g and - s/_header_state/_camel_mime_parser_state/g - - * camel-filter-driver.c: Same. - - * camel-folder-summary.c: Here too. - - * camel-http-stream.c: And here. - - * camel-mime-message.c: ... - - * camel-mime-part-utils.c: ... - - * camel-mime-part.c: ... - - * camel-movemail.c: ... - - * camel-multipart-signed.c: ... - - * camel-multipart.c: ... - - * providers/local/camel-mbox-folder.c: ... - - * providers/local/camel-mbox-summary.c: ... - - * providers/local/camel-mh-summary.c: ... - - * providers/nntp/camel-nntp-summary.c: ... - - * providers/pop3/camel-pop3-folder.c: ... - -2003-08-25 Jeffrey Stedfast - - * camel-mime-utils.[c,h]: Namespaced. - - * camel-data-wrapper.c: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-digest-folder.c: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-filter-driver.c: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-filter-search.c: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-folder-search.c: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-folder-summary.[c,h]: updated for namespace changed made - to camel-mime-utils.[c,h] - - * camel-http-stream.c: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-http-stream.h: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-internet-address.c: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-medium.[c,h]: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-mime-message.c: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-mime-parser.[c,h]: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-mime-part-utils.c: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-mime-part.[c,h]: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-movemail.c: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-multipart-encrypted.c: updated for namespace changed made - to camel-mime-utils.[c,h] - - * camel-multipart-signed.c: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-multipart.c: updated for namespace changed made to - camel-mime-utils.[c,h] - - * camel-search-private.[c,h]: updated for namespace changed made - to camel-mime-utils.[c,h] - - * camel-types.h: updated for namespace changed made to - camel-mime-utils.[c,h] - - * providers/imap/camel-imap-folder.c: updated for namespace - changed made to camel-mime-utils.[c,h] - - * providers/imap/camel-imap-store-summary.c: updated for namespace - changed made to camel-mime-utils.[c,h] - - * providers/imap/camel-imap-utils.c: updated for namespace changed - made to camel-mime-utils.[c,h] - - * providers/imapp/camel-imapp-utils.[c,h]: updated for namespace - changed made to camel-mime-utils.[c,h] - - * providers/local/camel-local-summary.[c,h]: updated for namespace - changed made to camel-mime-utils.[c,h] - - * providers/local/camel-maildir-summary.c: updated for namespace - changed made to camel-mime-utils.[c,h] - - * providers/local/camel-mbox-summary.c: updated for namespace - changed made to camel-mime-utils.[c,h] - - * providers/local/camel-spool-summary.h: updated for namespace - changed made to camel-mime-utils.[c,h] - - * providers/nntp/camel-nntp-summary.c: updated for namespace - changed made to camel-mime-utils.[c,h] - - * providers/nntp/camel-nntp-utils.c: updated for namespace changed - made to camel-mime-utils.[c,h] - - * providers/pop3/camel-pop3-folder.c: updated for namespace - changed made to camel-mime-utils.[c,h] - - * providers/sendmail/camel-sendmail-transport.c: updated for - namespace changed made to camel-mime-utils.[c,h] - - * providers/smtp/camel-smtp-transport.c: updated for namespace - changed made to camel-mime-utils.[c,h] - -2003-09-16 Jeffrey Stedfast - - * providers/local/camel-mbox-folder.c - (camel_mbox_folder_get_full_path): Implement a temp hack so trunk - works until we merge in new-ui-branch. - - * camel-stream-filter.c (do_flush): Don't warning about how we - haven't written anything to the stream, this is not an - error. fflush() doesn't care if you try to fflush() a stream - without writing to it, so we shouldn't care either. - -2003-09-15 Not Zed - - * providers/imapp/camel-imapp-store.c (store_resp_list) - (imap_login, try_sasl, imap_try_authenticate): removed dead code. - - * providers/imapp/camel-imapp-stream.c: return -1 if stream not - set. - - * providers/imapp/camel-imapp-engine.c (iterate_completion): put - done request on the done queue, so all requests are always - somewhere. - (camel_imapp_engine_command_free): just spit warnings of active - messages being freed, but abort if the item isn't in any list. - Also remove the node from its list before going on. - (iterate_untagged, iterate_continuation, iterate_completion): - staticifiy. - - * providers/imapp/camel-imapp-provider.c - (camel_imapp_module_init): move camel_exception_setup call here. - - * providers/imapp/camel-imapp-driver.c - (camel_imapp_driver_get_type): remove execption setup here, it - isn't early enough. - (camel_imapp_driver_list): handle exceptions. - -2003-09-12 Jeffrey Stedfast - - * providers/local/camel-mbox-folder.c - (camel_mbox_folder_get_full_path): Implements - CamelLocalFolder::get_full_path() (publicly namespaced so that - CamelMboxStore can re-use them). - (camel_mbox_folder_get_meta_path): Same. - - * providers/local/camel-mbox-store.c (get_folder): Changed the way - the path is constructed, since we now handle subdirectories and - stuff. - (delete_folder): Try deleting the Folder.sbd directory. We also - need to manage our own meta files since CamelLocalStore's impl - constructs paths differently than what we need. - (create_folder): Implemented. - (rename_folder): Implemented. - (scan_dir): Scan an mbox tree - (get_folder_info): Implemented using scan_dir(). - - * providers/local/camel-local-store.c (delete_folder): Set fi->url - to the correct value, meaning we need to prefix it with the - protocol and the folder_name is not actually part of the path, it - is a separate component to the url. - - * providers/local/camel-local-folder.c - (camel_local_folder_construct): Use the new class virtual method - to construct the full folder path and all the meta files. - (local_get_full_path): Implemented default get_full_path method. - (local_get_meta_path): Implemented default get_meta_path method. - -2003-09-11 Dan Winship - - * Makefile.am (noinst_LTLIBRARIES): Remove libcamel-static.la - -2003-09-05 Not Zed - - * providers/imap/camel-imap-store.c (imap_noop): call - camel_folder_sync bypassing the folder lock. See - imap_store_refresh_folders too. - -2003-09-04 David Woodhouse - - * providers/camel-imap-store.[ch]: Add PREAUTH handling and - pine/mutt/etpan/etc.-style 'ssh exec imapd' support. - -2003-09-03 David Woodhouse - - * camel-stream-process.[ch]: New stream implementation for running - commands. - * Makefile.am: Compile the above - -2003-08-20 Not Zed - - ** See bug #47765. - - * camel-folder-search.h: Removed match1 member. - - * camel-folder-search.c (camel_folder_search_match_expression): - use current directly rather than match1. This method isn't used - anywhere anyway. - (search_not): remove match1 stuff. - (search_match_all): properly handle the match-all against 1 - message as a scalar result, not an array result. - -2003-09-03 Not Zed - - * camel-http-stream.c (camel_http_stream_set_proxy): handle NULL - proxy_url - unset the proxy. - -2003-08-29 Not Zed - - * camel-object.c (camel_object_state_write): - (cobject_getv): - (cobject_setv, cobject_state_read, cobject_state_read) - (cobject_state_write): removed debug printfs. - - * providers/local/camel-local-folder.c (local_getv): Need to copy - the local properties list before passing it out, since it's freed. - -2003-08-27 Not Zed - - * providers/local/camel-local-folder.c (local_getv): implement - PERSISTENT_PROPERTIES, for index mode. - - * camel-object.c (cobject_state_read): Also add property reading, - and bump version to 1. - (cobject_state_write): add persistent property writing. - -2003-08-26 Not Zed - - * camel-folder.c (folder_getv): chain up properly. - - * camel-file-utils.c (camel_file_util_savename): helper to create - a .#filename filename. - - * providers/local/camel-local-folder.c - (camel_local_folder_construct): init meta-data for local folders. - (local_getv): chain up properly, if args are not processed, rather - than don't if they aren't. - -2003-08-23 Not Zed - - * camel-object.c (cobject_class_init): added a new event, - meta_changed. - (camel_object_meta_set, camel_object_meta_get): meta-data api. - (camel_object_free_hooks): Free meta-data if it is set on the - object. - - * providers/local/camel-local-folder.c - (camel_local_folder_get_type): setup a property list for local - folders, just 'index_body' at present. - -2003-08-25 Jeffrey Stedfast - - * camel-filter-driver.c (pipe_to_system): Added some more error - checking for reading/writing to the pipes. Fixes bug #47880. - -2003-08-21 Jeffrey Stedfast - - * camel-data-wrapper.c (decode_to_stream): Don't poke - wrapper->stream directly, use camel_data_wrapper_write_to_stream() - instead as this simplifies things and makes the imap data wrapper - implementation Just Work (tm). - - * providers/imap/camel-imap-wrapper.c: changed prototype of - write_to_stream() to return ssize_t. - -2003-08-20 Jeffrey Stedfast - - * providers/imap/camel-imap-wrapper.c (imap_wrapper_hydrate): Make - sure to ref the stream. Fixes bug #47749. - -2003-08-18 Not Zed - - * camel-http-stream.c: Various fixes to make it work. - - * tests/smime/pgp-mime.c (main): added missing 'ret' variable. - - * providers/smtp/camel-smtp-transport.c (connect_to_server): - * providers/imapp/camel-imapp-store.c (connect_to_server: - * providers/imap/camel-imap-store.c (connect_to_server): - * providers/pop3/camel-pop3-store.c (connect_to_server): - * camel-http-stream.c (http_connect): change service->session for - tcp_stream_ssl_new. - - * camel-tcp-stream-ssl.c: Changed service to session, and fix some - refcounting of it. - include camel-operation.h - -2003-08-15 Not Zed - - ** See bug #47634. - - * tests/lib/messages.c (test_message_compare): check - write_to_stream returns. - (message_dump_rec): helper to dump message structure. - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): dont set content - encoding here. - (camel_mime_part_construct_content_from_parser): set it here - instead, on every part. basically same as setting the - mime_type_field always. - - * camel-multipart-signed.c (camel_multipart_signed_class_init): - * camel-mime-message.c (camel_mime_message_class_init): - * camel-multipart.c (camel_multipart_class_init): override - decode_to_stream to always do the same as write_to_stream, since - we can never be encoded. - -2003-08-15 Jeffrey Stedfast - - * providers/imap/camel-imap-wrapper.c (imap_wrapper_hydrate): - Don't attach any filters to decode base64/qp/etc. - -2003-08-14 Jeffrey Stedfast - - * camel-mime-part.c (write_to_stream): Save errno when - flushing/unreffing the filter stream. - -2003-08-13 Jeffrey Stedfast - - * camel-mime-part.c (write_to_stream): If the content is - base64/qp/uu/etc encoded but the part is 7bit/8bit/(or otherwise - non-encoded), set reencode to TRUE so that we decode the original - content stream. Fixes a bug noticed on - evolution-patches@ximian.com where a patch had a - Content-Transfer-Encoding of 7bit but was base64 encoded. - -2003-08-13 Not Zed - - * camel-folder-summary.c (camel_folder_summary_remove_range): Fix - the range check, we were stopping removal of 1 or 2 removals, for - some odd and completely uncomprehensible reason. Perhaps debug - left in? - -2003-08-13 Not Zed - - ** See bug #47517. - - * camel-vee-folder.c (vee_sync): Always rebuild folder on any - sync, not just expunge ones. - -2003-08-11 Not Zed - - * providers/imapp/camel-imapp-store.c (imap_get_folder_info): - force connect manually so basics work. - - ** See bug #45505. - - * camel-service.c (camel_gethostbyname): duh, pthread_create - returns the error code directly, not via errno. - (camel_gethostbyaddr): Same, also properly handle the failure - case. - -2003-08-01 Not Zed - - ** See bug #47208. - - * camel-filter-search.c (match_all): match-all with no arguments - should always return TRUE. - - * camel-folder-search.c (camel_folder_search_execute_expression): - print a warning when we get an invalid result type & fixed a leak - for that case. - -2003-08-08 Jeffrey Stedfast - - * tests/message/test4.c: New test suite for the mime parser (which - is where the below 2 fixes were noticed). - - * camel-mime-parser.c (folder_boundary_check): Calculate 'len' by - subtracting the boundary start from inend rather than 'atleast'. - (folder_scan_content): Calculate 'inend' differently depending on - the EOF state. - -2003-08-08 Jeffrey Stedfast - - * camel-mime-filter-tohtml.c (html_convert): Rather than checking - *inptr == '\n', check inptr >= inend - this gets rid of an Invalid - Read report from valgrind. - - * camel-mime-part.c (write_to_stream): Don't necessarily re-encode - just because the encodings differ. Need to look into making it so - that message/rfc822 and multipart parts ignore the - Content-Transfer-Encoding header and just keep their 'encoding' - bits set to DEFAULT. - -2003-08-05 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (get_content): Updated. - - * camel-mime-message.c (camel_mime_message_init): Don't override - the mime_type here. - (process_header): Updated to use CamelDataWrapper's mime_type - field. - (find_best_encoding): Same. - (best_encoding): Here too. - - * camel-digest-folder.c (camel_digest_folder_new): Updated for - CamelMimePart::content_type change. - - * camel-mime-part.c (camel_mime_part_init): Override our parent - class's default mime_type. - (camel_mime_part_finalize): Don't need to unref the content_type - anymore. - (process_header): Updated to use CamelDataWrapper's mime_type - field. - (camel_mime_part_set_filename): Same. - (camel_mime_part_get_filename): Same. - (camel_mime_part_get_content_type): Same. - (set_content_object): Here too. - (write_to_stream): Updated. - (construct_from_parser): Updated. - - * camel-mime-part.h: Remove the content_type field. - -2003-07-31 Jeffrey Stedfast - - * tests/lib/messages.c (test_message_compare_content): If the - chunks differ, perform a hexdump on the data being compared so - that we may analyse it easier. - - * camel-multipart-signed.c (write_to_stream): Return ssize_t. - - * camel-mime-utils.h: Added the CamelMimePartEncodingType enum - here. - - * camel-mime-part.h: Removed the CamelMimePartEncodingType enum - from here. - - * camel-mime-part.c (write_to_stream): Updated to return - ssize_t. Also minor changes to only re-encode the content stream - if the charset or encoding changed (this way we write it out in - the original raw form if nothing changed). - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): Drastically - simplify. We no longer scan html content to try and find the - charset, nor do we care about converting the content to UTF-8 and - handling broken windows charsets. - - * camel-mime-message.c (find_best_encoding): Use - decode_to_stream() here. Also updated to not assume the content - charset is UTF-8 since it is very likely not the case anymore - since data-wrappers no longer are converted to UTF-8 at parse - time. - - * camel-folder-summary.c (summary_build_content_info_message): Use - decode_to_stream instead here too. - - * camel-folder-search.c (match_words_1message): Use - decode_to_stream instead of write_to_stream so we can search the - contents. - - * camel-data-wrapper.c (camel_data_wrapper_init): Set the default - encoding to DEFAULT. - (write_to_stream): Updated to return ssize_t - (camel_data_wrapper_decode_to_stream): New virtual function to - decode a data wrapper to a stream (results in nearly identical - behaviour to the old write_to_stream method). - (decode_to_stream): Default implementation of above virtual - method. Decodes base64/qp/etc streams. - - * camel-data-wrapper.h: Removed the rawtext bit and added an - encoding member. - -2003-08-01 Jeffrey Stedfast - - * tests/smime/pgp-mime.c: Same. - - * tests/smime/pgp.c: Updated to build and to import some custom - gpg keys for use with testing. - -2003-07-30 Jeffrey Stedfast - - * camel-mime-message.c (write_to_stream): Also updated. - - * camel-data-wrapper.c (write_to_stream): This should return ssize_t - - * camel-multipart-signed.c (write_to_stream): Updated. - - * camel-multipart.c (write_to_stream): Same. - - * camel-mime-part.c (write_to_stream): Here too. - -2003-07-11 Suresh Chandrasekharan - - * camel-iconv.c: Fix for #46168 'some additional locale aliases - required for chinese support'. - -2003-07-25 Jeffrey Stedfast - - * camel-mime-utils.c (header_decode_word): Revert NotZed's fix for - bug #42170 - this causes even more problems than it solves. See - bug #46331 for info. Basically, each address header would be - converted to UTF-8 twice which means no raw 8bit address header - would render correctly. - (header_decode_mailbox): Perform a sanity check on the resultant - addr->str to make sure that it is valid UTF-8, if not convert it - to UTF-8. Fixes bug #42170. - -2003-07-23 Ettore Perazzoli - - * camel-provider.c (camel_provider_init): Print the provider - directory as well, for debugging. - -2003-07-23 Jeffrey Stedfast - - * camel-mime-message.c (find_best_encoding): Revert my previous - changes to this function. - - * camel-mime-utils.h: Revert previous changes. - - * camel-mime-part.h: Revert previous changes. - - * camel-mime-part-utils.c: Revert previous changes. - - * camel-data-wrapper.c (camel_data_wrapper_init): Revert previous - changes. - (write_to_stream): Revert previous changes. - -2003-07-23 Dan Winship - - * camel-block-file.c: #include camel-file-utils.h for camel_read() - - * camel-uid-cache.c (camel_uid_cache_save): Remove unused variable - and label. - - * camel-url.c: #include camel-string-utils.h for camel_strdown - - * providers/pop3/camel-pop3-store.c (pop3_try_authenticate): Cast - an (unsigned char *) to (char *) to fix a warning - -2003-07-17 Jeffrey Stedfast - - * camel-mime-message.c (find_best_encoding): Updated to convert - to/from the correct charset (since content is no longer - necessarily in UTF-8). - (best_encoding): Free the charset string when we're done with it. - - * camel-stream-fs.c (stream_read): Increment the seekable stream - position by the number of bytes read. Oops. - (stream_write): Same here. - -2003-07-17 Timo Sirainen - - ** See bug #42573 - - * providers/imap/camel-imap-folder.c (do_append): Only free the - response after we have finished the literal request, otherwise we - could try processing folder updates incorrectly. - -2003-07-14 Jeffrey Stedfast - - * camel-mime-utils.h: Add the CamelMimePartEncodingType definition - here. - - * camel-mime-part.h: Remove the CamelMimePartEncodingType - definition. - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): Don't do any of the - auto-detection we used to do here anymore. Just read the content - into a memory buffer and record the encoding type. - (camel_mime_part_construct_content_from_parser): Don't mangle the - Content-Type struct here anymore. - - * camel-data-wrapper.c (camel_data_wrapper_init): Init encoding to - DEFAULT. - (write_to_stream): If the stream needs to be decoded, decode it. - -2003-07-15 Jeffrey Stedfast - - * camel-stream-fs.c (stream_read): If we read 0 bytes, then set - eos to TRUE. - -2003-07-09 Jeffrey Stedfast - - Get rid of the #ifdef ENABLE_THREADS since we no longer plan to - support/maintain this. - - * providers/nntp/camel-nntp-store.c: Here. - - * providers/nntp/camel-nntp-newsrc.c: And here. - - * providers/nntp/camel-nntp-folder.c: Same. - - * providers/local/camel-local-folder.c: And here. - - * camel-block-file.c: Here too. - - * camel.c: Same. - - * camel-certdb.c: Here too. - - * camel-charset-map.c: And here. - - * camel-cipher-context.c: " - - * camel-data-wrapper.c: " - - * camel-digest-folder.c: " - - * camel-exception.c: " - - * camel-folder.c: " - - * camel-folder-summary.c: " - - * camel-lock-client.c: " - - * camel-mime-utils.c: " - - * camel-object.c: " - - * camel-operation.c: " - - * camel-partition-table.c: " - - * camel-sasl-popb4smtp.c: " - - * camel-service.c: " - - * camel-session.c: " - - * camel-store.c: " - - * camel-store-summary.c: " - - * camel-text-index.c: " - - * camel-transport.c: " - - * camel-vee-folder.c: " - - * camel-tcp-stream-openssl.c: Removed pthread.h, it isn't needed. - -2003-07-09 Larry Ewing - - * camel.h: remove reference to camel-pgp-mime.h - -2003-07-08 Jeffrey Stedfast - - * camel-pgp-mime.[c,h]: Removed. - - * camel-iconv.c: Updated (new copy/paste from e-iconv). - - * camel-block-file.c (camel_block_file_get_block): Use - camel_read() rather than libc read. - - * camel-tcp-stream-raw.c (stream_read): Use camel_read(). - (stream_write): Use camel_write(). - - * camel-stream-fs.c (stream_read): Use camel_read(). - (stream_write): Use camel_write(). - -2003-07-07 Jeffrey Stedfast - - * providers/nntp/camel-nntp-folder.c (camel_nntp_folder_new): Use - camel_mkdir(). - - * providers/imap/camel-imap-folder.c (camel_imap_folder_new): Use - camel_mkdir(). - - * camel-session.c (get_storage_path): Use camel_mkdir(). - - * camel-store.c (camel_mkdir_hier): Removed. - - * camel-data-cache.c (camel_data_cache_new): Updated to use - camel_mkdir(). - (data_cache_path): Same. - - * camel-file-utils.c (camel_mkdir): Renamed and documented. - (camel_file_util_safe_filename): Documented. - (camel_read): Moved here from camel-io.c - (camel_write): Same. - - * camel-io.[c,h]: Removed. - - * camel-uid-cache.c (camel_uid_cache_new): Use the - camel-file-utils.c version of mkdir. - -2003-07-07 Jeffrey Stedfast - - * camel-session.c (camel_session_init): Updated for string-utils - namespace changes. - - * camel-provider.c: Updated for string-utils namespace changes. - - * camel-mime-part.c (init_header_name_table): Updated for - string-utils namespace changes. - - * camel-mime-message.c (camel_mime_message_class_init): Updated - for string-utils namespace changes. - (camel_mime_message_init): Same. - - * camel-mime-filter-enriched.c - (camel_mime_filter_enriched_class_init): Updated for string-utils - namespace changes. - - * camel-folder-summary.c (camel_folder_summary_init): Updated for - string-utils namespace changes. - - * camel-string-utils.[c,h]: Renamed from string-utils.[c,h] and - also namespaced all functions. - -2003-07-01 Jeffrey Stedfast - - * camel-sasl-digest-md5.c (digest_response): Don't quote the - charset value, the qop value, nor the response value. Fixes bug - #45712. - -2003-07-01 Jeffrey Stedfast - - * camel-mime-utils.c (header_format_date): Use gmtime_r() instead - of using gmtime() and memcpy() to try and be "atomic". - -2003-06-30 Dan Winship - - * camel-folder-search.c (camel_folder_search_finalize): free the - summary hash - -2003-06-24 David Woodhouse - - * camel-mime-utils.c (header_format_date): Put day of week into - outgoing email. - - -2003-06-25 Jeffrey Stedfast - - * camel-folder-summary.h: Added prototype for - camel_folder_summary_remove_range(). - -2003-06-25 Not Zed - - ** See bug #45386 - - * camel-service.c (camel_gethostbyname, camel_gethostbyaddr): Make - sure we have an exception that we test against. - -2003-06-20 Not Zed - - ** See bug #43887 - - * camel-mime-filter-enriched.c (camel_enriched_to_html): simple - wrapper to convert enriched to html in one go. - -2003-06-18 Not Zed - - * camel-service.c (get_hostbyaddr, get_hostbyname): if we got - cancelled, the message is floating, so free it. - (struct _lookup_msg): Add a cancelled tag. - (camel_gethostbyname, camel_gethostbyaddr): if we get a - failure/cancel, cancel the lookup thread and detach, so we dont - have to wait for it to return. cleanup changed to handle the case - where we didn't get a reply message. - -2003-06-13 Jeffrey Stedfast - - * providers/pop3/camel-pop3-folder.c (pop3_finalize): Made static - (to match the prototype). - -2003-06-13 Larry Ewing - - * camel-folder-thread.c (camel_folder_thread_messages_apply): - don't leak the summary when reloading it. Fixes a very large - leak. - -2003-06-17 Not Zed - - * camel-vee-folder.c (vee_folder_remove_folder): Calculate ranges - to remove folder info's more efficiently. affects shutdown - performance on big vfolders signifinantly. - (vee_folder_build_folder): do the same here, when rebuilding a - folder's definition. - - * camel-folder-summary.c (camel_folder_summary_remove_index): new - function to drop a range of index entries in one hit. - -2003-06-16 Not Zed - - ** See bug #31745 - - * providers/imap/camel-imap-store-summary.c - (camel_imap_store_summary_namespace_new): Workaround a shell bug - - if the namespace has '#' in it, then strip it. - -2003-06-16 Not Zed - - ** See bug #44322 - - * providers/imap/camel-imap-command.c (imap_command_strdup_vprintf): - If we are outputting a folder name, make sure we calculate buffer - size based on the raw/utf7 version - - ** See bug #44121 - - * camel-multipart-signed.c (signed_get_part): If we can't parse - the content, but we have a stream, just use that as the content. - -2003-06-05 Jeffrey Stedfast - - Fix for bug #40788. - - * providers/pop3/camel-pop3-engine.c (camel_pop3_engine_new): Now - takes a flags argument. Currently there is only 1 flag which can - be used to disable Pop3 server extensions. - (get_capabilities): Don't check for Pop3 server extensions if the - DISABLE_EXTENSIONS flag is set on the engine. - (camel_pop3_engine_iterate): If we get a response that is neither - +OK nor -ERR, default to treating it like a -ERR. - - * providers/pop3/camel-pop3-store.c (connect_to_server): Check for - the disable_extensions param. - - * providers/pop3/camel-pop3-provider.c: Define a checkbox to - disable all POP3 extension support. - -2003-06-11 Jeffrey Stedfast - - Partial fix for bug #44457. - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): Make sure to set - rawtext to FALSE if we successfully convert the text to UTF-8. - - * camel-data-wrapper.c (camel_data_wrapper_init): Default the - value of rawtext to TRUE instead of FALSE. This way if the mailer - decides to try displaying a non-textual part as text, it knows - that it needs to convert the content to UTF-8. - -2003-06-04 Jeffrey Stedfast - - * camel-uid-cache.c (camel_uid_cache_new): Create the directory - with mode 0777 and the cache file itself with mode 0666. Let the - user's umask filter the permissions. Instead of saving the fd on - the Cache object, instead save the filename. Use camel_read() - instead of expecting read() to just always work without getting an - EINTR/etc. - (maybe_write_uid): Don't do anything if cache->fd == -1, this - means an error has occured in a previous callback. Replace the 2 - calls to write() with camel_write() and check their return - values. If either of them fails, set cache->fd to -1 (GHashTable - doesn't give us a way to abort foreach'ing thru the table). - (camel_uid_cache_save): Save to a temp file instead of overwriting - the original. Do proper error checking, etc. Also added some - smarts about whether to try and overwrite the old cache even if we - haven't successfully saved all the uids in the cache. - (camel_uid_cache_destroy): Free the cache->filename, no longer - need to close (cache->fd). - -2003-06-11 Larry Ewing - - * camel-text-index.c (text_index_normalise): use g_utf8_strdown - properly. - -2003-06-09 Jeffrey Stedfast - - * camel-mime-message.c (find_best_encoding): Add the - CAMEL_BESTENC_TEXT bit to enctype if the part is a text part. - - * camel-mime-filter-bestenc.c - (camel_mime_filter_bestenc_get_best_encoding): If we have any - nul-bytes or if the content is non-text and contains any 8bit - octets, we need to use base64. Fixes bug #44344. diff --git a/camel/ChangeLog.pre-1-4 b/camel/ChangeLog.pre-1-4 deleted file mode 100644 index 7ea58c89d4..0000000000 --- a/camel/ChangeLog.pre-1-4 +++ /dev/null @@ -1,22083 +0,0 @@ -2003-06-01 Jeffrey Stedfast - - * broken-date-parser.c (d): Turn off debugging. - - * providers/pop3/camel-pop3-engine.c (get_capabilities): Move the - code that prepends the 'password' authtype to the auth list so - that we don't add it again when regetting the capabilities. - -2003-05-30 Jeffrey Stedfast - - * camel-filter-driver.c (run_only_once): Turned off a debugging - printf. - -2003-05-27 Jeffrey Stedfast - - This should finish fixing all variations of bug #42854, which, - funnily enough specified "copying" as the scenario for reproducing - this bug, but somehow I found/fixed it only for expunging for some - reason? I can't even guess as to how this happened. Oh well, - expunging needed fixing either way. - - * providers/imap/camel-imap-folder.c (imap_transfer_online): Sort - the uids here too (just like I had fixed for expunge a week or so - ago). - (imap_transfer_resyncing): Sort them here too. - (imap_search_by_uids): Sort here too, even though I don't think it - is necessary. Can't hurt. - (imap_expunge_uids_offline): Might as well sort here too. - -2003-05-22 Jeffrey Stedfast - - * camel-object.c (camel_object_bag_destroy): Lets try this - again. We don't actually want to free the key here, because - camel_object_bag_remove() does that for us. This should fix bug - #43406 properly. - -2003-05-20 Jeffrey Stedfast - - * camel-object.c (camel_object_bag_destroy): Create a second - GPtrArray for the keys. We don't want to use bag->free_key() on - the object. Fixes bug #43406. - -2003-05-19 Jeffrey Stedfast - - * camel-folder-summary.c (camel_folder_summary_load): Only display - a warning if errno != EINVAL (EINVAL means there was a version - mismatch, so we don't really need to warn here since we are - supposed to be able to handle this situation). - (perform_content_info_load): Turn off debugging message. - (summary_assign_uid): Turn off uid-clash warning. - (camel_folder_summary_decode_token): Turn off debug messages. - (summary_header_load): Turn off version-mismatch warning. - -2003-05-16 Jeremy Katz - - * providers/smtp/camel-smtp-transport.c (smtp_helo): Ensure cmdbuf - is initialized to avoid compiler warning. - - * providers/local/camel-mbox-summary.c (summary_header_load): Cast - folder_size to uint32 to fix warning. - (camel_mbox_summary_sync_mbox): Update for new API. - - * providers/imap/camel-imap-utils.c (parse_params): - imap_parse_nstring expects size_t, not int - (imap_body_decode): Likewise. - - * camel-stream-filter.c (do_read): presize needs to be size_t - instead of int. - (do_write): Likewise. - - * camel-seekable-substream.c (stream_read): Return ssize_t instead - of int to match prototypes. - (stream_write): Likewise. - - * camel-mime-part.c (construct_from_parser): len needs to be - size_t instead of int. - - * camel-mime-parser.c (folder_scan_step): datalength needs to be a - size_t* instead of an int* to make dependent APIs safe. - (camel_mime_parser_step): Likewise. - (folder_scan_content): Likewise. - * camel-mime-parser.h: Likewise. - - * camel-mime-message.c (camel_mime_message_class_init): Use glib - macro for pointer/int conversions. - (construct_from_parser): Update for new API. - - * camel-folder-summary.c - (camel_folder_summary_info_new_from_parser): Update len to be - size_t for new API. - (summary_build_content_info): Likewise. - * camel-http-stream.c (http_get_headers): Likewise. - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): Likewise. - * camel-multipart-signed.c (signed_construct_from_parser): Likewise. - * camel-multipart.c (construct_from_parser): Likewise. - - * camel-folder-search.c (match_words_index): Use glib macros for - pointer/int conversions. - * camel-html-parser.c (tokenise_setup): Likewise. - (convert_entity): Likewise. - * camel-block-file.c (block_hash_func): Likewise. - (camel_block_file_get_block): Likewise. - (camel_block_file_get_block): Likewise. - (camel_block_file_detach_block): Likewise. - * camel-session.c (session_thread_msg_new): Likewise. - (session_thread_msg_free): Likewise. - (session_thread_wait): Likewise. - * camel-text-index.c (text_index_compress_nosync): Likewise. - (text_index_compress_nosync): Likewise. - (camel_text_index_validate): Likewise. - * camel-vee-folder.c (vee_folder_remove_folder): Likewise. - (unmatched_check_uid): Likewise. - (folder_added_uid): Likewise. - (vee_folder_build_folder): Likewise. - (folder_changed_add_uid): Likewise. - (folder_changed_remove_uid): Likewise. - * providers/imap/camel-imap-search.c (imap_body_contains): Likewise. - * providers/pop3/camel-pop3-folder.c (cmd_list): Likewise. - (cmd_uidl): Likewise. - - * camel-data-cache.c (data_cache_init): Cast to CamelCopyFunc. - Fixes a warning. - -2003-05-15 Not Zed - - * camel-mime-utils.c (header_decode_word): Simplistic quick-fix - for #42710. Add a charset argument. If the data is 8 bit, try to - decode into the passed in charset (i.e. the message header?), at - worst, fall back to latin1, similarly to header_decode_text. - Fixed all callers to pass in a charset if available, or NULL. - -2003-05-14 Not Zed - - ** See bug #42540 - - * camel-service.c (camel_gethostbyname): pre-initialise the error - return to invalid, so if we cancel, we definetly get a bad result. - Also, for a valid return against result, not herr. - (camel_gethostbyaddr): Likewise. - -2003-05-13 Jeffrey Stedfast - - * providers/local/camel-local-folder.c (local_delete): Only delete - the index if it is non-NULL. Fixes bug #42763. - -2003-05-13 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c (imap_uid_array_to_set): Added - a note to the comment block for this function noting that uids - MUST be in sorted order. - - * providers/imap/camel-imap-folder.c (imap_expunge_uids_online): - Sort the uids before splitting them into UID set chunks. The code - that splits the uid array into sets expects the uids to be in - sorted order. Fixes bug #42854. - - * providers/imap/camel-imap-command.c (imap_command_start): - Re-enable camel_verbose_debug logging. - -2003-05-12 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_helo): If - host->h_name is NULL or an empty string, default back to using the - IP address rather than the hostname in the EHLO command. - -2003-05-13 Ettore Perazzoli - - * providers/imap/camel-imap-folder.c (d): Disable debugging. - - * providers/imap/camel-imap-command.c (d): Disable debugging. - - * providers/imap/camel-imap-search.c (d): Disable debugging. - -2003-05-02 Dan Winship - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): Don't call - g_utf8_validate on an empty message. Fixes a warning. - -2003-05-01 Jeffrey Stedfast - - Workaround for POS mailers like the one in bug #42045. - - * camel-mime-utils.c (header_decode_date): Make sure the numeric - timezone is between -1200 and 1200, otherwise it is invalid. - - * broken-date-parser.c (get_tzone): Make sure the numeric timezone - is between -1200 and 1200, otherwise it is invalid. - -2003-04-29 Dan Winship - - * Makefile.am (camel_lock_helper_SOURCES): Remove camel-lock.c - from here because it upsets automake 1.6 for some reason - (camel_lock_helper_LDADD): Add camel-lock.o here - -2003-04-29 Jeremy Katz - - * providers/imap/camel-imap-folder.c (parse_fetch_response): - body_len needs to be a size_t instead of int - -2003-04-22 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c: Disable debugging printfs. - - * providers/imap/camel-imap-store.c (imap_connect_online): #if 0 - out some code that parsed the namespaces since the results aren't - used and they generate debugging output. - -2003-04-23 Not Zed - - * providers/smtp/camel-smtp-transport.c (smtp_helo): only free the - host if it was set. removes a run-time warning. - - * camel-session.c (get_service): oops, the service owns the url - after we construct it. - -2003-04-22 Not Zed - - ** Should fix #41629, #41448, et al. - - * tests/folder/test10.c: a new torture test for object bag - creation/unreffing. - - * camel-url.c (camel_url_copy): new function to copy a url. - - * camel-object.c (camel_object_bag_new): add arguments for key - copy and key free functions. Fixed all callers. - (camel_object_bag_destroy): fix a memleak, free the bag key. - (camel_object_bag_get, camel_object_bag_reserve) - (camel_object_bag_abort, save_bag, save_object): Make the key a - void type, rather than char *. - (camel_object_bag_add): As above, and also copy the key. - (camel_object_bag_remove_unlocked): free the key using - bag->free_key. - - * camel-session.c (register_provider) - (camel_session_destroy_provider, get_service): Changed to use an - object bag instead of a hash table for the service 'cache'. - (service_cache_remove): Removed, no longer required. - -2003-04-21 Jeffrey Stedfast - - * camel-gpg-context.c (gpg_ctx_parse_status): Don't set seen_eof1 - here anymore once we get a trust metric. - (gpg_ctx_new): Init seen_eof1 to TRUE here. - (gpg_ctx_set_ostream): Change seen_eof1 to FALSE here this way we - only ever have to set this if we are expecting output. - (gpg_ctx_parse_status): Don't set seen_eof1 for importing either. - (gpg_ctx_op_step): Only FD_SET() those fd's that we have not yet - finished reading. - -2003-04-16 Jeffrey Stedfast - - * camel-url-scanner.c (camel_url_web_end): Urls are unlikely to - end with punctuation or closing braces, so strip any of those off - the end of the url. Fixes bug #41461. - - * tests/mime-filter/data/html.1.out: Removed a trailing \n at the - end of the file, this is incorrect (since out input file does not - contain one). - - * camel-mime-filter-tohtml.c (html_convert): Only output a
if - we found an eoln in the input. Along the same lines, don't write a - '\n' to the output buffer unless we've encountered that eoln in - the input. Fixes bug #41407. - -2003-04-17 Not Zed - - ** for #40989 - - * camel-text-index.c (text_index_delete): delete the block - file/key file directly, not just its files. - - * providers/local/camel-local-folder.c (local_delete): implement, - just delete the index file if it exists. - camel-store-delete-folder will delete other data (maybe it all - should be done here). - - * camel-block-file.c (camel_key_file_finalise): keep lock around - decrementing key file use count. - (camel_key_file_delete): new function to delete the key file (& - close it off). - (key_file_use): if we've been deleted, always fail. - (camel_block_file_finalise): only close the file if its a valid - fd. - (block_file_use): if we've been deleted, always fail. - (camel_block_file_delete): delete the block file & close. - (struct _CamelBlockFilePrivate): fix the !ENABLE_THREADS case to - still compile this. - - ** for #41163 - - * camel-multipart-signed.c (parse_content): Dont assume adding 1 - to line length will go to the next line. e.g. for dos lines that - end in \r\n. Fix for #41163. - (parse_boundary): util function to help above. - -2003-04-15 Jeffrey Stedfast - - * camel-gpg-context.c (gpg_verify): The gpg child process exiting - does not necessarily mean that we've ready everything that we can - from its pipes, so don't use gpg_ctx_op_exited() as a loop-exit - condition. If for some reason the gpg child process does exit (due - to an error), gpg_ctx_op_step() will eventually fail (as soon as - it has finished reading any data in the pipes) and cause the loop - to be terminated anyway. This fixes truncation of the gpg --verify - stderr output that Evolution displays as the "validity report" - (for lack of a better description). - (gpg_ctx_op_step): Removed some debugging printf's - (gpg_ctx_get_diagnostics): Use a bitfield to decide if we've - already flushed the diagnostics stream, much simpler (plus we have - plenty of bits to spare so might as well use them). - (gpg_ctx_new): Fixed another logic bug which determined whether or - not we should convert the gpg output from the locale charset into - UTF-8. - -2003-04-10 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c: Turn off debugging if - CAMEL_VERBOSE_DEBUG isn't set. - -2003-04-10 Not Zed - - * tests/mime-filter/data: filter data test cases. - - * tests/mime-filter/test-tohtml.c: New test for html filter. - - ** See bug #40969 - - * camel-mime-filter-tohtml.c (html_convert): Change the logic - slightly, scan a whole line within the main loop. - -2003-04-09 Jeffrey Stedfast - - * camel-gpg-context.c (gpg_ctx_get_utf8_diagnostics): Removed. I - just realised that we ALWAYS want to get gpg's stderr in UTF-8, so - the better solution (plus less code duplication) is to just have - the diagnostics buffer be a CamelStreamMem with a charset filter. - (gpg_ctx_new): Setup a filter stream to convert our gpg stderr - diagnostics into UTF-8 if needed. - (gpg_ctx_free): Unref the diagnostcis stream. - (gpg_ctx_parse_status): Flush the diagnostics stream if we are - going to use the data in an exception. - (gpg_ctx_op_step): Use camel_stream_write() to append to the - diagnostics stream rather than appending the buffer to a - GByteArray like we used to do. - (gpg_ctx_op_step): Flush the diagnostics stream here too. - (gpg_verify): Use a const char *diagnostics string here, forcing a - slight rearrangement of calls - use the const char *dignostics - before we gpg_ctx_free, otherwise we'll be passing free'd memory - off to the cipher_validity. - (gpg_ctx_get_diagnostics): Do the work here to flush the - diagnostics stream and nul-terminate the buffer. Also return const - now, instead of strdupping. No need for that. - (gpg_ctx_parse_status): Convert the user hint to UTF-8. - -2003-04-09 Jeffrey Stedfast - - * camel-gpg-context.c (gpg_ctx_get_utf8_diagnostics): Changed my - mind a bit on how I wanted this to work. Instead of aborting on an - illegal sequence, do like we do with camel-mime-filter-charset and - just skip over invalid sequences. Also, in the noop failure case, - close the iconv_t so we don't leak it. - -2003-04-09 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c (imap_body_decode): Save the - content size in a temp variable until after we've successfully - parsed all of the body_type_1part expr. Also fixed a type-o in the - body_type_mpart case that caused the parser to fail. - (imap_parse_body): On failure to parse the body, as we iterate - through the child nodes, set their children/parent/next nodes to - NULL so that content_info_free() won't double-free any of the - other nodes we have already free'd (or are about to free). - - * camel-gpg-context.c (gpg_ctx_get_utf8_diagnostics): New function - to get the UTF-8 version of the diagnostics (if the locale isn't - already UTF-8 safe). - (gpg_verify): Use the utf-8 diagnostics here. Also fixed a memleak - in the exception case. - - * camel-mime-filter-charset.c - (camel_mime_filter_charset_new_convert): NULL-protect the to/from - charsets in the g_warning call. - -2003-04-08 Jeffrey Stedfast - - Fixes for bug #40778. Probably others as well. - - * providers/imap/camel-imap-utils.c (parse_params): Return 0 on - success, or -1 on fail. The other small utility functions should - probably do the same, but I was too lazy to fix them. Setting - inptr to NULL is just lame. - (imap_body_decode): New function to correctly parse a BODY - response. - (imap_parse_body): Rewritten to use the above function. - -2003-04-08 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_helo): Make sure - host->h_name is not an empty string too? Apparently for one user - his resolved hostname is "". Go figure. Probably a broken system, - but easy enough to work around. - - * providers/pop3/camel-pop3-store.c (pop3_try_authenticate): If - store->engine->line is NULL, use _("Unknown error") as the error - string instead. - -2003-04-08 Not Zed - - * camel-folder-summary.c (camel_folder_summary_load): use - g_strerror, and use errno directly rather than ferrno(). - (summary_header_load): set errno when we get a version mismatch. - -2003-04-07 Jeffrey Stedfast - - * camel-gpg-context.c: Disable debug printf's - -2003-03-28 Jeffrey Stedfast - - * camel-sasl-gssapi.c (gssapi_challenge): If we are using the - heimdal krb5 implementation, don't free outbuf ever. Seems to - segfault if we do. - -2003-03-31 Jeffrey Stedfast - - * camel-mime-filter-enriched.c (enriched_to_html): Use strncasecmp - for matching the nofill and /nofill tags. Also fixed to handle - enriched tags that require tags. - -2003-03-28 Not Zed - - * providers/local/camel-spool-store.c (get_folder): remove unused - var. - - * providers/imap/camel-imap-utils.c (imap_parse_list_response): - moved an unused var to the #if 0'd out block. - - * providers/imap/camel-imap-store.c - (parse_list_response_as_folder_info): remove unused vars. - - * camel-index-control.c (main): deifne camel_init() before using - it. - - * camel-vee-store.c (vee_get_folder): removed unused var. - - * camel-stream-mem.c (stream_write): warning -> fixme. - - * camel-stream-filter.c (_CamelStreamFilterPrivate): Add a ; to - the end of the struct definition. - - * camel-store.c (camel_store_delete_folder): remove unused var. - (camel_store_rename_folder): " - (camel_store_unsubscribe_folder): " - - * camel-mime-part.c (write_to_stream): Changed warning into a - TODO. - (construct_from_parser): removed warning, the code was fixed. - - * camel-mime-message.c (construct_from_parser): Remove the - warning, the code was fixed. - - * camel-mime-filter-enriched.c (camel_mime_filter_enriched_new): - Remove unused var. - - * camel-medium.c (camel_medium_get_header): Removed warning, and - changed docs to reflect it. - - * camel-gpg-context.c (gpg_ctx_parse_status): handle MODE_EXPORT - as a noop (warning). - - * camel-folder.c (get_message_user_tag): changed a warning into a - fixme (its not that important). - (camel_folder_get_message_user_tag): " - - * camel-data-cache.c (data_cache_finalise): removed unused vars. - (data_cache_expire): " - -2003-03-27 Jeffrey Stedfast - - * camel-sasl-gssapi.c (gssapi_challenge): Get rid of debug - printf's that are no longer needed. In the case of errors, don't - release the outbuf gss_buffer_t since it shouldn't be set. Also - g_free (str) when we are done with it. - - * camel-mime-utils.c (header_encode_phrase_merge_words): When we - remove a node from the list, make sure to g_list_free_1(). - (header_encode_phrase_merge_words): Don't use - CAMEL_FOLD_PREENCODED as the upper-bound for merged-word length if - the merged-word will not be an rfc2047 encoded word. Instead, use - CAMEL_FOLD_SIZE-8 (which is the value we use in other places for - determining upper-bound lengths). Solves bug #38659. - -2003-03-27 Dan Winship - - * camel-url.c (append_url_encoded): Like camel_url_encode, but - works directly on an existing GString. - (camel_url_to_string, output_param): Use it. - (camel_url_encode): Likewise. Remove "escape_unsafe" arg since the - "unsafe" chars are the ones that should *always* be escaped, and - the places we were passing FALSE were wrong. - (camel_url_decode): replace with a new version - - * camel-file-utils.c (camel_file_util_safe_filename): Remove extra - arg to camel_url_encode. - - * tests/misc/url.c (main): Add tests of basic URL parsing and - unparsing - -2003-03-28 Not Zed - - * - camel-mime-part-utils.c (simple_data_wrapper_construct_from_parser): - Do a more thorough check for html marked as text/plain. Check - that the text starts with - - * camel-sasl-gssapi.c (camel_sasl_gssapi_finalize): Pass in the - addresses of the second args to the delete/release functions. - -2003-03-27 Not Zed - - * camel-object.c (camel_object_bag_list): Ignore whether or not - the bag is currently reserved. We'll miss the new potential - object, but only 1. Should address #40103. - -2003-03-25 Jeffrey Stedfast - - * camel-service.c (camel_gethostbyaddr): Don't use setv when we - don't need the stdarg interface. - (camel_gethostbyname): Same. - -2003-03-24 Jeffrey Stedfast - - * camel-folder-search.c (search_user_tag): This expression can - never return an array. We must always return a string value. - -2003-03-24 Timo Sirainen - - * camel-imap-command.c (imap_read_untagged) Integer overflow fix. - If server sent a huge literal length, only a few bytes of memory - was allocated to it, but server could write as much data there as - it wanted. - -2003-03-21 Jeffrey Stedfast - - Camel part of the fix for Lewing's bug #39204. Second half of the - patch should also fix it so that text/plain parts that are - detected as being text/html are rendered as html (not that I agree - with this mind you, but corporate customers want this "feature"). - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): If the part is - text/html and doesn't have a charset and we are able to find a - charset in the meta tags of the html content, set the charset - param on the content-type. - (camel_mime_part_construct_content_from_parser): After setting the - content object on the mime part, re-set the content-type of the - content object back to the one from the parser (as it may contain - changes from the original - see changes made to the ct in - simple_data_wrapper_construct_from_parser for details). - -2003-03-21 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (camel_certdb_nss_cert_get): continue - reading the cert file until we've read it all or get a non-EINTR - errno. - -2003-03-21 Jeffrey Stedfast - - * camel-sasl-gssapi.c: #include instead of - #include - -2003-03-20 Jeffrey Stedfast - - * camel-sasl.c: Plug in GSSAPI support. - - * camel-sasl-gssapi.[c,h]: Various fixes to make it compile (fixed - type-o's mostly). - -2003-03-20 Dan Winship - - Handle raw 8-bit From data "correctly". (The same way we handle - raw 8-bit Subject data.) - - * camel-mime-utils.c (header_decode_mailbox): Take a charset arg - and pass it to header_decode_string. - (header_decode_address): Take a charset arg and pass it to - header_decode_mailbox. - (header_mailbox_decode): Likewise. - (header_address_decode): Take a charset arg and pass it to - header_decode_address. - - * camel-folder-summary.c (summary_format_address): Take a charset - arg and pass to header_address_decode. - (message_info_new, camel_message_info_new_from_header): Pass - charset to summary_format_address - - * camel-internet-address.c (internet_decode): Update for - header_address_decode change. (Unfortunately we don't have a - charset to pass here.) - - * camel-mime-message.c (camel_mime_message_build_mbox_from): Move - this here from camel-mbox-summary since the same functionality is - needed by evolution-mail too (and update for header_address_decode - change) - - * providers/local/camel-mbox-summary.c - (camel_mbox_summary_build_from): Moved to CamelMimeMessage - -2003-03-17 Jeffrey Stedfast - - * camel-mime-part.c (process_header): Removed unused variable left - over from my previous fix. - - * providers/smtp/camel-smtp-transport.c (smtp_send_to): Don't pass - 'has_8bit_parts' to smtp_data() anymore. - (smtp_data): No longer takes 'has_8bit_parts' argument. Ignore - whether or not the message has 8bit parts when deciding what the - required encoding type we need to enforce. Fixes bug #39744. - -2003-03-13 Jeffrey Stedfast - - * camel-mime-part.c (process_header): Use - header_contentid_decode() as this new function should be safer - than the hack that we had before. - - * camel-mime-utils.c (header_contentid_decode): New function to - try and parse a content-id string in such a way as to work around - some of the known bugs in other MIME implementations. Try to be as - "safe" as we can - ie. don't allow for more than 1 @ (since the - mailer uses "@@@%d" as a fake content-id value for parts without - content-ids) and don't allow for invalid content-type chars. - -2003-03-13 Jeffrey Stedfast - - * camel-folder.c (get_uids): Don't add bogus uids to the uid - array. Might fix bug #38868 (it's the only way I can figure that - camel_folder_get_message_info() could possibly return NULL for the - Outbox folder). - -2003-03-12 Not Zed - - * camel-object.c (remove_bag): removed, it was double-freeing the - key. - (save_object): Just save the object in an array. - (camel_object_bag_destroy): first save the object bag's objects in - a list, then remove them one at a time from the bag since we can't - remove hash table entries while we're in a foreach (PITA glib - shit). For #39486. - (camel_object_bag_*): killed some warnings. - -2003-03-09 Jeffrey Stedfast - - * camel-url-scanner.c (camel_url_addrspec_end): Doh! If inptr == - pos + 1, then return FALSE (before it was checking for inptr == - pos, but it will never be pos). - -2003-03-07 Not Zed - - * camel-vee-folder.c (vee_search_by_expression): handle a null - return from search_by_expression, for bug #33786. - -2003-03-06 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c (imap_next_word): - s/g_strncasecmp/strncasecmp/g - - * camel-iconv.c: Updated to be an exact copy of e-iconv (except - names changed). We don't use this yet, but we may in the future. - - * camel-url.c (camel_url_new_with_base): Here too. - - * camel-sasl-kerberos4.c (krb4_challenge): Use camel_strdown() - here instead of g_strdown() since the latter has been deprecated. - - * providers/imap/camel-imap-utils.c (imap_parse_body): Use - camel_strdown() since g_ascii_strdown() does not do what we - thought. - - * providers/imap/camel-imap-store.c: - s/strstrcase/camel_strstrcase/g - - * providers/imap/camel-imap-folder.c (do_append): - s/strstrcase/camel_strstrcase/ - (handle_copyuid): Same. - - * string-utils.c (camel_strdown): New function because the - g_ascii_strdown interface sucks. - (camel_strstrcase): Renamed from strstrcase. - -2003-03-06 Jeffrey Stedfast - - * camel-text-index.c (camel_utf8_next): Same as below. - - * camel-search-private.c (camel_utf8_getc): Updated since not all - platforms/compiles support __inline__. - -2003-03-06 Jeffrey Stedfast - - * camel-mime-part.c (camel_mime_part_get_encoding): Get rid of the - const return - it mismatches the prototype and we don't need it - anyway. Fixes bug #39173. - -2003-03-06 Jeffrey Stedfast - - Fixes for bug #39170 - - * camel-store-summary.c (camel_store_info_set_string): Remove - return keyword. - - * camel-session.c (camel_session_thread_msg_free): Remove return - keyword. - (camel_session_thread_wait): Same. - - * camel-index.c (camel_index_cursor_reset): Remove return keyword. - -2003-03-06 Jeffrey Stedfast - - Fixes for bug #39168 - - * providers/local/camel-spool-summary.c: Get rid of the empty - private struct. - - * providers/local/camel-mbox-summary.c: Get rid of the empty - private struct. - - * camel-vee-store.c: Get rid of the empty private struct. - - * camel-mime-filter-from.c: Get rid of the empty private struct. - -2003-03-05 Jeffrey Stedfast - - * providers/sendmail/camel-sendmail-transport.c - (sendmail_send_to): Add a CRLF filter to the output stream to - convert any CRLF sequences into plain old line-feeds to work - around a bug in some local transport programs. - -2003-03-04 Jeffrey Stedfast - - * camel-object.h: s/class/klass in one place so that the header is - c++-safe. - -2003-03-03 Jeffrey Stedfast - - * camel-tcp-stream-openssl.c (camel_tcp_stream_ssl_new): Updated - to use the new API from a fe commits ago for the NSS stream. This - is just to make it compile, but does not update the behaviour to - act like the NSS stream. Note that people shouldn't be using - OpenSSL anyway. - (camel_tcp_stream_ssl_new_raw): Same. - - * camel-process.[c,h]: New source file containing convenience - functions for process creation/termination mainly for use with - Pipe filters but should be usable for anything we want. - - * camel-io.[c,h]: New source files implementing read/write system - calls with proper error checking and cancellation - (ie. StreamFs::read/write and CamelTcpStreamRaw::read/write). No - sense duplicating the same code over and over. Now I can use this - same code easily in other i/o code (such as Pipe filters and gpg - code?). - -2003-03-03 Not Zed - - * camel-store.c (camel_store_unsubscribe_folder): Do similar - folder != NULL checking as for delete_folder before passing a NULL - to object_bag_remove. - -2003-02-28 Jeffrey Stedfast - - * camel-http-stream.c (http_connect): Here too. - - * providers/smtp/camel-smtp-transport.c (connect_to_server): Same - as IMAP and POP. - - * providers/imap/camel-imap-store.c (connect_to_server): Same as - the POP3 code. - - * providers/pop3/camel-pop3-store.c (connect_to_server): Pass in - appropriate flags for camel_tcp_stream_ssl_new*() functions. - - * camel-tcp-stream-ssl.c (enable_ssl): Not all ssl/tls streams - will want to allow each of SSLv2, SSLv3 and TLSv1 so use flags to - decide which to enable/disable. - (camel_tcp_stream_ssl_new): Now takes a flags argument to mask out - which SSL/TLS versions the stream should be compatable with. - (camel_tcp_stream_ssl_new_raw): Same. - -2003-02-27 Jeffrey Stedfast - - * camel-stream-filter.c: Add a 'flushed' state variable to the - private struct. - (do_read): Set p->flushed to TRUE after we call - camel_mime_filter_complete() on all the filters. - (do_reset): Set p->flushed to FALSE. - (do_eos): Make sure the filters have been flushed before returning - that the stream is at EOS. - - * camel-mime-filter-canon.c (complete): Don't add a eol - - otherwise we will fail to verify some mutt signatures that do not - have a blank line before the boundary line (and note that the last - \n before the boundary really belongs to the boundary anyway) so - #if 0 this code out for now. - -2003-02-27 Not Zed - - * camel-multipart-signed.c: Undo jeff's changes. - - * providers/local/camel-spool-store.c (scan_dir): Fix a paste-o in - the object_bag_get key. - -2003-02-26 Jeffrey Stedfast - - * camel-multipart-signed.c: Updated to use g_alloca instead of - alloca so that we can skip all the #ifdef checks and skip checking - for alloca in configure.in and all that foo. - - * camel-store.c (camel_store_delete_folder): Make sure the folder - is non-NULL before trying to remove it from the store's - object-bag. - -2003-02-25 Jeffrey Stedfast - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): canonicalise the - charset name (if it is an iso charset) so that our strncasecmp to - see if it is an iso-8859-# charset will be guarenteed to work on - all systems. - (canon_charset_name): New function to return the canonical iso - charset name. - (simple_data_wrapper_construct_from_parser): If the charset is - NULL *or* the charset == "us-ascii" then check that it is 7bit - clean to decide if it is rawtext (we did not check the case where - charset was "us-ascii" before). - -2003-02-25 Jeffrey Stedfast - - * camel-mime-message.c: Same as the ones below. - - * camel-mime-part.c: Reverted back to pre-camel-iconv - - * camel-filter-search.c: Same as below. - - * camel-folder-summary.c: Reverted back to pre-camel-iconv - - * camel.c (camel_init): Reverted to pre-camel-iconv - - * camel-charset-map.c (camel_charset_locale_name): Removed (part - of the revert). - (camel_charset_canonical_name): Same. - - * camel-mime-filter-charset.c: Revert back to using e_iconv from GAL. - - * camel-mime-part-utils.c: Revert back to using e_iconv from GAL. - - * camel-mime-utils.c: Revert back to using e_iconv from GAL. - - * camel-sasl-digest-md5.c: Revert back to using e-iconv from GAL. - -2003-02-24 Jeffrey Stedfast - - * camel-charset-map.c (camel_charset_canonical_name): g_alloca - (strlen (charset) + 1) so we don't overflow the buffer. - - * providers/pop3/camel-pop3-stream.c (stream_write): Don't write - the passwd, fixes "bug" #38601. - - * camel-iconv.c: Make bucket->refcount 31 bits and bucket->used 1 - bit instead of having each use their own 32bit int. - (iconv_cache_bucket_expire): Use g_iconv_close() here, missed this - before. - (camel_iconv): Might as well call g_iconv here even though it just - calls iconv directly. - -2003-02-21 Jeffrey Stedfast - - * camel-iconv.c (camel_iconv_charset_name): New function...back - from the depths of hell from whence it came originally. Turns out - that g_iconv_open() is lame and can't handle all the stuff we used - to handle in e_iconv_charset_name(). - (camel_iconv_open): Use camel_iconv_charset_name() on the to/from - charsets rather than camel_charset_canonical_name(). Now maybe - g_iconv_open will work for charsets such as "ks_c_5601-1987". - - * providers/pop3/camel-pop3-store.c (pop3_connect): Reget the - capabilities after a successful authentication. - - * providers/pop3/camel-pop3-engine.c (get_capabilities): If we are - in the TRANSACTION state and CAPA did not list UIDL as a supported - command, try checking for it the hard way. - -2003-02-23 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_data): Do it the - same way we just made the sendmail code do it. - - * providers/sendmail/camel-sendmail-transport.c - (sendmail_send_to): My last change but in a better way. - -2003-02-22 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_data): Remove all - Bcc headers before sending to the smtp server. - - * providers/sendmail/camel-sendmail-transport.c - (sendmail_send_to): Remove all Bcc headers before sending to - sendmail. - -2003-02-20 Jeffrey Stedfast - - * camel.c (camel_init): Call camel_iconv_init(). - (camel_shutdown): Call camel_iconv_shutdown(). - - * camel-sasl-digest-md5.c (digest_response): Updated to use - camel-iconv and the new camel-charset-map functions. - - * camel-mime-utils.c: Updated to use camel-iconv and the new - camel-charset-map functions. - - * camel-mime-part-utils.c (check_html_charset): Use - camel_charset_canonical_name() instead of e_iconv_charset_name() - which is longer available. - (convert_buffer): Use camel-iconv. - (simple_data_wrapper_construct_from_parser): Since - camel_charset_iso_to_windows() returns the charset in it's - canonical format, no need to re-canonicalise it. - - * camel-mime-part.c (process_header): Use - camel_charset_canonical_name() instead of e_iconv_charset_name() - which is longer available. - - * camel-mime-message.c (process_header): Use - camel_charset_canonical_name() instead of e_iconv_charset_name() - which is longer available. - - * camel-mime-filter-charset.c: Use camel-iconv. - - * camel-folder-summary.c (message_info_new): Use - camel_charset_canonical_name() instead of e_iconv_charset_name() - which is longer available. - (content_info_new): Use camel_charset_locale_name(). - (camel_message_info_new_from_header): Same as message_info_new(). - - * camel-search-private.c: Use g_alloca() instead of alloca(). - - * camel-filter-search.c (check_header): Use - camel_charset_canonical_name() instead of e_iconv_charset_name() - which is longer available. - - * camel-charset-map.c (camel_charset_locale_name): New function, - replaces e_iconv_locale_charset(). - (camel_charset_canonical_name): New function, similar to - e_iconv_charset_name() but instead of returning the iconv-friendly - name, it returns the canonical name. (g_iconv will do the - iconv-friendly name conversions for us). - -2003-02-20 Jeffrey Stedfast - - * camel-filter-search.c (run_command): Redirect program's stdout - and stderr to /dev/null - - * camel-filter-driver.c (pipe_to_system): Redirect the program's - stderr to /dev/null - (pipe_to_system): Write the pipe to a mem stream and use the mem - stream in the parser. Also, when setting an exception get the - errno from the parser so we can give more info about the error to - the user. - -2003-02-19 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (stream_connect): Fixed a type-o in the - ENABLE_IPv6 ifdef section. - -2003-02-19 Jeffrey Stedfast - - * camel-filter-driver.c (pipe_message): New filter action that - pipes the message source to the user-program and reads back the - modified message and replaces driver->priv->message with the new - message object. - (do_copy): Check p->modified to make sure the message hasn't been - modified by the pipe-message action - if it has been modified, - default to the slower camel_folder_append_message() way of - copying. - (do_move): Same. - (pipe_to_system): Set p->modified to TRUE if the user-program gave - us back a message stream and we were able to parse it. - (camel_filter_driver_filter_message): If the message has been - modified, always use camel_folder_append_message() when appending - it to the default folder. - -2003-02-14 Jeffrey Stedfast - - * camel-folder-search.c: Added a (get-size ) function to fix bug - #38073. - (search_get_size): Implemented. - -2003-02-14 Jeffrey Stedfast - - * camel-url-scanner.c (url_scanner_table_init): Mark chars with - the high-bit set as CTRL chars. - (camel_url_web_end): If the char before the start of the url is an - open-brace, watch out for the matching close-brace. - (camel_url_file_end): Same. - -2003-02-14 Jeffrey Stedfast - - * camel-smime-context.c (smime_get_password): Same as the gpg and - pkcs7 contexts. - - * camel-sasl-popb4smtp.c (popb4smtp_challenge): Updated for - camel_session_get_password(). - - * camel-pkcs7-context.c (get_password): Same as the gpg code. - - * camel-gpg-context.c (gpg_ctx_parse_status): Updated for - camel_session_get_password(). - - * providers/smtp/camel-smtp-transport.c (smtp_connect): No need to - set USER_CANCEL exception here as it is done by - camel_session_get_password(). Also updated for the new - get_password() API change. - - * providers/imap/camel-imap-store.c (imap_auth_loop): Updated for - camel_session_get_password() changes. We don't need to play the - "bad passwd" game here too, do we? Bah, probably should but I - don't feel like it for now. Maybe when we rewrite the IMAP - provider. - - * camel-session.c (camel_session_get_password): Now takes a - 'reprompt' argument that will force user-input to be given even if - we have the passwd cached. - - * providers/pop3/camel-pop3-store.c (pop3_connect): Instead of - uncaching the passwd after we receive a -ERR from the POP server, - set 'reprompt' to TRUE to force user-input for the next password - prompt (ie, make sure the front-end knows not to just return the - cached value). The front-end can then decide to fill-in the - user-input field with the last passwd that the user supplied. - (pop3_try_authenticate): Now takes a reprompt argument which we - pass into camel_session_get_password(). - -2003-02-05 Dan Winship - - * Makefile.am (libcamelincludedir): Define in terms of - privincludedir. - (camellibexecdir): Define in terms of privlibexecdir - (libcamel_la_LDFLAGS): Remove -rpath. (automake will add that) - - * providers/imap/Makefile.am (libcamelimapincludedir): Define in - terms of privincludedir. - (INCLUDES): Remove -I$(includedir) - * providers/local/Makefile.am: Likewise - * providers/nntp/Makefile.am: Likewise - * providers/pop3/Makefile.am: Likewise - * providers/sendmail/Makefile.am: Likewise - * providers/smtp/Makefile.am: Likewise - -2003-02-04 Not Zed - - * camel-object.c (camel_object_bag_new): Init bag->owner to 0. - -2003-01-31 Not Zed - - * camel-object.c (camel_object_bag_*): Changed to use a posix - semaphore instead of a condition variable + flag to reserve the - object bag because e_mutex_cond is broken. - -2003-02-04 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c (imap_parse_body): Use - g_ascii_strdown() instead of g_strdown, since g_strdown is - deprecated. - (imap_parse_body): Same. - - * providers/imap/camel-imap-folder.c (decode_internaldate): Use - strncasecmp() here too. - (parse_fetch_response): And here. - (camel_imap_folder_selected): Here too. - - * providers/imap/camel-imap-utils.c (imap_namespace_decode): Use - strncasecmp() instead of g_strncasecmp() because the latter is - deprecated. - - * providers/imap/camel-imap-store.c (imap_get_capability): Again here. - (hash_folder_name): Here too. - (compare_folder_name): And here. - (get_folder_online): Again. - (get_folder_offline): And again. - - * providers/imap/camel-imap-folder.c (camel_imap_folder_selected): - Same as below again. - - * providers/imap/camel-imap-command.c (camel_imap_response_free): - Same as below. - - * providers/smtp/camel-smtp-transport.c (smtp_data): Use - strcasecmp() because g_strcasecmp() is deprecated. - - * camel-url.c (camel_url_new_with_base): Use g_ascii_strdown() - instead of g_strdown, since g_strdown is deprecated. - -2003-01-28 Jeffrey Stedfast - - * camel-sasl-gssapi.c (gssapi_challenge): Pass in some default - flags to gss_init_sec_context() (these default flags are defined - as a MUST in rfc1964). - -2003-01-22 Hans Petter Jansson - - * Makefile.am: $(libexec) -> $(libexecdir) - -2003-01-22 Ettore Perazzoli - - * providers/imap/Makefile.am (libcamelimapincludedir): Update to - the new $(BASE_VERSION)-versioned path. - * providers/smtp/Makefile.am (libcamelsmtpincludedir): Likewise. - * providers/sendmail/Makefile.am (libcamelsendmailincludedir): - Likewise. - * providers/pop3/Makefile.am (libcamelpop3includedir): Likewise. - * providers/nntp/Makefile.am (libcamelnntpincludedir): Likewise. - * providers/local/Makefile.am (libcamellocalincludedir): Likewise. - - * camel-lock-client.c (camel_lock_helper_init): Use - CAMEL_LIBEXECDIR instead of CAMEL_SBINDIR to find - camel-lock-helper. - - * Makefile.am: Install camel-lock-helper and camel-index-control - in $(libexec)/evolution/$(BASE_VERSION)/camel. Install - libcamel.la in $privlibdir. - (install-exec-hook): Update for the new location of - camel-lock-helper. - (libcamelincludedir): Version using $(BASE_VERSION). - (INCLUDES): Define CAMEL_LIBEXECDIR. - -2003-01-21 Jeffrey Stedfast - - * camel-mime-filter-canon.c (complete): Set the backbuflen to 0 so - that calling us again won't re-flush the same data. - -2003-01-17 Larry Ewing - - * camel-mime-filter-enriched.c (enriched_to_html): only grow the - buffer when we are out of space. - -2003-01-14 Not Zed - - * camel-mime-parser.c (folder_scan_step): If we have no - content-type header, set it to text/plain explcitly, rather than - NULL, because some code doesn't handle NULL. - -2003-01-14 Jeffrey Stedfast - - * camel-sasl-gssapi.[c,h]: New source files implementing the - GSSAPI SASL mechanism. - -2003-01-13 Not Zed - - * camel-mime-filter-tohtml.c: fix header include order. - - * camel-object.c (camel_object_bag_reserve): Add an assert to - check we're not trying to reserve the bag more than once in a - given thread. - (camel_object_bag_list): If we have reserved the bag, dont try and - cond wait. Fixes a deadlock. - - * camel-mime-filter-tohtml.c (writeln): Read the characters as - utf8, rather than as 8 bit bytes. Remove the PRESERVE_8BIT as it - has no meaning. Also change the default logic slightly so that 8 - bit or greater characters are properly converted to entities. - - * camel-utf8.c (camel_utf8_getc_limit): new function, gets a utf8 - char, bounded by an end pointer. - -2003-01-07 Dan Winship - - * camel-provider.h (CamelProvider): add a "translation_domain" - field. (NULL for all providers in the camel source tree itself). - - * camel-session.c (register_provider): Translate provider strings - in the correct domain - -2003-01-06 Not Zed - - * camel-store.c (store_sync): init local exception before doing - anything. fixes a crash. - -2003-01-04 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_send_to): Instead of - checking recipients != NULL, check that camel_address_length - (recipients) != 0 since it is illegal for recipients to be NULL - (camel_transport_send_to already checks this). - -2002-12-17 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c: Replace calls to - g_string_sprintfa() with g_string_append_printf() since the former - seems to have been deprecated. - - * providers/imap/camel-imap-search.c: Same. - - * providers/imap/camel-imap-folder.c: Here too. - - * providers/local/camel-mbox-summary.c: And here. - - * providers/local/camel-local-summary.c: Replace - g_string_sprintf() with g_string_printf(). - - * camel-data-cache.c (data_cache_expire): Replace - g_string_sprintf() with g_string_printf(). - - * camel-url.c: Replace calls to g_string_sprintfa() with - g_string_append_printf() since the former seems to have been - deprecated. - - * camel-service.c: Same. - - * camel-mime-utils.c: Here too. - -2002-12-16 Jeffrey Stedfast - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): Detect text/html - parts that were marked as text/plain and re-tag them as text/html - parts. Note: currently just checks if the first non-lwsp char is a - '<' - but we might need to be smarter about this? *sigh* Stupid - Windows mailers. - - * camel-mime-filter-tohtml.c (camel_text_to_html): New convenience - function to replace calls to e_text_to_html() in the - mailer/composer etc. - - * camel.h: #include some headers we had forgotten to add - previously, also added camel-mime-filter-enriched.h. - - * camel-mime-filter-enriched.[c,h]: New stream filter to convert - text/enriched and text/richtext into HTML. - -2002-12-15 Jeffrey Stedfast - - * camel-multipart-signed.c (camel_multipart_signed_verify): Don't - apply the CANON_STRIP filter here, since we are verifying whatever - raw data we received (all we want to do is convert o the canonical - CRLF format). - -2002-12-10 Jeffrey Stedfast - - * camel-mime-filter-tohtml.c (html_convert): Use camel-url-scanner - instead of regex. - -2002-12-09 Jeffrey Stedfast - - * camel-url-scanner.c (camel_url_addrspec_end): Fixed to not be - fooled in the case where the address is followed immediately by a - period. - (camel_url_web_end): Made more robust. - (camel_url_scanner_scan): Oops. We need to set the match->pattern - string pointer to the correct pattern before executing the - start/end methods (as some of them rely on this info). - -2002-12-09 Jeffrey Stedfast - - * camel-url-scanner.c: New code to scan for patterns (used only - for url pattern matching atm, but we may find other uses for this - and thus rename it? I dunno). Uses ETrie. - -2002-12-07 Not Zed - - * camel-data-cache.c (data_cache_init): Use a bag instead of a - hashtable to track the cache streams. - (data_cache_finalise): Same. - (free_busy): No longer needed. - (data_cache_expire): use bag instead of hashtable. - (stream_finalised): No longer required. - (camel_data_cache_add): objectbagise - (camel_data_cache_get): " - (camel_data_cache_remove): " - (data_cache_path): Set the now expired date before running expiry, - so it plays better with multiple threads. Still a couple of - harmless races. - -2002-12-06 Not Zed - - * providers/local/camel-spool-store.c (scan_dir): folders -> - object bag. - (get_folder_info_mbox): folders -> object bag. - - * providers/local/camel-mh-store.c (folder_info_new): folders -> - object bag. - - * providers/local/camel-maildir-store.c (scan_dir): folders -> - object bag. - - * providers/local/camel-local-store.c (rename_folder): folders -> - object bag. - - * camel-private.h (CamelStorePrivate): Remove 'cache' lock, - handled by the objectbag. - - * providers/imap/camel-imap-store.c (copy_folder): Removed. - (imap_store_refresh_folders): folders -> object bag. - (get_folder_counts): folders -> object bag. - - * camel-vee-store.c (vee_get_folder): changes for folders - objectbag. - (vee_get_folder_info): Change to use folders objectbag. Also, - dont refresh the base folder if we're in FAST mode. - (build_info): Removed, no longer needed. - (vee_rename_folder): Fixed for folders objectbag. - - * camel-store.c (camel_store_init): init the folders objectbag. - (camel_store_finalize): Destroy the folders object bag. - (folder_matches): - (folder_finalize): Removed, now handled implicitly by the - objectbag. - (camel_store_get_folder): object bag changes. - (camel_store_delete_folder): " - (get_subfolders): Removed, now handled without a callback. - (camel_store_rename_folder): Changed to use object bag of folders. - (trash_add_folder): Removed. - (init_trash): use folders object bag. - (copy_folder_cache): - (sync_folder): Removed, no longer needed. Weird arsed code anyway. - (store_sync): Use folder object bag instead of hashtable. - (camel_store_unsubscribe_folder): " - (camel_store_init): remove cache_lock init, no longer used. - (camel_store_finalize): Same for cleanup. - -2002-12-05 Not Zed - - * camel-store.h (struct _CamelStore): change folders from a - hashtable into a CamelObjectBag. - - * camel-object.c (camel_object_ref): Use type_lock instead of - class lock for ref counting. - (camel_object_unref): Use type_lock instead of class lock for - unref. - (camel_object_unref): If the object is 'bagged', then also look - hooks, and remove it from any bags. - (camel_object_bag_new): - (camel_object_bag_destroy): - (camel_object_bag_add): - (camel_object_bag_get): - (camel_object_bag_remove_unlocked): - (camel_object_bag_list): - (camel_object_bag_abort): - (camel_object_bag_remove): New functions to implement a utility - object which can manage a 'bag' of weakly ref'd children in an - atomic & threadsafe way. - -2002-12-04 Jeffrey Stedfast - - * providers/imap/camel-imap-store-summary.c - (camel_imap_store_summary_add_from_full): Properly handle the case - where the namespace is "". Fixes bug #34975 - -2002-12-03 Jeffrey Stedfast - - * broken-date-parser.c (get_tzone): Fixed to not get false - positives when the token is shorter than the actual timezone - string (but matches the first little bit of it). - (datetok): Modified to properly handle when the first char of a - token is a special char (such as a '-') that is also used as a - token delimiter. - -2002-11-21 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (stream_read): Use the new - camel_operation_cancel_prfd() function to get the cancellation fd - so we can poll on it for cancellation stuff. - (stream_write): Same. - -2002-11-22 Not Zed - - * camel-operation.c (camel_operation_cancel_prfd): Implement, gets - a nspr pr filedesc to poll/wait on - (struct _CamelOperation): include a pr filedesc. - -2002-11-21 Not Zed - - * providers/imap/camel-imap-store-summary.c - (camel_imap_store_summary_namespace_find_path): If we have a - namespace of "", then always match any path. - (camel_imap_store_summary_namespace_find_full): Same, for full - names. Should address #33309 & friends. - -2002-11-19 Radek Doulik - - * camel-mime-filter-tohtml.c (html_convert): added - CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT flag - -2002-11-18 Rodney Dawes - - * tests/*/Makefile.am: Removed $(GNOME_LIBDIR) and $(GNOMEUI_LIBS) - -2002-11-15 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (imap_connect_online): If the - namespace is at/below INBOX, check for the INBOX explicitly (since - it obviously won't show up in a LSUB INBOX.*). If either INBOX is - not returned in the response or if the folder flags contain - \NoSelect, subscribe to INBOX and then try LSUB again. - -2002-11-11 Jeffrey Stedfast - - * camel-mime-filter-tohtml.c (html_convert): Rewritten. Much much - much cleaner implementation now, though uses malloc/free more - often than I'd like. - -2002-11-11 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (get_message_simple): Use - g_strerror when setting an exception string (we need it to be in - UTF-8). - - * providers/pop3/camel-pop3-store.c (pop3_try_authenticate): Use - g_strerror when setting an exception string (we need it to be in - UTF-8). - - * providers/pop3/camel-pop3-folder.c (pop3_refresh_info): Use - g_strerror when setting an exception string (we need it to be in - UTF-8). - (pop3_get_message): Same. - - * providers/local/camel-spool-summary.c (spool_summary_sync_full): - Use g_strerror when setting an exception string (we need it to be - in UTF-8). - (spool_summary_check): Here too. - - * providers/local/camel-spool-store.c (construct): Use g_strerror - when setting an exception string (we need it to be in UTF-8). - (get_folder): Same. - (scan_dir): Here too. - - * providers/local/camel-spool-folder.c (spool_lock): Use - g_strerror when setting an exception string (we need it to be in - UTF-8). - - * providers/local/camel-mh-summary.c (mh_summary_check): Use - g_strerror when setting an exception string (we need it to be in - UTF-8). - - * providers/local/camel-mh-store.c (delete_folder): Use g_strerror - when setting an exception string (we need it to be in UTF-8). - - * providers/local/camel-mbox-summary.c (summary_update): Use - g_strerror when setting an exception string (we need it to be in - UTF-8). - (mbox_summary_sync_full): Here too. - (mbox_summary_sync_quick): Same. - (mbox_summary_sync): Also here. - (camel_mbox_summary_sync_mbox): Again here. - - * providers/local/camel-mbox-folder.c (mbox_lock): Use g_strerror - when setting an exception string (we need it to be in UTF-8). - (mbox_append_message): Same. - (mbox_get_message): Here too. - - * providers/local/camel-maildir-summary.c (maildir_summary_load): - Use g_strerror when setting an exception string (we need it to be - in UTF-8). - (maildir_summary_check): Same. - - * providers/local/camel-maildir-store.c (get_folder): Use - g_strerror when setting an exception string (we need it to be in - UTF-8). - (delete_folder): Same. - (delete_folder): Here too. - - * providers/local/camel-local-summary.c (local_summary_sync): Use - g_strerror when setting an exception string (we need it to be in - UTF-8). - - * providers/local/camel-local-store.c (get_folder): Use g_strerror - when setting an exception string (we need it to be in UTF-8). - (create_folder): Same. - (xrename): Here too. - (rename_folder): And here. - (delete_folder): Also here. - - * camel-provider.c (camel_provider_init): For debugging printfs, - we want to use normal strerror (we want locale charset, not - UTF-8). - - * camel-movemail.c (camel_movemail): Use g_strerror when setting - an exception string (we need it to be in UTF-8). - (movemail_external): Same. - (camel_movemail_copy_file): Here too. - (camel_movemail_solaris): Also here. - - * camel-mime-utils.c (rfc2047_decode_word): For debugging printfs, - we want to use normal strerror (we want locale charset, not - UTF-8). - (header_encode_param): Same. - - * camel-mime-part-utils.c (convert_buffer): For debugging printfs, - we want to use normal strerror (we want locale charset, not - UTF-8). - - * camel-lock-client.c (camel_lock_helper_init): Use g_strerror - when setting an exception string (we need it to be in UTF-8). - - * camel-data-cache.c (camel_data_cache_remove): Use g_strerror - when setting an exception string (we need it to be in UTF-8). - - * camel-tcp-stream-raw.c (flaky_tcp_write): For debugging printfs, - we want to use normal strerror (we want locale charset, not - UTF-8). - (flaky_tcp_read): Same. - - * camel-gpg-context.c (gpg_ctx_op_step): For debugging printfs, we - want to use normal strerror (we want locale charset, not UTF-8). - - * camel-service.c (camel_gethostbyname): Use g_strerror when - setting an exception string (we need it to be in UTF-8). - - * camel-lock.c (camel_lock_dot): Use g_strerror when setting an - exception string (we need it to be in UTF-8). - (camel_lock_fcntl): Same. - -2002-11-07 Not Zed - - * camel-mime-part.c (camel_mime_part_set_content_type): constify - the content_type. - -2002-11-07 Jeffrey Stedfast - - * camel-i18n.h: Added. - - * camel-object.h: #include camel-i18n.h instead of gnome-i18n.h - - * camel-lock.c: Same. - -2002-11-07 Rodrigo Moya - - * camel-object.h: removed gnome-defs.h, it does not exist. - -2002-11-05 Not Zed - - * Makefile.am (camel_lock_helper_LDADD): Created temporary link - list, we need to link with something for gettext. - - * camel.h: Remove gstring-util.h and hash-table-utils.h. - - * camel-text-index.c: - (text_index_normalise): Changed for g_utf8_strdown api change. - - * camel-search-private.c: - * camel-mime-utils.c: - * camel-mime-part-utils.c: - * camel-html-parser.c: - * camel-charset-map.c: Include glib/gunicode.h from glib instead - of gal. - - * camel-filter-driver.c: Remove include of gtk/gtk.h, should never - have been there. - -2002-11-01 Jeffrey Stedfast - - * camel-mime-utils.c (g_string_append_len): Removed. Glib2 has - this function. - - * providers/local/camel-local-store.c (delete_folder): Use - g_path_get_basename instead of g_strdup (g_basename (filename)). - - * camel-uid-cache.c (camel_uid_cache_new): Use g_path_get_dirname - since g_dirname has been deprecated. - -2002-10-31 Jeffrey Stedfast - - * camel-gpg-context.c (camel_gpg_context_class_init): Set the - virtual method pointers to the import/export methods. - (camel_gpg_context_init): Set the key_protocol string. - (gpg_hash_to_id): Handle 2 more hash types. - (gpg_id_to_hash): Same. - (gpg_ctx_op_step): Slight fixes to support import/export. - (gpg_ctx_parse_status): Fix to hack around the fact that importing - keys doesn't write to stdout. - (gpg_import_keys): Implemented. - (gpg_export_keys): Implemented. - - * camel-cipher-context.c (camel_cipher_context_class_init): Hook - up default virtual methods for import/export. - (camel_cipher_import_keys): Implemented. - (camel_cipher_export_keys): Implemented. - -2002-10-31 Jeffrey Stedfast - - * Makefile.am: Removed hash-table-utils.[c,h] from the build. - - * hash-table-utils.[c,h]: Removed. - - * string-util.c: Imported g_strcase[hash,equal] into here so we - can remove hash-table-utils.[c,h]. - - * camel-medium.c: Removed #include "hash-table-utils.h" - - * camel-mime-message.c: Same here. - - * camel-mime-part.c: And here. - - * camel-session.c: Here too. - - * providers/imap/camel-imap-store-summary.c: #include - string-utils.h instead of hash-table-utils.h - - * camel-charset-map.c: Same. - - * camel-folder-summary.c: Here too. - - * camel-provider.c: Again here. - - * camel-store-summary.c: And again... - -2002-10-31 Jeffrey Stedfast - - Remove a ton of useless snot. - - * Makefile.am: Remove gstring-util.[c,h] from the build. - - * gstring-util.[c,h]: Removed. - - * string-utils.c (string_equal_for_glist): Removed. - (string_split): Removed. - (string_trim): Removed. - (string_prefix): Removed. - (string_unquote): Removed. - (strip): Removed. - - * hash-table-utils.c (g_hash_table_generic_free): Removed. - - g_str[n]casecmp functions are deprecated in glib2. - - * string-utils.c (strstrcase): Use strncasecmp instead of - g_strncasecmp. - - * hash-table-utils.c (g_strcase_equal): Use strcasecmp - instead of g_strcasecmp. - - * camel-smime-utils.c (camel_smime_is_smime_v3_signed): Same. - (camel_smime_is_smime_v3_encrypted): Here too. - - * camel-sasl-digest-md5.c (decode_data_type): And here. - (parse_server_challenge): Again here. - - * camel-pgp-mime.c (camel_pgp_mime_is_rfc2015_signed): Same. - (camel_pgp_mime_is_rfc2015_encrypted): Same - - * camel-mime-part-utils.c (check_html_charset): Here too. - - * camel-folder-summary.c (camel_system_flag): Same. - -2002-10-25 Jeffrey Stedfast - - * camel-gpg-context.c (gpg_ctx_parse_status): Don't prematurely - set gpg->complete to TRUE. Let gpg_ctx_op_step () set it to TRUE - when gpg closes the status-fd instead. - -2002-10-24 Not Zed - - ** For bug #31647 and bug #31456. - - * camel-store-summary.c (store_info_string): for STORE_INFO_NAME, - skip the leading /. - - * providers/imap/camel-imap-store.c - (parse_list_response_as_folder_info): Remove jeff's last patch, - and use the store summary to create the name and path of the - folderinfo so it manages namespace issues. - (get_folder_info_online): Just pass @top directly to - build_folder_info always, since namespace is mapped to 1 tree - level. - (imap_build_folder_info): Remove jeff's last patch, dont strip - leading /'s, they shouldn't exist. - (imap_connect_online): Remove adding the INBOX here, we add it - later. - (get_subscribed_folders): Make sure INBOX is always in the list. - some imap servers dont seem to let you subscribe to it(?), so - always have it act as subscribed. - - * camel-store.c (camel_folder_info_build): back out the last 2 - patches from Jeff (for #31456) to get the original behaviour. - (camel_folder_info_build): When creating a fake - parent, dont strip the namespace from the full_name. malloc keys - in hash since we dont have them anymore. - (free_name): Helper to free names. - - * providers/imap/camel-imap-store-summary.c - (camel_imap_store_summary_namespace_new): Canonicalise the - namespace (strip trailing dir_sep), and change the path to remove - any /'s. - (camel_imap_store_summary_namespace_find_path): - (camel_imap_store_summary_namespace_find_full): new, find - namespace by path/full name. - (camel_imap_store_summary_full_from_path): Changed to a simple - wrapper around path_to_full, after checking namespace. - (camel_imap_store_summary_add_from_full): map the namespace if - present. - (camel_imap_store_summary_path_to_full): If namespace exists, - unmap it. - -2002-10-18 Jeffrey Stedfast - - * camel-filter-driver.c (camel_filter_driver_filter_folder): - Canonicalise the source_uri to not have a path. Fixes bug #32268. - -2002-10-17 Jeffrey Stedfast - - Possible fix for bug #32270 - - * providers/pop3/camel-pop3-store.c (try_sasl): If we get an I/O - error, we should not be setting the CANT_AUTH exception but should - instead be setting the SYSTEM exception. Also check for EINTR - which signifies a USER_CANCEL exception. - (pop3_try_authenticate): If the auth mechanism isn't supported, - don't set the CANT_AUTH exception since then we will loop and try - again with the same data which will just cause an infinite loop. - (pop3_connect): Simplified a bit. - -2002-10-17 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (camel_certdb_nss_cert_set): If - ~/.camel_certs doesn't exist, create it. - -2002-10-15 Not Zed - - * camel-tcp-stream-ssl.c (cert_fingerprint): helper, build - fingerprint. - (camel_certdb_nss_cert_get): Helper for nss certs. Lookup cert. - As well as fingerprint, the whole raw cert is checked for - validity. - (camel_certdb_nss_cert_add): Add an nss cert to a certdb, also - saves the cert by fingerprint in ~/.camel_certs/. - (ssl_bad_cert): Changed to use above functions to simplify logic. - (ssl_bad_cert): Also added non-compiled code which mimics what - mozilla does, but it doesn't work right :-/ - (camel_certdb_nss_cert_set): Save the raw cert associated with a - cert. - - * camel-certdb.c (certdb_cert_free): Free the raw cert data if - set. - -2002-10-14 Not Zed - - * camel-file-utils.c (camel_file_util_encode_string): Encode a - length of 0 as 1, not 0, to match the decode code. - -2002-10-03 Not Zed - - * camel-folder.c (filter_filter): Do the filtering ourselves. - This is so a problem like a missing uid (which can happen - legitemitely) doesn't prematurely abort filtering. Stop on all - other errors. See #31667. - -2002-10-16 Jeffrey Stedfast - - * camel-gpg-context.c (camel_gpg_context_new): No longer takes a - path argument. - (camel_gpg_context_fianlise): No need to free ctx->path. - (gpg_ctx_new): No longer takes a path argument either. - (gpg_ctx_free): No need to free ctx->path, it's no longer used. - (gpg_ctx_op_start): Don't stat the path anymore and change the - first arg to execvp to "gpg" so that we use the shell's - environment to find gpg. - (gpg_sign): Updated. - (gpg_verify): Updated. - (gpg_encrypt): Updated. - (gpg_decrypt): Updated. - (gpg_ctx_get_argv): Removed some debug printfs. - -2002-10-15 Jeffrey Stedfast - - * camel-gpg-context.c (gpg_id_to_hash): If the hash id is NULL, - return CAMEL_CIPHER_HASH_DEFAULT. Fixes bug #32229. - -2002-10-08 Jeffrey Stedfast - - * providers/imap/camel-imap-command.c (imap_read_response): If the - response from the IMAP server is "No", don't set the - SERVICE_UNAVAILABLE exception, this makes error reporting in the - UI for deleting IMAP folders that cannot be deleted inaccurate - (ie, it reports "Cannot delete in offline mode" which is not the - problem). - -2002-10-07 Jeffrey Stedfast - - Fixes bug #31752 - - * providers/smtp/camel-smtp-transport.c (connect_to_server): Don't - forget to send another EHLO command to the server once we toggle - into STARTTLS mode. - (smtp_helo): Reset any flags set using the EHLO response and also - any authtypes. - -2002-10-06 Jeffrey Stedfast - - Fixes bug #31681 - - * camel-mime-utils.c: Fix all mailing list regex patterns to allow - any number of spaces *or* tabs as pre-padding for the header - values. - -2002-10-03 Jeffrey Stedfast - - * camel-mime-part.c (write_to_stream): Use the content-object's - rawtext flag to decide if it needs to be filtered through the - charset filter instead of using the mime part's rawtext flag since - this will never be set. Partial fix for bug #31655. - -2002-10-03 Not Zed - - * camel-folder.c (folder_changed): Dont get the filter driver - inside the change_lock. Its not necessary, and can cause deadlock - with the way the mailer gets the filter driver via g_mainloop. - Should fix #31572. - -2002-10-02 Jeffrey Stedfast - - * camel-charset-map.c (camel_charset_iso_to_windows): Map us-ascii - to windows-1252 also. - -2002-10-02 Not Zed - - * providers/imap/camel-imap-folder.c (get_matching): Set *set to - NULL if we dont get any matches. - (imap_sync_online): If we get no matches, skip any work, also - reorder some code to make it easier to skip. See #31031. - - * providers/imap/camel-imap-store.c - (imap_check_folder_still_extant): Default to "TRUE", if the list - command failed, it probably means a server problem, assume the - worst. This makes imap_refresh_info not clear the exception and - crash. Fixes crash of #31000. - -2002-10-01 Not Zed - - * providers/imap/camel-imap-folder.c (imap_refresh_info): Make - sure we pass the exception to imap_folder_selected(), otherwise - failures can be lost. See bug #31000. - -2002-10-01 Not Zed - - * camel-folder.c (thaw): Add an assertion that the frozen count>0. - (freeze): Same for >= 0. - - * camel-vee-folder.c (camel_vee_folder_remove_folder): Use the - unmatched freeze_count when thawing folders removed from - unmatched, rather than the folder's freeze_count. Might be - related to #27391. - -2002-10-01 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (decode_internaldate): Use - strtol when decoding the timezone (since it can be negative) and - don't forget to increment inptr to the start of the time (ie, - don't leave inptr pointing to the year when decoding the - hour:min:sec). - -2002-09-30 Jeffrey Stedfast - - Fixes bug #31456. - - * providers/imap/camel-imap-store.c (imap_connect_online): Don't - LSUB "" "*", instead get both an LSUB containing the subfolders of - the namespace and an LSUB of INBOX (assuming namespace was - non-empty). This fix really has nothing to do with bug #31456 but - is what should have been done in the first place. - (parse_list_response_as_folder_info): Simplify a tad and strip - extra leading /'s from fi->path. - (imap_build_folder_info): Strip extra leading /'s from fi->path. - - * camel-store.c (camel_folder_info_build): Don't strip the - namespace from the fi->full_name when hashing or creating fake - parent folder-infos. Fixes a bug I found while trying to reproduce - bug #31456. - (camel_folder_info_build_path): Strip off extra leading dir_sep - chars from the path. - -2002-09-30 Not Zed - - * providers/imap/camel-imap-folder.c (imap_get_message): Remove - debug content_info_dump, could cause a crash, and not really - needed anymore. - - * camel-folder-summary.c (camel_content_info_dump): Check ci->type - != NULL before dereferencing it. Should fix crash #31331. - -2002-09-27 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (decode_internaldate): New - function to decode the INTERNALDATE response from an IMAP server - so we don't have to use my broken-date-parser routines. - -2002-09-27 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (connect_to_server): - NULL-check the streams before unreffing them in the case of a - failure during ssl negotiations. - - * camel-tcp-stream-ssl.c (camel_tcp_stream_ssl_enable_ssl): Check - SSL_ResetHandshake() for errors. Also force a handshake after - we've reset the handshake state on the socket. - -2002-09-27 Not Zed - - * providers/imap/camel-imap-folder.c (imap_update_summary): Use - the summary's last uid as the one to fetch from, ignoring the - cache. Use strtoul instead of atoi as well. - - * providers/imap/camel-imap-store.c (get_folder_counts): If we - have the folder open, and the unread count has changed, refresh - it. Should fix #30399 enough. Also in non-check-all mode, if we - have the folder open, use it anyway. - -2002-09-26 Not Zed - - * tests/folder/test2.c (main): Treat spool as a local folder, so - the ref checks work right. - - * providers/local/camel-spool-store.c (get_folder): Implement - FOLDER_CREATE flag. - (scan_dir): Dont free name on exception, its alloca'd. - (scan_dir): If we start scanning from a file, just add that - directly. - (scan_dir): Allow empty files to also show up in folder list, as - well as files starting with "From ". - (get_folder): Use creat() instead of open() to create file. - - * providers/local/camel-spool-folder.c (camel_spool_folder_new): - Check folder != NULL before writing to it. - - * providers/local/camel-local-store.c (create_folder): Handle a - parent of NULL for creating top-level dirs. Part of #31186. - - * providers/imap/camel-imap-store.c - (parse_list_response_as_folder_info): Store the folder flags in - the store summary. - (get_one_folder_offline): Set the noselect url parameter if this - is a noselect folder, from the stored summary flags. #30877. - -2002-09-23 Jeffrey Stedfast - - * camel-mime-filter-charset.c (complete): Handle EILSEQ by eating - bytes in the input buffer until conversion is successful. The old - behaviour aborted when it got EILSEQ and just dumped the raw data. - (filter): Same. Fixes bug #30873. - -2002-09-24 Not Zed - - * camel-mime-utils.c (mail_list_magic[]): Changed the Mailing-List - rule to get the complete domain (* in wrong spot). #31087. - - * camel-text-index.c (text_index_compress_nosync): If we have no - data written to a key, dont add it, or its partition header. - -2002-09-23 Not Zed - - * camel-block-file.c (sync_nolock): Mark root block dirty if we're - going to sync it. - (camel_key_file_finalise): de-count the active list if we close - it. - - * camel-text-index.c (text_index_delete): Implement. - (text_index_compress_nosync): Use index_delete when we're finished - with the old one, so it is properly deactivated. - - * camel-index.c (camel_index_delete): Remove api call. Mark index - deleted in new state variable. - (camel_index_*): Wrap all calls in check for deleted state. - -2002-09-23 Jeffrey Stedfast - - * camel-folder.c (transfer_message_to): If the original message is - deleted, reset the deleted flag when we're done. Fixes bug #30876. - - * providers/imap/camel-imap-folder.c (add_message_from_data): - Decode the INTERNALDATE if we've got one. - (imap_update_summary): Instead of requesting a list of specific - headers, request HEADER.FIELDS.NOT (RECEIVED) to reduce bandwidth - usage even more. - (parse_fetch_response): Change slightly to allow HEADER.FIELDS or - HEADER.FIELDS.NOT so that we can make changes in - imap_update_summary and not need to keep changing this function to - match. Also parse an INTERNALDATE response. - -2002-09-22 Dan Winship - - * camel-mime-parser.c (folder_scan_drop_step): fix non-ANSI switch - statement. - - * camel-service.c (service_getv): Likewise. - - * providers/imap/camel-imap-store.c (imap_getv): Likewise. - - * providers/pop3/camel-pop3-folder.c (cmd_builduid): Likewise. - -2002-09-20 Not Zed - - * tests/misc/split.c: New regression test for word - splitting/search input parsing code. - - * tests/folder/test9.c (main): Fix for filter_driver api change. - - * camel-search-private.c (camel_search_words_split): Handle "'s - and \'s to escape characters. For fat, lazy, slobs who dont like - anything changing. - -2002-09-19 Not Zed - - * camel-filter-search.c (camel_filter_search_match): Take new - session arg. Update callers. - (symbols[]): changed get-source to header-source - (header_source): Changed from get_source. Now a boolean, returns - true if source matches one of the arguments. Uses the provider - url comparison directly for accurate checking. Makes 'filter on - source' work. - - * camel-filter-driver.c (camel_filter_driver_new): Take new arg, - session. - (camel_filter_driver_finalise): Free session. - -2002-09-19 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (parse_fetch_response): Don't - increment the response pointer when deciding what type of header - response we got, this screws up the string that we strdup into the - part_spec string later. Also, instead of using the entire blob of - HEADER.FIELDS that we get in the response, shorten it to just - HEADER.FIELDS to use as the part_spec key. - -2002-09-18 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (CAMEL_MESSAGE_INFO_HEADERS): - Include MIME-VERSION and CONTENT-TYPE. - -2002-09-18 Not Zed - - * providers/imap/camel-imap-command.c - (camel_imap_command_response): If we get an ALERT, pass it to the - user. An rfc2060 MUST, and bug #22496. - -2002-09-17 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (parse_fetch_response): - Handle when the response is from a HEADER.FIELDS (if so, we don't - want to cache the result). - (imap_update_summary): Request specific headers when building the - CamelMessageInfo's rather than fetching the full headers. - -2002-09-13 Jeffrey Stedfast - - * camel-mime-part.c (process_header): If header_msgid_decode fails - for the content-id field, just grab whatever is between the <>'s - (yes, this means that the content-id is invalid - but what can ya - do?). Addresses bug #21027. - -2002-09-11 Jeffrey Stedfast - - * camel-mime-utils.c (header_encode_string): Revert a patch that I - had not meant to commit that was aimed at fixing bug #29234. - -2002-09-10 Jeffrey Stedfast - - * camel-store-summary.c (camel_store_summary_load): Same as - below. Also save errno before closing the file so our caller can - figure out why we failed. - (camel_store_summary_save): Same here, but also flush the output - stream to disk. - - * camel-folder-summary.c (camel_folder_summary_load): s/fclose(in) - == -1/fclose(in) != 0/ since fclose doesn't necessarily return -1 - on fail, all we really know is that it returns 0 on success and - non-zero on fail. - - * camel-certdb.c (camel_certdb_save): fsync() the stream after we - fflush it. - - * camel-folder-summary.c (perform_content_info_save): Do proper - error checking and return -1 on fail. - (camel_folder_summary_save): Check the return of - perform_content_info_save and a few other output calls within the - message_info_save loop. If any of them fail, save errno, close the - file, and return -1. If we finish the loop without fail, fflush - the stream and then fsync (fflush only flushes user-space buffers, - you still need to fsync afterward to flush the data to disk). If - either fail, treat it as an exception by saving errno, closing the - stream, and returning -1. I suspect that this also fixes bug - #30150 because the old code would fclose if fflush or fclose - failed in the check after the loop (man fclose(3) states that any - further calls using the stream (even another call to fclose) will - have undefined behaviour no matter what the first fclose call - returned). - - * providers/local/camel-local-summary.c - (camel_local_summary_init): Don't malloc a private struct of 0 - size. - - * providers/imap/camel-imap-folder.c - (camel_imap_folder_fetch_data): Clear the exception even if we - failed to get the message (part) from the imap-message-cache if we - are online and able to try fetching it from the IMAP server. - -2002-09-10 Not Zed - - * camel-data-cache.c (data_cache_expire): Remove the hash table - entry using the right path. Related to #29731. - (camel_data_cache_remove): " - -2002-09-09 Jeffrey Stedfast - - Fixes bug #4224 - - * providers/imap/camel-imap-folder.c - (camel_imap_folder_fetch_data): Pass ex into - camel_imap_message_cache_get(). - - * providers/imap/camel-imap-message-cache.c - (camel_imap_message_cache_get): Now takes an exception and sets it - on fail. - (camel_imap_message_cache_copy): Updated to properly handle - cache_get error conditions. - -2002-09-04 Dan Winship - - * camel-mime-utils.c (header_decode_date): Use e_mktime_utc. - - * camel-mime-message.c (camel_mime_message_set_date): Use - e_localtime_with_offset. - - * broken-date-parser.c (decode_broken_date): Use e_mktime_utc. - -2002-09-04 Not Zed - - * tests/folder/test4.c (main): clear nonfatal stuff. - - * tests/folder/test6.c (main): check inbox and 'another folder' - because some servers do different things w/ inbox. - - * providers/imap/camel-imap-message-cache.c - (camel_imap_message_cache_get): Dont try to open the directory - instead of an empty "" uid. - - * providers/imap/camel-imap-folder.c (imap_get_message): we dont - want to g_return_if_fail, we need to set an exception and always - handle the case. - (get_message_simple): Set an exception if we get a construct - failure. - (imap_refresh_info): if we're refreshing inbox, force a reselect. - this is required for at least cyrus. CHECK doesnt work either :( - - * tests/lib/folders.c (test_folder_basic): for non-local stores, - the folder will have an extra ref for selection, take this into - account when checking ref leaks. - (test_folder_message_ops): Dont try to delete folder with messages - in it, it works generally with imap. also, change params so we - can test different mailbox types. - (test_folder_message_ops): disconnect remote services before - finishing off. doesn't need to stricly but makes ref count - checking more accurate. - (test_folder_message_ops): removed explicit remote sync, imap does - it itself now ... - - * providers/imap/camel-imap-store.c: - (camel_imap_store_finalize): call service_disconnect, so it isn't - called later in the finalise chain, to properly cleanup on exit. - - * camel-mime-parser.c (folder_scan_content): If we fake the from - eof file boundary, also make sure we say we matched nothing. Also - make the end case a little more robust to make sure we expired all - hope of finding a sub-boundary. - - * providers/imap/camel-imap-store.c, - providers/imap/camel-imap-folder.c: Lots of changes, too numerous - to list. Changed to use camel-imap-store-summary to cache list - requests. Changed to use a canonicalised url path with / instead - of per-store directory separator. Indirects folder name so - invalid folder names can still be accessed. Summary now stored in - a new expandable format in .ev-store-summary. - -2002-08-29 Not Zed - - * tests/folder/test3.c: Change the case sensitive search of - subject to expect case insensitive results, as the behaviour has - changed. - (main): Made the search content before sync nonfatal. its - something that needs to be fixed but not practical concern in - evolution. - - * camel-block-file.c (block_file_validate_root): Only spit out the - invalid root warnings if the file isn't empty. - - * camel-text-index.c (text_index_compress_nosync): Swap the path - as well when we compress. - - * camel-mime-parser.c (folder_scan_content): Treat the end of file - as a boundary if we're scanning From lines, and drop the last \n. - (folder_scan_init_with_fd): Dont pre-read from the fd, and init eof. - (folder_scan_init_with_stream): Similar. - (folder_read): Handle eof, and set eof on 0 read. - (folder_seek): Dont pre-read after a seek, and reset eof flag. - (camel_mime_parser_init_with_fd): Fix doco, no pre-read occurs - anymore. - (camel_mime_parser_init_with_stream): Same. - - * providers/local/camel-mbox-summary.c - (camel_mbox_summary_sync_mbox): Add a \n to end of content of each - message, not at start. - - * providers/local/camel-mbox-folder.c (mbox_append_message): - Instead of appending "\nFrom " to a mailbox, start with "From ", - and append a \n after the message always. For better mutt/elm - compatability. Also, unlock after we've stat'd. - (mbox_append_message): Set the message's from_pos exactly as the - mbox size. - -2002-08-28 Jeffrey Stedfast - - * camel-tcp-stream-openssl.c (stream_setsockopt): Fixed `set' to - hold the correct value when setting the flags. - - * camel-tcp-stream-raw.c (stream_setsockopt): Fixed `set' to hold - the correct value when setting the flags. - - * camel-mime-filter-tohtml.c (is_protocol): Match file: urls too. - -2002-08-28 Not Zed - - * tests/folder/test8.c (test_add_message): Change message number - to use hex, so its properly unique. - (worker): Same here. - - * tests/misc/utf7.c: some utf7/utf8 tests. - - * providers/imap/camel-imap-utils.c (imap_mailbox_encode): Changed - to use camel_utf8_utf7 code. - (imap_mailbox_decode): As above, using camel_utf8_utf7. 'UTF-7' - isn't a widely support iconv() codeset, and besides the new code - is simpler. - - * camel-utf8.[ch]: robust utilities for working with utf8 and utf7. - -2002-08-27 Jeffrey Stedfast - - * camel-folder-thread.c (camel_folder_thread_messages_new): Now - takes a third argument to specify whether or not to group messages - by subject when threading. It seems some people don't want this - feature (see bug #22791 for details). - (thread_summary): If thread_by_subject is enabled, group - un-threaded messages by subject otherwise don't bother. - -2002-08-26 Jeffrey Stedfast - - * providers/imap/camel-imap-command.c - (camel_imap_response_free_without_processing): If the response is - NULL, just return. (now works the same way as imap_response_free - which allowed a NULL response argument). Fixes bug #25491. - -2002-08-26 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c: - - * providers/imap/camel-imap-folder.c: - - * providers/imap/camel-imap-command.c: Lock the - CamelService->priv->connect_lock instead of using our own - command_lock. This fixes bug #28177. - -2002-08-23 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_helo): If we fail to - send the EHLO/HELO command successfully, set transport->connected - to FALSE when we close the tcp connection. Also updated to work on - an IPv6 network. - (smtp_connect): transport->authtypes can be NULL, so NULL-protect - the call to g_hash_table_size() - this should fix a warning that - was reported on the evolution@ximian.com mailing list. - (smtp_set_exception): If the status message is multi-line, add a - \n between lines. - (connect_to_server): If we are going to ignore the EHLO/HELO error - as if it were non-fatal, then we should clear the exception. - -2002-08-22 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (imap_noop): If current_folder - is not NULL and the summary for that folder is dirty, sync the - flags rather than sending a NOOP. - - * providers/imap/camel-imap-utils.c (imap_parse_list_response): - Workaround for Courier imap's brokeness when LSUBing the INBOX - folder when it isn't subscribed to. Fixes bug #28929. - -2002-08-21 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (connect_to_server): If - imap_get_capability() fails, after unlocking the command_lock, - disconnect the service. - -2002-08-21 Jeffrey Stedfast - - * camel-session.c (get_service): Don't register the noop timeout - here anymore, we're gonna handle all this in the mailer now. - (camel_session_register_timeout): Removed. - (camel_session_remove_timeout): Removed. - -2002-08-28 Not Zed - - * providers/imap/camel-imap-store.c (construct): Load store - summary if it exists. - (can_work_offline): Just see if we have any folders to say whether - we can work offline or not. Should probably always just return - true. - -2002-08-27 Not Zed - - * providers/imap/camel-imap-store-summary.[ch]: New files to - handle offline definition of folders, etc. - - * camel-url.h: Define CamelURL to be struct _CamelURL rather than - anonymous struct. - - * camel-store-summary.[ch]: a few api tweaks. Also, the summary - header is versioned separately at each level, so that version - upgrades can be handled separately. Renamed FolderInfo -> - StoreInfo to avoid namespace with current FolderInfo code. This - should be reversed when the FolderInfo code is rationalised to - this new base. - -2002-08-23 Not Zed - - * providers/imap/camel-imap-command.c (camel_imap_command): domt - encode folder name. - - * providers/imap/camel-imap-folder.c (do_copy): dont encode folder - name. - (do_append): dont encode folder name. - - * providers/imap/camel-imap-store.c (get_folder_status): don - encode folder name in imap request. - (get_folder_online): here too for creating folder. - (rename_folder): Assume the incoming 'new name' is a utf8 path, - whereas the 'old name' is as from get folder info (raw). - (create_folder): Dont encode parent_name, assume its the raw - thing. - -2002-08-22 Not Zed - - * providers/imap/camel-imap-store.c (get_folder_online): Select - based on unconverted name. - (imap_build_folder_info): New function to create a folderinfo - properly based on raw name. - (subscribe_folder): Use above helper. - (imap_folder_effectively_unsubscribed): Same here. - (imap_forget_folder): Same here. - (get_one_folder_offline): " - -2002-08-21 Not Zed - - * providers/imap/camel-imap-store.c - (parse_list_response_as_folder_info): Setup path properly, as - decoded path with / separator. Setup full_name as non-decoded raw - name. Keep url as decoded path but with server separator - ... (ick). - (create_folder): Dont call build_path anymore, get_folders() does - it for us. - (subscribe_folder): Build the path ourself. - (imap_folder_effectively_unsubscribed): Same here. - (get_subscribed_folders): list using %S not %F, we're using the - raw server provided name directly. - (subscribe_folder): As above, for SUBSCRIBE. - (unsubscribe_folder): Same here. - (delete_folder): Same. - (rename_folder_info): Same here for source name. - (rename_folder): And here? - (get_folders_online): Amd here. - - * providers/imap/camel-imap-utils.c: - (imap_parse_list_response): Dont decode the mailbox. - - * camel-utf8.[ch]: some new utf8 & utf7 utilities. - - * providers/imap/camel-imap-utils.c (imap_mailbox_encode): - (imap_mailbox_decode): use camel_utf7/8* functions instead. - : Add config.h and alloca.h headers. - -2002-08-20 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (imap_noop): Override the - default noop implementation. - - * camel-store.c (camel_store_noop): New virtual method to ping a - store. - - * camel-session.c (get_service): Register a timeout that calls - camel_store_noop() every 10 minutes. - -2002-08-19 Peter Williams - - Plug some large leaks in the indexing code. - - * camel-mime-filter-index.c (camel_mime_filter_index_set_index): Unref - the old index if necessary. - - * camel-text-index.c (camel_text_index_get_type): Give it the correct - parent type so that finalize handlers chain. - (camel_text_index_name_get_type): Here too. - (camel_text_index_cursor_get_type): Here too. - (camel_text_index_key_cursor_get_type): Here too. - -2002-08-20 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (get_folders): Don't let the - minimum recursive depth be negative. - (get_folders): Pass flags & CAMEL_FOLDER_INFO_SUBSCRIBED as the - `lsub' argument to get_folders_online() otherwise we'll end up - doing a LIST when we really wanted to do an LSUB. - - * camel-session.c: Set CAMEL_URL_NEED_PATH for the vFolder - provider. - -2002-08-19 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c: Changed the STOREINFO_VERSION - - should fix bug #28571, but if it doesn't - oh well, I don't - care. I'm considering it fixed no matter what. - - * camel-gpg-context.c (gpg_sign): If the diagnostics are empty, - just explain that gpg failed to execute. - (gpg_encrypt): Same. - (gpg_decrypt): And here too. - - * tests/lib/camel-test.c (camel_test_init): Updated to pass the - needed arguments to camel_init() and to init gthreads before camel - (since camel expectes it to be initialised already). - - * tests/lib/session.c: #include needed for - ENABLE_THREADS so that sizeof (CamelSessionClass) gives the - correct size. - - * tests/*: Updated to work with camel API changes. - -2002-08-16 Dan Winship - - * camel-session.c (get_service): If the passed-in URL contains a - path, but the service doesn't allow paths, then the path part must - be a folder name, and we should ignore it here. #29010 - -2002-08-16 Chris Toshok - - * camel-arg.h: remove the outer parens from the expansion of - camel_argv_{start,end} since at least on freebsd va_end is - #defined to be nothing, so (va_end(..)) causes a syntax error. - -2002-08-16 Not Zed - - * providers/imap/camel-imap-store.c (get_folders): Fix the logic - check for working out if we add inbox or not, we do it if we - listed the namespace. - -2002-08-15 Not Zed - - * camel-store.h (CamelFolderInfo): added a flags field, defined - some flags, currently only used by imap. This and below is first - step to getting incremental folder tree loading. - - * providers/imap/camel-imap-store.c (get_subscribed_folders): If - the subscribed list is empty, always add inbox. - (imap_connect_offline): If the 'storeinfo' namespace isn't the - same as our own (if its set), then ignore it, assume we changed - settings. Otherwise you can't change the namespace ... - (get_folders): allow the env variable CAMEL_IMAP_MAX_DEPTH to - override the default maximum recursion depth if 10 levels. - (camel_imap_store_readline): Dont depend the log debug on d(x) - being defined. - (get_folder_info_online): changed to use new functions/names. - -2002-08-14 Not Zed - - * providers/imap/camel-imap-store.c (get_subscribed_folders): - Removed the by_hand sillyness. Return an array instead. - (get_folders): New method to get folders recursively without - having to use '*'. Uses '%', and stops if it gets too deep - (current max of 10). - (get_folder_counts): New method to fill out unread counts on - folderinfo tree. - (get_subscribed_folders): Fix some failure logic. - - * providers/imap/camel-imap-utils.[ch]: Changed IMAP_LIST_FLAGS to - use the new CamelFolderInfoFlags directly. - -2002-08-09 Peter Williams - - * providers/imap/camel-imap-folder.c (get_temp_uid): New function, - generate a UID that has better chances of being unique. - (imap_append_offline): Use it here. - (imap_transfer_offline): And here. - -2002-08-09 Peter Williams - - * providers/imap/camel-imap-store.c - (get_folder_info_online): Tweak how we build the tree based on whether - a full tree or a subtree is being requested. Fixes subscribe dialog - on UW servers. - (get_one_folder_offline): Don't add folders that we're not subscribed - to; fixes UW folders that weren't being marked as NoSelect because - the storeinfo doesn't record that information. - -2002-08-09 Peter Williams - - * providers/imap/camel-imap-folder.c (imap_rename): When renaming our - cache, add the "/folders" to the path. - -2002-08-08 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (camel_imap_folder_init): Set - some default permanent_flags. This is the other cause of bug - #28038. - (imap_refresh_info): After calling camel_imap_command() with a - NULL format value (this is a shortcut to change the current_folder - by SELECTing it), call camel_imap_folder_selected(). This may have - been why permanent_flags never got set on the folder even after - going online in bug #28038. - (imap_update_summary): Same here. Also NULL-guard - camel_imap_response_free(). - -2002-08-07 Jeffrey Stedfast - - * camel-mime-utils.c (header_encode_param): Oops - outbuf pointed - to alloca'd memory but we were g_free'ing it after using - it. Instead use g_malloc for this outbuf buffer since it may be - kinda large. Also don't depend on a single byte to nul-terminate - the outbuf buffer so as to be safe with charsets such as UCS2 and - UCS4, instead keep a pointer to the end of the buffer. - - * providers/imap/camel-imap-folder.c (parse_fetch_response): Only - add the stream to the gdatalist if it is non-NULL. - -2002-08-06 Jeffrey Stedfast - - * providers/sendmail/camel-sendmail-transport.c - (sendmail_send_to): If writing to the sendmail pipe fails, wait - for the sendmail process to exit before returning. Fixes bug - #19636. - -2002-08-06 Not Zed - - * providers/pop3/camel-pop3-folder.c (cmd_list): Add messageinfo - to id table, and store array index in messageinfo too. - (fi_to_index): Removed, use index member of messageinfo, fixed - callers. - (cmd_builduid): Parse the headers of the data, and ignore any - status or x-status headers. - (uid_to_fi): Removed, use the hashtable instead. - (id_to_fi): Same. - (cmd_uidl): Add messageinfo to uid table. - (pop3_refresh_info): Setup hash tables, and fill out uid table for - nonuid capable servers. - (pop3_finalize): Destroy hash tables. Only free resources if the - uids table is not null (if finalised before we ran refresh info). - (id_to_fi): Removed. Use id hash table instead, fixed caller. - -2002-08-05 Jeffrey Stedfast - - * camel.c (camel_init): Always set a g_atexit handler to - flush/save the camel-certdb. - - * providers/imap/camel-imap-store.c (get_folder_info_online): If - we are asking for the toplevel folders, use the IMAP store's - namespace as the toplevel folder rather than an empty - string. Fixes bug #28574. - (imap_forget_folder): Rearrange the code so that name can never be - used uninitialised. - - * providers/imap/camel-imap-utils.c (imap_namespace_concat): - Removed. - -2002-08-05 Dan Winship - - * camel-folder-summary.h (CamelMessageFlags): Add - CAMEL_MESSAGE_ANSWERED_ALL, for folders that can distinguish a - reply-to-sender from a reply-to-all. (eg, Exchange) - - * providers/local/camel-local-folder.c (local_init): Add - ANSWERED_ALL to permanent_flags too. - -2002-08-02 Jeffrey Stedfast - - Fixes bug #26237. - - * providers/imap/camel-imap-command.c - (imap_command_strdup_vprintf): Don't prepend any namespace shit in - the %F case. - - * providers/imap/camel-imap-utils.c (imap_parse_list_response): - Don't strip off the namespace. - -2002-08-01 Peter Williams - - * providers/imap/camel-imap-store.c (create_folder): If the folder - name contains the directory separator, reject it. - -2002-08-02 Not Zed - - * providers/local/camel-mbox-summary.c (mbox_summary_check): Clear - the summary after building the 'removed uid' list. - - * camel-folder-summary.c (message_info_load): revert jeff's patch - below, and do it slightly differently, and stop the auto-reformatting - bullshit. - -2002-08-02 Not Zed - - * providers/local/camel-maildir-summary.c (message_info_new): If - we get a duplicate, just re-use the old info. - (remove_summary): Add any removed to a change list. - (maildir_summary_check): If we find new ones in 'cur' track them - in the change list. Removed FIXME about it. For #18348. - -2002-08-01 Jeffrey Stedfast - - * camel-folder-summary.c (message_info_load): Do more error - checking to prevent crashing if we fail to read a string for - example. - -2002-07-29 Peter Williams - - Fix bug #28238 - - * providers/imap/camel-imap-store.c (imap_forget_folder): New - function, breaking out the code in delete_folder() to handle when - a folder is removed. - (imap_folder_effectively_unsubscribed): New function, breaking out - the code in unsubscribe_folder() to handle when a folder is - unsubscribed. - (imap_check_folder_still_extant): New function, check whether a - folder exists by LIST'ing it. - (imap_store_refresh_folders): Add code here to check if the folder - still exists if we're unable to refresh its info. If so, pretend - that it was unsubscribed (to get the mailer to remove it from - the tree) and delete its cache. If somehow this goofs up, the - worst that can happen is that we must redownload the headers. - (get_folder_status): If we can't get the status, behave as above. - (delete_folder): Call imap_forget_folder() where the bulk of this - code has gone. - (unsubscribe_folder): Call imap_folder_effectively_unsubscribed() - where the bulk of this code has gone. - -2002-07-31 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (parse_fetch_response): - Disable my fix to not cache headers as it means that each time we - load the message, we've got to re-fecth the headers. - - * camel-mime-filter-tohtml.c (is_addr_char): Don't use - "isprint(c)" to mean "c >= 32 && c < 128" since it doesn't in most - locales. - (is_url_char): Same. - (is_trailing_garbage): Same. - (is_domain_name_char): New macro for dns-valid characters - (email_address_extract): Use is_domain_name_char rather than - is_addr_char for the part after the @. - -2002-07-30 Jeffrey Stedfast - - * camel-tcp-stream.c (camel_tcp_address_new): Update the comment. - - * camel-tcp-stream-raw.c (socket_connect): If building with IPv6 - support and the address is an IPv6 address, connect using a - sockaddr_in6 otherwise use the standard IPv4 sockaddr_in - structure. - (stream_get_local_address): Fix to work with IPv6 addresses. - (stream_get_remote_address): Same. - - * camel-tcp-stream-openssl.c (socket_connect): Same as above. - (stream_get_local_address): Fix to work with IPv6 addresses. - (stream_get_remote_address): Same. - - * camel-tcp-stream-ssl.c (stream_connect): If building with IPv6 - support and the address is an IPv6 address, initialise the - PRNetAddr accordingly. - (stream_get_local_address): Fix to work with IPv6 addresses. - (stream_get_remote_address): Same. - -2002-07-30 Jeffrey Stedfast - - * camel-tcp-stream-openssl.c (ssl_verify): X509_digest() needs a - pointer to an int len. Also fixed some other compiler errors. - - * camel-certdb.h: #include - -2002-07-30 Jeffrey Stedfast - - * camel-certdb.c: New source file implementing a very basic - certificate database. This is mostly just here because the Mozilla - NSS certdb seems to not be working for everyone's Evolution - install (works fine for me and Ettore but not many other people). - - * camel-tcp-stream-ssl.c (ssl_bad_cert): If we have this - certificate in our own CamelCertDB, then get the trust value from - that and only prompt the user if the trust is unknown. - - * camel-tcp-stream-openssl.c (ssl_verify): Same. - - * camel.c (camel_init): Create our default certdb. - -2002-07-30 Peter Williams - - * providers/imap/camel-imap-folder.c (imap_transfer_offline): Use - the same command-counter mojo that the append code uses in case - the use tries to copy the same message to the folder repeatedly. - -2002-07-29 Jeffrey Stedfast - - * camel-filter-driver.c (unset_flag): New filter action to unset a - system flag. The exact opposite of set_flag. - -2002-07-26 Jeffrey Stedfast - - * providers/local/camel-local-store.c (get_folder): If the path - exists and is a directory, return non-NULL. Missed this before - which is how we could return NULL even on success. Oops. - -2002-07-26 Peter Williams - - * providers/imap/camel-imap-summary.c - (camel_imap_summary_add_offline_uncached): The flags'n'tags - copy was unnecessary. Removed it. - -2002-07-25 Jeffrey Stedfast - - If we're gonna do an elite hack, lets do it right. - - * providers/local/camel-local-store.c (get_folder): On success, - return non-NULL so that our caller doesn't have to depend on 'ex' - being non-NULL in order to work correctly. - - * providers/local/camel-mbox-store.c (get_folder): Don't bother - checking if an exception was set, just use the return value of - camel-local-store's get_folder. - - * providers/local/camel-maildir-store.c (get_folder): Same as the - mbox change. - - * providers/local/camel-mh-store.c (get_folder): Here too. - -2002-07-25 Peter Williams - - * providers/imap/camel-imap-summary.h - (camel_imap_summary_add_offline_uncached): Prototype. - - * providers/imap/camel-imap-summary.c - (camel_imap_summary_add_offline_uncached): New function to add an - uncached message to the summary while offline. - - * providers/imap/camel-imap-store.c (imap_connect_online): Only - refresh the folders if the disco diary is empty (ie, we're not - resyncing.) - - * providers/imap/camel-imap-folder.c (imap_transfer_offline): Emit - an event for the source if deleting its originals. Also, if we - can't load the message, still process it, using the new imap - summary function. - -2002-07-25 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c: Remove "possibly - non-fatal" exception strings, all exceptions are fatal unless - their caller decides otherwise. - (connect_to_server): If smtp_helo() fails due to us getting - disconnected, treat the exception as fatal. - (smtp_connect): Abort if smtp_helo() fails and we got - disconnected. - (smtp_send_to): If smtp_mail() fails, abort the send operation. - (smtp_set_exception): If respbuf was NULL, then we got - disconnected and so update our state accordingly. - (smtp_disconnect): Only send a QUIT if we are still in the - connected state (or, at least think we are). - -2002-07-24 Peter Williams - - * providers/imap/camel-imap-folder.c - (imap_expunge_uids_resyncing): It would help to mark the UIDs as - deleted before we try to expunge them - (in the case when no other UIDs were marked deleted this didn't - happen.) Also fix an FMR. - (imap_expunge_uids_offline): Trigger a folder_changed event with - our own changeinfo because camel_imap_response_free won't be able - to do that for us. - -2002-07-25 Jeffrey Stedfast - - * camel-filter-driver.c (do_shell): Renamed from - shell_exec(). Also, we now want to pass argc/argv on to the - CamelFilterDriverShellFunc. - (camel_filter_driver_set_shell_func): Renamed a bit. - - * camel-filter-search.c (pipe_message): Renamed from shell_exec(). - -2002-07-25 Not Zed - - * camel-folder-summary.c (camel_folder_summary_save): When writing - the summary, use TRUNC flag, duh. Also, write to a temp file - first, and rename when closed successfully, and check ferror() and - fclose() against 0 rather than -1. - - * providers/local/camel-mbox-summary.c (summary_update): Decrement - i if we remove the summary item so we dont skip every 2nd one. - - * camel-mime-utils.c (header_decode_mailbox): Use - rfc2047_decode_word explicitly incase we just found an encoded - word. Stops us re-decoding the string twice, which fixes memory - corruption in #26330 when the HUGE string is used later. - -2002-07-24 Not Zed - - * camel-partition-table.c (camel_key_table_next): Didn't unlock if - we exited on an empty key list. - - * providers/imap/camel-imap-folder.c (imap_expunge_uids_online): - Sync before doing an expunge if we dont have uidplus. See #25766. - (imap_expunge_uids_resyncing): Same here. - - * providers/imap/camel-imap-store.c (get_folder_info_online): - Duplicated the very much hack in imap_store_refresh_folders() to - avoid a deadlock in #27959. A decent fix has to wait for a - rewrite. - (get_folder_online): Move folders to a subdirectory of - storage_path, rather than in it. Bye bye everyones settings. See - 24947. - (get_folder_offline): And here too. - (delete_folder): And here too. - (rename_folder): and here too. - (get_folder_info_offline): And here too. I love code reuse. - -2002-07-23 Jeffrey Stedfast - - * camel-tcp-stream.c: #include for memcpy. - -2002-07-22 Not Zed - - * camel-vee-folder.c (vee_set_message_user_tag): Oops, forgot to - implement this. Fixes #24604. - -2002-07-21 Jeffrey Stedfast - - * camel-mime-filter-crlf.c (filter): Only add a \r if the - character before the \n wasn't already a \r - this covers for when - people add DOS files as attachments. Fixes bug #28056. - -2002-07-19 Not Zed - - * camel-mime-part-utils.c (convert_buffer): Changed to use a - different length calculator. - -2002-07-17 Jeffrey Stedfast - - * camel-lock.c: Add the appropriate #include for the _() macro. - -2002-07-17 Not Zed - - * providers/pop3/camel-pop3-store.c (pop3_try_authenticate): Got - rid of the stupid "tryagain" semantics, which didn't work. - (pop3_connect): Fixed here to only retry under proper conditions. - -2002-07-16 Jeffrey Stedfast - - * camel-mime-filter-canon.c (filter): When CRLF encoding, "empty" - (after stripping trailing whitespace characters) lines need to end - in CRLF also, not just lines with data in them. - -2002-07-16 Peter Williams - - * providers/imap/camel-imap-folder.c (imap_sync_online): Clean - up some improper usage of CamelExceptions (looking at - camel_exception_is_set when ex = NULL). - - * providers/imap/camel-imap-store.c (get_folder_online): Here too. - - * providers/imap/camel-imap-message-cache.c - (camel_imap_message_cache_new): Nothing sets the exception so - don't bother to check it at the end of this function. Prevents - a warning about checking a NULL exception's value. - -2002-07-16 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_helo): Make the - standard AUTH format take priority over the AUTH= priority, since - sometimes servers only list a subset of the supported authtypes in - the AUTH= response while they list all authtypes in the standard - AUTH response. Fixes "bug" #27841. - -2002-07-15 Peter Williams - - * providers/imap/camel-imap-folder.c (imap_get_message): If we're - not online and the message isn't in our cache, give up. - -2002-07-15 Not Zed - - * camel-filter-search.c (get_label): Removed. - (get_score): Removed. Labels & scores are stored in tags, we - already have a function to get tags. - (user_tag): Fail if we dont get valid arguments, it must be a - string type. - (system_flag): Same here. - -2002-07-15 Jeffrey Stedfast - - * camel-mime-utils.c (header_msgid_generate): Try to get the FQDN - from the results of gethostname(). If that fails, then fall back - to the results gotten from gethostname() or if that fails just use - "localhost.localdomain". Addresses bug #17416. - (header_decode_param): Protect against a NULL value. - - * providers/smtp/camel-smtp-transport.c (smtp_data): Get rid of - the constant 'required' variable, just use the value when calling - set_best_encoding. - - * providers/local/camel-local-provider.c: Changed the mbox and - spool provider descriptions to try and be more clear. I'm not sure - I like the mention of Evolution in the mbox provider description, - but there was no other way to make it clear that it MOVED mail out - of the mbox folder into a folder managed by Evolution without - mentioning Evolution. *sigh* Anyways, to me "retrieve" means move, - but apparently this isn't clear to the weak minded. - -2002-07-15 Peter Williams - - * providers/imap/camel-imap-folder.c (imap_rescan): >= is not - appropriate here because the sequences are 1-based; so seq = - summary_len is valid. Hopefully addresses 15646, because this - caused the last message in a folder to be reloaded, replacing its - CamelMessageInfo, and the tree view was using the old - CamelMessageInfo. - -2002-07-13 Not Zed - - * camel-folder-summary.c - (camel_folder_summary_info_new_from_message): Only assign a uid if - indexing is enabled. This stops us always assigning a uid in the - imap folder and disco folder? - - * providers/imap/camel-imap-folder.c (imap_update_summary): Also - check the uid is set at all, another bit of a fix for #15667. - -2002-07-09 Not Zed - - * providers/imap/camel-imap-folder.c (imap_update_summary): Check - for existing messages of the same uid before doing anything. If - it exists, do nothing (perhaps it should merge?). A dirty hack for - #15667. - -2002-07-12 Jeffrey Stedfast - - * camel-multipart-encrypted.c (camel_multipart_encrypted_decrypt): - On error, do not unref the parts gotten using - camel_multipart_get_part() since that function does not ref the - parts. Also don't forget to reset the decrypted stream before - trying to parse it ;-) - -2002-07-12 Jeffrey Stedfast - - * camel-multipart.c (camel_multipart_class_init): Updated to not - use camel_type_get_global_classfuncs() since this is just a cast - macro now. - - * providers/imap/camel-imap-folder.c (get_content): Handle - multipart/encrypted parts too. - - * camel-mime-part-utils.c - (camel_mime_part_construct_content_from_parser): Handle - multipart/encrypted types too. - -2002-07-11 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_data): Don't let any - parts have a binary encoding. - -2002-07-11 Jeffrey Stedfast - - Fixes bug #27672 - - * camel-mime-filter-bestenc.c: Conditionally #include - - * camel-mime-filter-linewrap.c: Same here... although we could - probably just get rid of this filter? We don't seem to use it - anywhere since we try to QP/Base64 encode any text parts with long - lines. Besides, we couldn't use this filter for SMTP anyway since - we can't risk possibly linewrapping a binary mime part. I dunno, - maybe this could be useful in the composer though? *shrug* - - * providers/smtp/camel-smtp-transport.c (smtp_data): Always call - camel_mime_message_set_best_encoding() even if the server allows - 8BITMIME and even if we don't have any 8bit parts because we may - have parts with long lines (>998 octets) which also need to be - encoded. - - * camel-mime-message.c (check_8bit): Don't forget to check for the - binary encoding here as well. - -2002-07-11 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (parse_fetch_response): If we - are fetching HEADERs, don't cache the stream - instead just create - a mem-stream and return that. This reduces a significant amount of - overhead due to disk i/o. - - * camel-multipart-encrypted.c (camel_multipart_encrypted_decrypt): - Don't forget to set an appropriate exception before returning - NULL. - -2002-07-10 Jeffrey Stedfast - - * camel-filter-driver.c (get_message_cb): Make sure message is - non-NULL before setting the source on it. - - * camel-gpg-context.c: Renamed stdin to stdin_fd, stdout to - stdout_fd, and stderr to stderr_fd in struct _GpgCtx since - Solaris' stdin/stdout/etderr variables seem to be macros and are - thus breaking the compilation. - -2002-07-04 Jeffrey Stedfast - - * providers/nntp/camel-nntp-provider.c: Set the IS_SOURCE provider - flag. - - * providers/pop3/camel-pop3-store.c: Change all exceptions to - report which POP server failed (and tried to make a few of the - exceptions a bit more clear). - -2002-07-03 Not Zed - - * camel-vee-folder.c (vee_sync): If we get an exception from the - child sync, update the exception string so we know where it really - was. - - * camel-vee-store.c (change_folder): Util to emit created/deleted - events. - (vee_get_folder): If the folder has path elements, and its parents - dont exist, create dummy no-select nodes. This is for bug #4246. - (vee_delete_folder): Use change_folder() to save code. - - * providers/local/camel-mbox-folder.c (mbox_set_message_flags): - Only set xevchange if we're storing status headers in pine format, - so we dont do a full sync every time any flag changes. - -2002-06-27 Not Zed - - * camel-object.c (camel_object_hook_event): Take a void object arg. - (camel_object_remove_event): " - (camel_object_unhook_event): " - (camel_object_trigger_event): ", also, execute events in the same - order they were added, i.e. reverse hook-list order. - -2002-06-28 Jeffrey Stedfast - - * camel-gpg-context.c (gpg_ctx_get_argv): Don't use - --no-auto-key-retrieve, this option has apparently been deprecated - in gpg 1.0.7. - -2002-06-27 Jeffrey Stedfast - - * camel-gpg-context.c (gpg_ctx_op_step): Loop on our reads while - errno is EINTR or EAGAIN. Also make sure to completely read stdout - and stderr by keeping better state. - (gpg_ctx_parse_status): In the case of a NODATA response from gpg, - try to use the diagnostics that gpg may have written to its - stderr. - (gpg_verify): Check that the gpg process has not exited. - (gpg_ctx_op_wait): Make sure we haven't already exited (as by - gpg_ctx_op_is_exited()) and if we have, retrieve the exit status - from the gpg context. - -2002-06-26 Jeffrey Stedfast - - * camel-pgp-context.[c,h]: Removed. - - * camel-pgp-mime.c (pgp_mime_part_sign_restore_part): Removed. - (pgp_mime_part_sign_prepare_part): Removed. - (camel_pgp_mime_part_sign): Removed. - (camel_pgp_mime_part_verify): Removed. - (camel_pgp_mime_part_encrypt): Removed. - (camel_pgp_mime_part_decrypt): Removed. - (camel_pgp_mime_is_rfc2015_signed): Documented. - (camel_pgp_mime_is_rfc2015_encrypted): Same. - -2002-06-26 Jeffrey Stedfast - - * camel-multipart-encrypted.c (camel_multipart_encrypted_encrypt): - Oops, this needs to take a userid argument. - - * camel-gpg-context.c (gpg_clearsign): Removed (never did anything - anyway). - - * camel-pgp-context.c (pgp_clearsign): Removed. - - * camel-cipher-context.c (camel_cipher_clearsign): Removed unused - method. - - * camel-multipart-encrypted.[c,h]: New class implementing the - multipart/encrypted content type. Contains methods for encrypting - and decrypting a multipart/encrypted MIME object. - - * camel-gpg-context.c (gpg_ctx_parse_status): Check for NODATA - too. - -2002-06-25 Jeffrey Stedfast - - * providers/local/camel-local-provider.c: Remove the #include for - camel-spoold-store.h - -2002-06-26 Not Zed - - * camel-gpg-context.c: Include for struct timeval. - - * providers/local/camel-local-provider.c - (camel_provider_module_init): Removed spoold provider. The spool - provider does it now. - (): Spoold doesn't exist anymore, remove its header. - -2002-06-25 Not Zed - - * providers/local/camel-spool-folder.c (camel_spool_folder_new): - Support a new xstatus option - folders update/honour the - Status/X-Status headers in addition to X-Evolution. - - * providers/local/camel-local-summary.c - (camel_local_summary_write_headers): If supplied with an - additional status or xstatus arg, write a Status header and/or - X-Status. Also fix the case of properly terminating the headers - if an xev line isn't supplied. - - * providers/local/Makefile.am (libcamellocalinclude_HEADERS,SOURCES): - Removed spoold-store.[ch]. - - * providers/local/camel-local-provider.c - (camel_provider_module_init): For the spoold type, just use the - spool store instead. - - * providers/local/camel-spool-store.h: Added a type field, so the - 1 store can implement different types without having to subclass. - - * providers/local/camel-spool-store.c - (camel_spool_store_get_toplevel_dir): Removed, inherits from local - store now. - (construct): If we're pointing to a file, treat it as mbox mode, - otherwise treat it as 'elm' mode. - (get_folder): Only test for INBOX in mbox mode. - (get_folder_info_elm): - (get_folder_info_mbox): Two alternatives for getting folder info, - depending on the type of folder we're looking at. - (get_folder_info_mbox): Make the url include the protocol. - (scan_dir): " - - * providers/local/camel-spoold-store.c - (camel_spoold_store_get_toplevel_dir): Removed, inherits from - local store now. - - * camel-folder.c (get_message_user_tag): Dont use a - g_return_if_fail for info==NULL. This is not an error. - (set_message_user_tag): And same here. - (set_message_user_flag): Sigh, and here. - (get_message_user_flag): And here. - (set_message_flags): and here ... - (get_message_flags): Dum de dum, de done at last. - - * providers/local/camel-mbox-folder.c (mbox_get_message): Check - for new messages whenever we retrieve one. In the common - no-update case, this is a single stat. - (mbox_get_message): If we need to rescan, then force a full rescan - to make sure it does the right thing. - (mbox_get_message): Cleanup the exception handling a bit, if we do - get an error, propagate any folder changes anyway as well. - (mbox_set_message_user_flag): Argh more of these stupid g_returns - taht shouldn't be. - (mbox_set_message_user_tag): Here too. - (mbox_set_message_flags): If the read flag is being changed, mark - it as an xevchange (i.e. Status line change). - - * providers/local/camel-mbox-summary.c (summary_rebuild): Merged - into summary_update. - (summary_update): Changed to allow it to update existing lists of - messages without clearing out the summary. - (mbox_summary_check): Dont clear the summary, just re-scan. - (message_info_new): Attempt to support the 'Status: RO' elm/pine - thing. - (camel_mbox_summary_encode_status): - (camel_mbox_summary_decode_status): Util functions for - creating/parsing the Status line. - (camel_mbox_summary_sync_mbox): Write out the status line if we're - going to try support it. - (camel_mbox_summary_xstatus): Implement option to control - read/write of (x-)status. - (message_info_new): Do x-status stuff based on run-time option. - (camel_mbox_summary_sync_mbox): " - (mbox_summary_add): If x-status enabled, then always add - status/x-status headers to message. - - * camel-folder-summary.c (summary_assign_uid): If the messageinfo - is already in the summary, AND is the same messageinfo, dont do - anything, return a value to indicate this. - (camel_folder_summary_add): Do nothing if this info already in the - summary, so we can perform updates. - -2002-06-24 Not Zed - - * providers/local/camel-local-summary.c - (camel_local_summary_check_force): New method to force the next - summary check to be a full check, set if a mismatch occurs. - - * camel-folder-summary.c (camel_folder_summary_load): If we have - no summary path set, dont do any i/o, rather than abort. - (camel_folder_summary_save): " - (camel_folder_summary_header_load): " - - * providers/local/camel-spool-store.h: Inherit from camel mbox - store, even if we override almost everything. - - * providers/local/camel-local-folder.c - (camel_local_folder_construct): If the base path points to a file, - use that as the folder path as well. - - * providers/local/camel-spool-folder.h: Inherit from - camel-mbox-folder. - - * providers/local/camel-spool-summary.c (spool_summary_sync_full): - Use camel_mbox_summary_sync_mbox to do most of the work. - - * providers/local/camel-spool-summary.[ch]: Make spool-summary - inherit from mbox summary rather than foldersummary. - - * providers/local/camel-mbox-summary.c (mbox_summary_sync): Make - sync_full/quick virtual methods. - (camel_mbox_summary_sync_mbox): The full sync method put into a - simple function that sync's from fd to fd. - (mbox_summary_sync_full): Use summary_sync_mbox to do the real - work. - (mbox_summary_check): Create removed events if the folder gets - cleared. Also, dont clear the summary before a rebuild, try to - merge. - -2002-06-25 Jeffrey Stedfast - - * camel-gpg-context.c: #include - -2002-06-25 Jeffrey Stedfast - - * camel-gpg-context.c (gpg_hash_str): Return the option as - --digest-algo= - (gpg_ctx_parse_status): Decode more status information and keep - track of trust and such. - (gpg_ctx_op_complete): Make sure we aren't waiting for gpg to - write data to stdout (such as encrypted/decrypted data or a - signature). - (gpg_encrypt): Remove the fejj@stampede.org hard-coded value - (which had only meant to be for testing). - -2002-06-24 Jeffrey Stedfast - - * camel-gpg-context.c (gpg_ctx_get_argv): Use --command-fd rather - than --passphrase-fd since what we really want is an interactive - mode (besides, --passphrase-fd requires a passphrase to be sent - before --status-fd will send a NEED_PASSPHRASE status message). - (gpg_ctx_parse_status): When we encounter a BAD_PASSPHRASE, tell - the session to uncache it. - (camel_gpg_context_set_always_trust): Implemented. - -2002-06-23 Jeffrey Stedfast - - * camel-gpg-context.c (gpg_ctx_parse_status): Check for ERRSIG - also. - (gpg_ctx_op_step): Don't try writing a passphrase unless our - operation requires it. - -2002-06-22 Jeffrey Stedfast - - * camel-gpg-context.c (gpg_encrypt): Return -1 on error. - (gpg_decrypt): Same. - (gpg_sign): Again here. - (gpg_ctx_op_step): Only attenmpt to read from the status-fd if we - are not already 'complete'. - - * camel-pgp-mime.c (camel_pgp_mime_part_encrypt): Flush the - filtered stream. - -2002-06-21 Jeffrey Stedfast - - * camel-gpg-context.[c,h]: New source files implementing the - CamelCipherContext class for gnupg. - - * camel-pgp-context.c (camel_pgp_context_new): Return a - CamelCipherContext. - - * camel-pgp-mime.c (camel_pgp_mime_part_decrypt): Take a - CamelCipherContext argument rather than a CamelPgpContext since we - now have a CamelGpgContext also. - (camel_pgp_mime_part_encrypt): Same. - (camel_pgp_mime_part_verify): Same. - (camel_pgp_mime_part_sign): Same. - -2002-06-20 Jeffrey Stedfast - - * camel-digest-folder.c: Updated to support searching as well as - making it use CamelDigestSummary. - - * camel-digest-summary.[c,h]: New class to handle the summary for - CamelDigestFolder. - - * camel-tcp-stream-ssl.c (set_errno): PR_IO_TIMEOUT_ERROR should - map to ETIMEDOUT and not EAGAIN. - (stream_connect): Reset the PR_Poll() timeout back to 2 minutes as - this wasn't the problem afterall. - -2002-06-19 Not Zed - - * camel-mime-parser.c (folder_scan_drop_step): Drop back to - initial state if we came from eof state. - -2002-06-19 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (stream_connect): Set the poll timeout to - be PR_INTERVAL_MIN, this one shouldn't need to be 2 minutes (plus - it blocks my connection at home for far too long). - - * providers/imap/camel-imap-folder.c (imap_refresh_info): Make - sure we hold the command_lock before accessing current_folder. - (imap_append_online): Same. - (imap_transfer_online): Same. - - * providers/imap/camel-imap-store.c (delete_folder): We need to - hold the command_lock before we can set the current_folder to - NULL. - (rename_folder): Same. - (get_folder_info_online): We need to make sure we hold the - command_lock in order to use current_folder. - (everywhere): Same. - -2002-06-19 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_connect): Don't - bother trying to authenticate (and thus don't throw up an error - dialog) unless the server is an ESMTP server and supports - authentication. - - * camel-sasl-plain.c: Change the user-friendly name to PLAIN, this - is what it should be. Not "Password" because user's immediately - think that they need authentication when they see "Password" even - if they don't need it at all. - -2002-06-17 Jeffrey Stedfast - - * camel-vee-folder.c (camel_vee_folder_add_folder): Update the - freeze state of the new source folder. - (camel_vee_folder_remove_folder): Undo any freeze state that we - have imposed on this source folder. - -2002-06-14 Jeffrey Stedfast - - * camel-vee-folder.c (vee_freeze): Freeze source folders. - (vee_thaw): Thaw all source folders. Fixes bug #24317. - - * providers/imap/camel-imap-folder.c (imap_sync_online): Unlock - the command_lock after each UID STORE command so that other - (probably more important) threads can send their requests. - - * camel-arg.c: - * camel-disco-diary.c: - * camel-index-control.c: - * camel-mime-part.c: - * camel-pgp-mime.c: - * camel-store.c: - * camel-tcp-stream-ssl.c: - * camel-text-index.c: Fixed compiler warnings. - - * camel-multipart-signed.c: Updated to use ctx->sign_protocol - rather than ctx->protocol. - - * camel-cipher-context.h: Add an ecnryption protocol member. - - * camel-pgp-context.c (camel_pgp_context_init): Set the encryption - protocol. - -2002-06-11 Not Zed - - * camel-vtrash-folder.c (camel_vtrash_folder_class_init): Our - parent class is camel_vee_folder, not camel_folder, fix setting of - parent folder (unused anyway, but removes a run-time warning). - -2002-06-07 Not Zed - - * camel-pgp-context.c (camel_pgp_context_init): Duh! The protocol - is application/pgp-signature. TODO: need to have a signed and an - encrypted protocol specified separately. - -2002-06-06 Not Zed - - * camel-folder-thread.c (thread_summary): Do the work here. - (camel_folder_thread_messages_remove): Implement. Remove some - uid's from the tree. Disalbe from build, for now. - (remove_uid_node_rec): Actually do the work. - (camel_folder_thread_messages_add): Implement. Add some summary - items to the tree. Disable from build though. - (camel_folder_thread_messages_apply): Make a thread tree built - using camel_folder_thread_new() map to a new set of uids, - preserving some order. Meant primarily to manage deleted + added - uids in a user-friendly manner. - -2002-06-09 Jeffrey Stedfast - - * camel-multipart-signed.c (camel_multipart_signed_verify): Use - CAMEL_EXCEPTION_SYSTEM rather than '1' for clarity. - -2002-06-07 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (stream_connect): Up the timeout on the - connect code to 2 minutes. - -2002-06-05 Dan Winship - - * camel-mime-utils.c (header_decode_mailbox): Parse - "From: Dan Winship " (with no domain) in the way the sender - meant it, even though it's completely wrong. - -2002-06-04 Not Zed - - * providers/local/camel-local-provider.c: Remove the - CONF_DEFAULT_PATH entry, as this is handled by the url config - stuff. This made it basically impossible to configure any local - folder from the gui. - - * providers/local/camel-local-folder.c (local_refresh_info): Force - a refresh. Should work for all local folders to force them to - refresh. - - * providers/local/camel-maildir-folder.c (maildir_refresh_info): - Removed, moved into camel-local-folder. - - * providers/local/camel-mh-summary.c (mh_summary_next_uid_string): - Once we assign or get a uid, tell the summary of this, so the next - uid we get will be higher than any previously. - - * camel-object.c (camel_object_ref, camel_object_unref): I got - sick of casting, these now take void * like they should, and - perform their own run-time type checking. - - * providers/local/camel-mh-store.c (recursive_scan): Changed to - use stat, not lstat (*shrug* maybe someone wants to softlink their - maildir tree?). - (inode_hash): - (inode_equal): - (inode_free): Copied from camel-maildir store (should put into - camel-local-store or utils?). - (recursive_scan): Changed to check for re-visiting inodes. Also, - it builds the tree itself, rather than using folder_info_build. - (add_folder): Changed to folder_info_new. - (recursive_scan): Properly honour the recursive flag. Also, - lookup unread count from folder. - (folder_info_new): Init unread message count to -1, since we dont - know yet. - (folder_info_new): Take the name as an argument, and perform the - merging here. - (folders_update): Util func to add/remove folders from .folders - file. I'm assuming its sorted. - (get_folder): Add the folder to .folders if we created a new one, - and if it exists. - (delete_folder): Remove from .folders, etc. - (folders_scan): If we have a .folders file, read and use that - instead. - (recursive_scan): Handle scanning from a particular directory - properly. - (rename_folder): Implement so we can track any changes to the - .folders file if its turned on. - - ** Applied patch below from Greg Hudson. - -2002-05-10 Greg Hudson - - * camel-mh-store.c (get_inbox, get_folder_info, recursive_scan, - add_folder): Implement support for MH stores. - - * camel-mh-summary.c (mh_summary_check, sort_uid_cmp): Sort MH - messages by message number (uid), like we sort maildir messages by - date. - - * camel-local-provider.c (mh_provider): Turn on source and store - flags. - -2002-06-03 Not Zed - - * camel-vee-folder.c (camel_vee_folder_add_folder): - (folder_changed_change): - (folder_changed_remove_uid): - (folder_changed_add_uid): - (vee_folder_build_folder): Check that any unmatched operation is - not concerning any vfolder. Other vfolders should never be part of any - unmatched handling. For #24615, and others probably. - -2002-06-02 Not Zed - - * camel-sasl.c (camel_sasl_new): - (camel_sasl_finalize): setup/free the mech string. - - * camel-sasl.h: Added 'mech' mechanism string. - -2002-06-01 Not Zed - - * providers/imap/camel-imap-folder.c (imap_getv): Implement. Only - the object_description arg. - (camel_imap_folder_get_type): Init parent_class holder. - - * providers/local/camel-local-folder.c (local_getv): Implement, - object_description arg. - - * camel-folder.c (folder_getv): Implement, add a bunch of args you - can get -> camel_folder_get_unread_count etc will be going RSN i - hope. - (camel_folder_finalize): Free cached description string. - - * camel-object.c (cobject_getv): Implement - CAMEL_OBJECT_ARG_DESCRIPTION, just return the classname of the - object. - (camel_object_getv): - (camel_object_get): - (camel_object_setv): - (camel_object_set): Take object = void *, to simplify usage. - (camel_object_setv): Removed unecessary locals. - (camel_object_getv): Same. - (camel_object_free): New method, free an arg, upto implementations - whether args are static/const or not. - (cobject_free): Implement a dummy do nothing free. - -2002-05-31 Not Zed - - * camel-vee-folder.c (camel_vee_folder_get_location): new function - to get the real location (folder) (and uid) of a vfolder object. - Using the folderinfo, since we already have it, maybe it should - use the uid. - -2002-05-31 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (get_content): When the part - is a multipart/signed, make sure to free the part_spec before - returning (the other types already did this properly). - - * providers/imap/camel-imap-message-cache.c - (camel_imap_message_cache_get): Free the path buffer when we're - done with it. - - * providers/imap/camel-imap-folder.c (imap_update_summary): Free - the final tagged response buffer. - - * providers/imap/camel-imap-command.c (imap_read_untagged): If we - fail to read a literal, free the temporary string buffer. - - * providers/imap/camel-imap-folder.c (imap_rescan): Revert my fix - from the other day since camel_imap_command_response() doesn't - guarentee that resp will be set to NULL on error. - - * camel-data-cache.c (camel_data_cache_get): If we fail to be able - to create a stream to insert into the cache, then free the 'real' - path. - -2002-05-30 Not Zed - - * camel-cipher-context.h: Added a protocol field for users to use. - - * camel-stream-filter.c (do_read): Sigh, the pre-size is READ_PAD - not READ_SIZE. Big difference. - (READ_PAD): Bumped upto 128 from 64, so we can fit a typical line - in full. - - * providers/imap/camel-imap-folder.c (get_content): Changed to - load multipart/signed as an opaque block into the right kind of - object. - - * camel-multipart.h (struct _CamelMultipart): Removed the boundary - field. It wans't actually used anywhere. - - * camel-seekable-substream.c - (camel_seekable_substream_new_with_seekable_stream_and_bounds): - Shortened this stupidly long name to just :new(), its the only way - its ever used. Fixed all callers. - - * camel-multipart-signed.[ch]: new wrapper for multipart/signed - types. We need to treat the entire content as a blob of data for - transport purposes. This also cleans up a lot of the sign/verify - handling. - - * camel-mime-part-utils.c - (camel_mime_part_construct_content_from_parser): Just call - camel_multipart_construct_from_parser for multipart parts, also - use a multipart_signed for multipart/signed types. - - * camel-multipart.c (camel_multipart_construct_from_parser): New - virtual function for multiparts to buld themselves. - (construct_from_parser): Implement for normal multiparts. - (toplevel): Got rid of a warning, it'll never be an abstract - class. - - * camel-pgp-context.c (pgp_hash_to_id): - (pgp_id_to_hash): Implement. - (camel_pgp_context_init): Init the pgp protocol specifier. - - * camel-cipher-context.c (camel_cipher_id_to_hash): - (camel_cipher_hash_to_id): Util virtual methods to handle the - cipher id string. - - * camel-mime-filter-canon.[ch]: A new filter, end/start of line - canonicalisation filter. Can escape "From " and strip trailing - whitespace, and canonicalise the end of line to crlf or to lf. - -2002-05-29 Not Zed - - * camel-multipart.h (struct _CamelMultipart): Removed the - 'parent', nothing used it, anywhere. Cleaned up some formatting - slightly. - -2002-05-30 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (camel_imap_store_readline): - On error, don't leak the GByteArray buffer. - - * providers/imap/camel-imap-folder.c (imap_rescan): Free the - response before checking for errors. I'm not sure this'll actually - fix the memory leak here, but it might? Certainly can't hurt. - - * camel-block-file.c (camel_block_file_finalise): Destroy the - blocks hash table. - -2002-05-29 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (connect_to_server): Only free - the LOGOUT response if it is non-NULL. - -2002-05-28 Not Zed - - * providers/local/camel-maildir-folder.c (maildir_refresh_info): - Implement. Run a summary check to update for any newly arrived - messages. - - * providers/local/camel-maildir-store.c (scan_dir): If we have a - folder, execute a refresh_info on it, to suck in any new stuff. - -2002-05-28 Jeffrey Stedfast - - * camel-filter-driver.c (camel_filter_driver_log): Use the - CamelMessageInfo rather than the CamelMimeMessage because the - message may not have been loaded (thus NULL). - -2002-05-27 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (connect_to_server): On - connection failure, unref the tcp stream. - - * providers/pop3/camel-pop3-store.c (connect_to_server): On - connection failure, unref the tcp stream. - - * providers/imap/camel-imap-store.c (connect_to_server): On - connection failure, unref the tcp stream. - - * providers/nntp/camel-nntp-store.c (nntp_store_query_auth_types): - Our parent class is no longer CamelRemoteStore. - (nntp_store_init): Same. - (camel_nntp_store_get_type): Here too. - (nntp_connect): Rewritten to try to connect via SSL. Also remove - code using CamelRemoteStore. - (camel_nntp_command): Don't call camel_remote_store_connected(). - -2002-05-24 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (content_info_get_part_spec): - Helps if we allocate enough space here. Also, start smoking the - same purple flavoured IMAP crack when counting parts (parts don't - count if their parent part is a message/* part with a parent - part). Fixes bug #25260. - -2002-05-24 Jeffrey Stedfast - - * providers/imap/camel-imap-command.c (imap_read_untagged): Use - the new readline function. - - * providers/imap/camel-imap-store.c (connect_to_server): Use the - new camel_imap_store_readline() function which doesn't suck quite - as bad as the original camel_remote_store_recv_line() function. - (camel_imap_store_readline): New function to replace - camel_remote_store_recv_line(). This function is at least safe - with embedded nul chars. Not that any of our callers use it - *sigh*. - -2002-05-24 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (connect_to_server): Added - some NULL protection fixes. - -2002-05-22 Jeffrey Stedfast - - * camel-remote-store.c: Removed from the build. Glory glory - hallelujah. - - * camel-disco-store.c: Updated to inherit from - CamelStore rather than CamelRemoteStore. - - * providers/imap/camel-imap-command.c (imap_command_start): Don't - use the camel-remote-store shit to send a string. Just use - camel_stream_printf for chrissakes. - - * providers/imap/camel-imap-store.c: Updated to not depend on - CamelRemoteStore and to handle STARTTLS. - (imap_disconnect_online): Unref the streams. - (imap_keepalive): Removed. - (camel_imap_store_connected): New function to replace - camel_remote_store_connected(). - (camel_imap_store_finalize): Unref the streams. - (camel_imap_store_recv_line): New function to replace - camel_remote_store_recv_line(). - (imap_get_capability): Renamed from connect_to_server - (connect_to_server): New function to try and connect to the - server. - (connect_to_server_wrapper): New wrapper function around - connect_to_server that takes the ssl modes into consideration. - (query_auth_types): Don't bother calling our parent's - implementation of query_auth_types() since CamelDiscoStore doesn't - have any anyway. - (imap_get_name): New method to implement CamelService::get_name - -2002-05-18 Not Zed - - * camel-search-private.c (camel_utf8_getc): If we get an invalid - start char, just ignore it and goto the next character. - -2002-05-16 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (get_folder_offline): Don't - call some retarded function to simply set an exception. - - * camel-filter-search.c (get_label): New e-sexp callback function - to get a user_tag label value. - -2002-05-15 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c - (imap_parse_namespace_response): New function to parse a NAMESPACE - response properly. - (imap_namespaces_destroy): New function to destroy the returned - structure from the above function. - -2002-05-15 Jeffrey Stedfast - - * camel-service.c (service_setv): Only reconnect if we are already - connected, if we are in a disconnected state then no need to - reconnect. - - * providers/imap/camel-imap-folder.c (get_content): If the - part_spec is an empty string for a leaft part, use "1" since we - don't actually want to get the raw message headers too. - -2002-05-15 Not Zed - - * providers/imap/camel-imap-store.c (refresh_folder_info): removed. - (imap_store_refresh_folders): Copy the folders first, then refresh - them, outside of the cache_lock, which could cause deadlocks - because of a workaround for crappo exchange. - (imap_disconnect_online): Dont pass an exception to LOGOUT - command. The required response 'BYE' always sets an exception - when we call LOGOUT. This also interfered with a lot of other - processing causing partial failures and messed up offline/online - state. - - * camel-disco-folder.c (disco_prepare_for_offline): Do progress - reporting. - -2002-05-14 Jeffrey Stedfast - - Fixes bug #24136. - - * providers/imap/camel-imap-folder.c (content_info_get_part_spec): - New function to take a CamelMessageContentInfo and generate a - part-specification string. - (get_content): Stop passing around part_spec strings and use - content_info_get_part_spec instead. - - * camel-folder-summary.c (camel_content_info_dump): Made this into - a public debugging function. - - * providers/imap/camel-imap-utils.c (imap_parse_body): Make sure - to set the parent of any message/rfc822 subparts. - -2002-05-13 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_message): Previous - fix reverted. - -2002-05-13 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (camel_imap_store_class_init): - Overload the setv/getv CamelObject virtual methods. - (imap_setv): Implemented. - (imap_getv): Implemented. - -2002-05-13 Dan Winship - - * camel-folder.c (camel_folder_append_message): Add a "char - **appended_uid" argument, for the caller to optionally pass in a - variable to receive the UID of the appended message (if the - provider knows it). - (camel_folder_transfer_messages_to): Likewise, add "GPtrArray - **transferred_uids" - (transfer_messages_to): Update default implementation to handle - transferred_uids. - - * camel-disco-folder.c (disco_append_message, - disco_transfer_messages_to): Update for API changes. - - * camel-disco-diary.c (camel_disco_diary_replay): Update the - diary's temporary uid->real uid map when replaying appends and - transfers. - - * providers/imap/camel-imap-folder.c (imap_append_offline, - imap_append_online, imap_transfer_offline): Pass back the new - UIDs, when requested and available. - (imap_append_resyncing): Pass back the new UIDs when requested and - available. Remove the diary uidmap managing code since - CamelDiscoDiary can handle that itself now. - (imap_transfer_online, imap_transfer_resyncing): Update for new - APIs, but don't actually pass back the new UIDs yet. (It's tricky - since the COPYUID response may not be in the same order as the - input uids.) - - * providers/local/camel-maildir-folder.c (maildir_append_message): - Pass back the new UID if requested. - - * providers/local/camel-mbox-folder.c (mbox_append_message): - Likewise. - - * providers/local/camel-mh-folder.c (mh_append_message): Likewise. - - * providers/local/camel-spool-folder.c (spool_append_message): - Likewise. - - * camel-digest-folder.c (digest_append_message, - digest_transfer_messages_to): Update for API changes. - - * camel-filter-driver.c (camel_filter_driver_filter_message, - do_copy, do_move): Update for API changes. - - * camel-vee-folder.c (vee_append_message, - vee_transfer_messages_to): Likewise. - - * camel-vtrash-folder.c (vtrash_append_message, - vtrash_transfer_messages_to): Likewise. - -2002-05-13 Not Zed - - * camel-folder-thread.c - (camel_folder_thread_messages_new_summary): - (camel_folder_thread_messages_new): Since the fix for #3357 uses - 'order=0' to indicate tree structure nodes, make sure we dont - actually set order=0 for valid messages, otherwise we silently - lose duplicates of the first message (i==0). Fixes #19920. - -2002-05-10 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_message): Fetch the - BODYSTRUCTURE rather than BODY since BODY seems to be lacking some - of the data we need. This fixes bug #24136. - - * camel-transport.c (camel_transport_get_type): Might help if we - called camel_transport_class_init. - -2002-05-10 Dan Winship - - * camel-folder.c (camel_folder_transfer_messages_to): Replace - copy_messages_to and move_messages_to with a single function that - just takes a "delete_originals" flag. Also, use the vtrash - implementation if *either* folder is a vtrash. - (transfer_messages_to): Make this use camel_operation_progress - (previously move_messages_to did but copy_messages_to didn't), and - freeze/thaw the folder(s) if doing multiple messages. - - * camel-vtrash-folder.c (vtrash_transfer_messages_to): Update for - move/copy merge. Move the "move messages into vtrash" code here - from mail-ops.c. Now all of the vtrash move/copy special casing is - in camel instead of half of it being here and half in mail/. (This - should also make it so that "Move to Trash" will work in filter - rules.) - - * camel-vee-folder.c (vee_transfer_messages_to): Make this just - return an exception, since it will only be called when trying to - move/copy messages from one vfolder to another. - (vee_append_message): Add this too so we get a nicer error message - than the default "unimplemented" one in camel-folder.c. - - * camel-digest-folder.c: Replace copy_messages_to and - move_messages_to with transfer_messages_to. - - * camel-disco-folder.c: Likewise - - * camel-disco-diary.c (camel_disco_diary_log, - camel_disco_diary_replay): replace MOVE/COPY with TRANSFER. - - * providers/imap/camel-imap-folder.c (imap_transfer_offline, - imap_transfer_online, imap_transfer_resyncing): Update for - changes. (This ends up being a bit more complicated than it was - before for now, but later disconnected operation changes should - resimplify it.) - - * camel-filter-driver.c (camel_filter_driver_filter_message, - do_copy, do_move): Use transfer_messages_to instead of copy. - -2002-05-09 Jeffrey Stedfast - - * camel-filter-search.c (shell_exec): New filter function to pipe - a message to another program. - (run_command): Fixed some bugs to make this work. - -2002-05-09 Not Zed - - * camel-service.c (camel_service_disconnect): Instead of testing - for SERVICE_CONNECTED, we need to also handle SERVICE_CONNECTING - too, as it will often have setup some details before it failed. - Make it !DISCONNECTED (and !DISCONNECTING for recursive calls, - which happen). Fixes #23782, and maybe also #21604 and many other - random crashes. - -2002-05-08 Jeffrey Stedfast - - * camel-digest-store.c (digest_setv): Implemented. - (digest_getv): Implemented. - - * camel-disco-store.c (disco_setv): Implemented. - (disco_getv): Implemented. - - * camel-remote-store.c (remote_store_setv): Implemented. - (remote_store_getv): Implemented. - - * camel-transport.c (camel_transport_class_init): Implemented. - (transport_setv): Implemented. - (transport_getv): Implemented. - - * camel-store.c (store_setv): Implemented. - (store_getv): Implemented. - - * camel-service.c (service_setv): Implemented. - (service_getv): Implemented. - - * providers/pop3/camel-pop3-store.c (pop3_try_authenticate): - camel_pop3_engine_iterate doesn't return the state, it returns -1 - on fail, 0 when finished processing request or >0 if more ops are - in the queue, so don't check status against CAMEL_POP3_STATE_OK, - instead check pcp->state against that. - -2002-05-07 Jeffrey Stedfast - - * camel-object.h: s/class/klass for arguments so that c++ - developers don't complain later. - -2002-05-07 Dan Winship - - * camel-object.c (camel_object_class_cast): Fix a crash in a - g_warning. - -2002-05-07 Not Zed - - * camel-remote-store.c (remote_send_string): Check for LOGIN xxxx - as well if debug is on, so we dont print passwords to evolution - logs. - - * providers/imap/camel-imap-utils.c (imap_is_atom_char): This was - really broken. 1. isprint() is locale dependent, and 2. it looked - up an 8 bit value in a 7 bit table without truncating it. I've - removed the isprint() stuff and just put it directly into the - special table, which i've expanded to the right size too. - - * providers/imap/*: Applied patch from Preston Elder - to make camel only use literals if it needs to - for simple strings. Changed slightly to use imap_is_atom() and - more consistent formatting. - * providers/imap/camel-imap-utils.c (imap_is_atom): Changed from - imap_needs_quoting(). - - ** Merged in camel-object2 branch. Simpler camelobject - implementation + object args interface. - - * camel.c (camel_init): Call camel_object_get_type() to make sure - camel_object_type is initialised. - - * camel-object.h (CAMEL_OBJECT_TYPE): Changed to return global - camel_object_type pointer, not call camel_object_get_type. - -2002-05-06 Jeffrey Stedfast - - * providers/pop3/camel-pop3-store.c (pop3_try_authenticate): If - the pop3 command status is -1, then we probably have a TCP error - (?) so set a SYSTEM exception so our caller can distinguish - between a "bad password" and a "tcp error". - (pop3_connect): Only uncache the password on "bad password" - errors. - - * camel-pgp-mime.c (pgp_mime_part_sign_prepare_part): Use - CamelMimeFilterBestenc to get a more appropriate encoding rather - than just blindling assigning QP. - - * providers/imap/camel-imap-folder.c (do_append): Call - camel_mime_message_encode_8bit_parts() which fixes bug #10885. - - * camel-tcp-stream-raw.c (socket_connect): Don't bother with - counting down the timeout. - -2002-05-02 Jeffrey Stedfast - - * camel-stream-fs.c (stream_read): Same fix as the tcp stream. - (stream_write): Again here. Just like tcp stream's stream_write(), - also make sure to save errno before calling fcntl to restore the - fd flags. - - * camel-tcp-stream-raw.c (stream_read): Handle EINTR errors for - select(). - (stream_write): Same and also preserve errno when setting the fd - flags back. If w == -1, return -1. - -2002-05-02 Jeffrey Stedfast - - * camel-mime-utils.c (header_decode_mailbox): Fixed the fix for - stupidly-broken-mailer bug #5 to work when multiple unescaped - characters were in a row. Fixes bug #24140. - - * camel-tcp-stream-raw.c (socket_connect): Check select() for - EINTR errors. - - * camel-pgp-context.c (crypto_exec_with_passwd): Change the order - of some code so that we check if the select() failed before we - check for user-cancellation. - - * camel-service.c (camel_gethostbyname): Check for EINTR when - select()ing. - (camel_gethostbyaddr): Same. - -2002-04-29 Jeffrey Stedfast - - * camel-provider.c (camel_provider_auto_detect): Now takes a - CamelURL argument rather than a GHashTable *settings argument. - -2002-04-29 Not Zed - - * providers/local/camel-spool-store.c (get_folder_info): We want - to set unread_count to get_unread_message_count, not - get_message_count(). Might fix #17174. Also removed FIXME: as it - was fixed. - -2002-04-26 Jeffrey Stedfast - - * providers/local/Makefile.am: Don't link to libibex.a anymore. - - * providers/nntp/Makefile.am: Same. - - * providers/imap/Makefile.am: And again here. - - * camel-store-summary.h: No longer want to #include - - - * camel-provider.c (camel_provider_auto_detect): New function to - auto-detect configuration settings. - -2002-04-26 Not Zed - - * camel-block-file.c (block_file_validate_root): Remove the - excessive \n's, after printfs. - - * camel-text-index.c (text_index_compress_nosync): @!#$@#$!@$#!. - Since the rename op was fixed, this broke compression's rename, - resulting in the index 'vanishing' after every compress - (i.e. after every reindex). Fix this code to account for the - fixed rename operation. - -2002-04-25 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_rcpt): Don't put a - space between the "RCPT TO:" and the "" strings - - rfc0821 was not clear on this but it seems rfc2821 defines a - grammar excluding that SP. - (smtp_mail): Same. - -2002-04-24 Jeffrey Stedfast - - * providers/local/camel-local-provider.c - (camel_provider_module_init): Configure the default paths for mh, - mbox, maildir, spools, etc. - - * camel-provider.h: Add a CAMEL_PROVIDER_CONF_LABEL enum and - define some default CamelProviderConfEntry macros. - -2002-04-19 Jeffrey Stedfast - - * providers/pop3/camel-pop3-folder.c (pop3_refresh_info): Free the - LIST pop3 command. - - * camel-data-cache.c (data_cache_finalise): Free the cdc->path. - - * camel-multipart.c (write_to_stream): Don't g_return_val_if_fail - here if the boundary is an empty string. See bug #23676 for - details. The way I see it, we have 2 options: 1) leave this fix - the way it is, thus allowing multipart boundaries to be - empty-strings; or 2) make camel_multipart_get_boundary() change - the boundary to something legal if the boundary is an - empty-string. Since the parser should be able to handle an - empty-string boundary *and* more importantly because we want to - keep the same boundaries as the original raw message so as to be - able to verify multipart/signed parts, I vote for solution #1. - -2002-04-19 Not Zed - - * devel-docs/camel-index.txt: Start of a white-paperish document - describing camel-index and older libibex. - -2002-04-18 Not Zed - - * providers/local/camel-local-store.c (rename_folder): If we get a - failure, make sure we set an exception. - - * camel-text-index.c (camel_text_index_rename): If the file - doesn't exist, just assume it never did, dont return failure. - (text_index_rename): Add '.index' to the path name we're using, - since we dont get it passed in. - - * camel-folder-search.c (check_header): When doing a contains - match, split the words and perform an and on it. - (match_words_messages): If we have an index, but were forced to do - a full search, first lookup a subset of messages using - the index and a simplified word set. Only do a manual search of - this subset. - -2002-04-17 Not Zed - - * camel-folder-search.c (match_message_index): Changed to take a - utf8 string not a regex pattern. - (match_words_index): Matches against a camel_search_words list. - (match_words_1message): Matches a single message against a - camel_search_words list. - (match_words_message): Same, but gets the message from the folder - for you. - (match_words_messages): Matches a list of messages against a words - list. - (search_body_contains): Rewritten to handle multiple word - searches. For #23371. - - * providers/imap/camel-imap-search.c (sync_match): Split words - when searching, to support multiple search words. Also, try - searching specifying charset of utf8 if we can, if that fails, - fall back to not specifying charset. TODO: It should translate - the strings into the locale default charset? - - * providers/imap/camel-imap-store.c (connect_to_server): Added new - cap - utf8_search, if set, we tell the server we're searching - using utf8, otherwise we dont (incorrectly, since we always use - utf8 to search). - - * camel-search-private.c (camel_ustrstrcase): Make this class public. - (camel_search_words_split): Split a word into multiple words based - on whitespace, and keep track of whether the word is simple - (indexable directly), or not. - (camel_search_words_free): Free 'em. - -2002-04-17 Jeffrey Stedfast - - * camel-vee-folder.c (vee_search_by_expression): If the vee-folder - is the unmatched, we don't have our own expression so we cannot - merge them. Instead, just use the expression passed in. This fixes - a Null-Pointer-Read crash on Solaris systems at least. - -2002-04-16 Jeffrey Stedfast - - * camel-filter-driver.c (camel_filter_driver_filter_folder): Get - rid of an unused variable. - - * providers/smtp/camel-smtp-transport.c (smtp_helo): Use - camel_gethostbyaddr since gethostbyaddr is not reentrant. - - * camel-http-stream.c (http_connect): Updated after the rename of - camel_get_host_byname. - - * camel-service.c (camel_gethostbyname): Renamed. - (camel_gethostbyaddr): New cancellable/reentrant version of - gethostbyaddr. - -2002-04-14 Jeffrey Stedfast - - * providers/local/camel-spoold-store.c: Added #include - for dirent.h which needs it on MacOS X. - - * providers/local/camel-maildir-store.c: Same. - - * providers/nntp/camel-nntp-store.c: Same. - - * providers/imap/camel-imap-message-cache.c: Same. - - * camel-provider.c: Same. - - * camel-data-cache.c: Same. - -2002-04-12 Jeffrey Stedfast - - * broken-date-parser.c (datetok): Treat commas as token - delimeters. - (WEEKDAY_CHARS): Use full weekday names in case the broken mailer - used the full names. - (MONTH_CHARS): Same as above but for months. - -2002-04-15 Not Zed - - * *.c: Fix callers for api changes to camel-object, mainly - declare_event->add_event, and classfuncs->klass, and a couple - of missing #include 's - - * camel-arg.[ch], Makefile.am: New support code for - camel_object_get/set arg. - - * *.h: Fixed all uses of get_type to return a CamelType rather - than a guint (now a pointer). - - * camel-object.[ch]: Major cleanup of object implementation. Also - added a get/set interface, and some debugging options. - -2002-04-11 Not Zed - - * providers/local/camel-spool-summary.c (spool_summary_sync_full): - If the last message(s) were deleted, and we had any messages - output, account for the lost \n of the following From line by - adding an extra \n. fix for #8214. - -2002-04-10 Not Zed - - * camel-mime-part-utils.c (convert_buffer): If we get a 0 length - input, return a 0 lenght output as valid - fixes bugs with some - iconv impl and its simpler anyway. - -2002-04-11 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c: Set the UID_SET_LIMIT value - to 4096. I ran into an issue tonight where apparently the IMAP - server changed the UIDVALIDITY and so Evo needed to re-fetch all - headers and it was trying to send a uid set of some 25k (yes, I - have a very large INBOX). Anyways, it was set to unlimited - before. Courier IMAPd can safely handle up to ~16k per token, but - UW IMAPd can only handle 8k per command-line, so I set it to 4k - just to be safe. - -2002-04-10 Jeffrey Stedfast - - * camel-mime-part-utils.c (convert_buffer): Fixed a bug that would - miscalculate how much data to copy into the GByteArray (negative - value) thus causing a segfault. Also optimized it while I was at - it. - -2002-04-09 Jeffrey Stedfast - - * camel-store.c (camel_store_init): Make the folder_lock - recursive. See bug #22363 for details. Basically, - get_folder_info() is requesting a diary folder which in turn - connects which requests then calls get_folder() but deadlocks - because get_folder_info already holds the lock. - - * camel-mime-message.c (camel_mime_message_set_date): Don't adjust - the timezone offset if we used tm.tm_gmtoff because it is already - adjusted. - -2002-04-09 Not Zed - - * camel-mime-part.c (construct_from_parser): If we get multiple - Content-Type header values, change subsequent headers to - X-Invalid-Content-Type so it doesn't wreck processing. This fixes - the reported case in #18929, but i dont know if it fixes the - original posters problems. - -2002-04-08 Not Zed - - * camel-vtrash-folder.c (vtrash_move_messages_to): If we find - we're moving from the vtrash to another folder, we need to convert - the uid from a vfolder uid to the source uid (+8). Fix for - #20886. Also changed to batch multiple moves to different folders - so they are done as efficiently as possible rather than one at a - time. - - * camel-mime-utils.c (base64_decode_step): If we only get passed - '=', we back track only if we actually output any data. Fix for - #21716. - (quoted_decode): Pass out size_t instead of int, and use 0 instead - of -1 for error since its not signed. This will fix similar bug - to above in different circumstances since the result is taken as - unsigned. This is only an internal func. - (quoted_encode): Return size_t just for consistency. - - * camel-block-file.c (block_file_validate_root): Comment out the - debug and move it into a warning when the validation fails. - -2002-04-08 Jeffrey Stedfast - - * camel-mime-utils.c (uuencode_close): Don't count our filler when - encoding our line-length octet. - -2002-04-05 Jeffrey Stedfast - - * camel-http-stream.c (http_get_headers): Don't get the statuscode - here anymore. - (http_method_invoke): Use a User-Agent header and do basic proxy - authentication. - (stream_read): Handle redirects. - (camel_http_stream_set_user_agent): New function to allow client - to set the User-Agent string. - (camel_http_stream_set_proxy): New function for setting the proxy - server. - (camel_http_stream_set_proxy_authrealm): New function for setting - the proxy auth realm. - (camel_http_stream_set_proxy_authpass): New function for setting - the proxy auth password. - -2002-04-04 Jeffrey Stedfast - - * camel-folder-summary.c (message_info_new): Simplified since we - can now decode in-reply-to without getting extra cruft. Get rid of - the FIXME about having to check scan->id because of the - possibility of it being NULL, this can no longer happen. - - * camel-mime-utils.c (header_references_inreplyto_decode): New - function to decode in-reply-to headers. Only grabs the first thing - that looks like a message-id and then returns. - (header_references_decode): Loop calling - header_references_decode_single (a new internal function). - -2002-04-04 Not Zed - - * providers/imap/camel-imap-search.c (imap_body_contains): If - (body-contains) is not passed any arguments, return empty/false. - Fixes a crash exposed by #15001. - - * camel-remote-store.c (remote_connect): Reset the keepalive - timeout to 10 minutes rather than the 30 seconds I was using for - testing. - -2002-04-03 Dan Winship - - * camel-provider.h (CamelProvider): make service_cache be an array - of CAMEL_NUM_PROVIDER_TYPES elements so you can have a single - provider offer both stores and transports. (Eg, Exchange, NNTP) - - * providers/imap/camel-imap-provider.c: Don't initialize - service_cache here. (The session code can do it itself since the - url_hash and url_equal functions are stored as part of the - provider.) - - * providers/nntp/camel-nntp-provider.c: Likewise. - - * providers/local/camel-local-provider.c: Likewise. - - * providers/pop3/camel-pop3-provider.c: Likewise. - - * providers/sendmail/camel-sendmail-provider.c: Likewise. - - * providers/smtp/camel-smtp-provider.c: Likewise. - - * camel-session.c (register_provider): Initialize the provider's - service cache(s) here. - (camel_session_class_init): Don't initialize. - vee_provider.service_cache here. - (camel_session_destroy_provider): Update to destroy multiple - service_caches. - (service_cache_remove, get_service): Tweak these a bit to deal - with multiple service_caches. - -2002-04-02 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (set_errno): Handle a ton more nspr i/o - errno's. - (stream_connect): Act as if we are doing a non-blocking - connect. This is to try and work around bug #15120 where users get - an EINPROGRESS error. Maybe importing a PRFileDesc into SSL mode - automagically makes it non-blocking? I dunno. - -2002-04-01 Jeffrey Stedfast - - * camel-folder-summary.c (message_info_new): Updated the - construction of the references to match JWZ's updated algorithm - initialization (ie, append any In-Reply-To reference onto any - References header and never take more than a single message-id - from the In-Reply-To header since anything after the first will - probably just be email addresses). Fixes bug #1336. - -2002-04-03 Not Zed - - * providers/local/camel-local-folder.c - (camel_local_folder_construct): Turn indexing back on, fingers - crossed ... - - * camel-block-file.c (sync_nolock): #!@$@$#@~#$ - DF@#$!Q@$#!@$#!#%. Well it helps if we're iterating a list to - iterate the node pointer ... - - * camel-text-index.c (text_index_sync): Sync the key tables - explcitly. - (text_index_sync): Debug out frag info. - (camel_text_index_dump): Added a (rather large, but optional) raw - dumping mode for debugging purposes. - - * camel-partition-table.c (camel_key_table_finalise): Sync root - block when done. - (camel_key_table_sync): New function, sync key table (root) explicitly. - (camel_partition_table_sync): Method to explicitly sync the - partition table. - -2002-04-02 Not Zed - - * camel-block-file.c (camel_block_file_free_block): Mark root - block dirty when we change it (this function isn't used yet - anyway). - - * camel-text-index.c (text_index_add_name_to_word): Touch the root - block when we modify the counts. Also, abort processing on any - errors. - (text_index_sync): Fix typo in comments. Sync the block file - inside the lock. - (text_index_compress_nosync): Lock the old index while we're - compressing. - (text_index_compress_nosync): Remove the bogus while() at the end - of the while() loops! Also plug a memleak - records weren't - freed. - (text_index_rename): Lock around rename op. - (text_index_add_name): More typos. - (text_index_sync): Touch root when changing it. - (text_index_add_name): " - (text_index_delete_name): " - (camel_text_index_new): Touch root if we change it. - (text_index_cursor_reset): Make sure we NULL pointers after we - free them (nothing uses this yet). - - * camel-partition-table.c (hash_key): Remove some debug - accidentally left in. - (camel_partition_table_add): When linking in the next block list, - set the right previous pointer. - (camel_key_table_add): Simplify the 'left' calculation (it was - already ok though). - (camel_key_table_next): Initialise returns before processing. - Broaden the lock slightly, and simplify validity calculations. - - * providers/imap/camel-imap-store.c (imap_keepalive): Put back in - the exception setup stuff i disabled for debugging. - - * providers/local/camel-local-folder.c - (camel_local_folder_construct): Temporarily disable indexing. - -2002-03-28 Not Zed - - * camel-partition-table.c (camel_key_table_lookup): Change range - checking assert to a warning. - - * providers/pop3/camel-pop3-folder.c (pop3_finalize): Make sure we - flush out all outstanding commands before finalising, stops being - finalised while outsanding requests are processed by the store - finalise. - (pop3_get_message): Instead of pre-fetching all messages, just - pre-fetch a maxiumum number at any one time, stops us running out - of cache fd's. - - * providers/nntp/camel-nntp-folder.c (nntp_folder_init/finalise): - Setup priv data + locks, & free. - - * providers/imap/camel-imap-folder.c (imap_rescan): Batch all - message_chagned events into a single folder_changed event - (otherwise updates can be >>> expensive, like >5 hours for 80K - messages changing!). Alternately it could use folder - freeze/unfreeze perhaps. - -2002-03-27 Not Zed - - * providers/imap/camel-imap-store.c (imap_keepalive): Pass an - exception to called code so it behaves properly since it uses the - passed exception to check returns. - -2002-04-01 Dan Winship - - * providers/imap/Makefile.am (libcamelimap_la_LDFLAGS): Use - -avoid-version instead of -version-info 0:0:0, and specify - -module. (From Max Horn ). - - * providers/local/Makefile.am (libcamellocal_la_LDFLAGS): Likewise. - - * providers/nntp/Makefile.am (libcamelnntp_la_LDFLAGS): Likewise. - - * providers/sendmail/Makefile.am (libcamelsendmail_la_LDFLAGS): - Likewise. - - * providers/smtp/Makefile.am (libcamelsmtp_la_LDFLAGS): Likewise. - - * providers/pop3/Makefile.am (libcamelpop3_la_LDFLAGS): Likewise. - Also remove $(KRB4_LDFLAGS) since KPOP is gone. - (INCLUDES): and $(KRB4_CFLAGS) - -2002-03-28 Jeffrey Stedfast - - * camel-filter-driver.c (do_copy): We now have to check to make - sure that p->message is non-NULL because we only load the message - when we have to. - (do_move): Same here. - -2002-03-28 Dan Winship - - * camel-transport.c (camel_transport_send_to): Change the message - arg to a CamelMimeMessage instead of a CamelMedium. Even the NNTP - provider returns CamelMimeMessages, and we're never going to - support anything more exotic than that. Also do a few more - g_return_if_fails here instead of in the providers. - (camel_transport_can_send): No longer needed. - (camel_transport_send): Remove this too. It wasn't being used any - more, and it doesn't behave exactly the same in sendmail and smtp. - - * providers/smtp/camel-smtp-transport.c (smtp_send, - smtp_can_send): Gone. - (smtp_send_to): Update for arg change. - (smtp_data): Make this take a CamelMimeMessage too. - - * providers/sendmail/camel-sendmail-transport.c (sendmail_send, - sendmail_can_send): Gone. - (sendmail_send_to): Update for arg change, and merge in the part - that used to be shared with sendmail_send. - -2002-03-27 Jeffrey Stedfast - - * camel-filter-driver.c (camel_filter_driver_filter_folder): - Construct the source_url the right way. The previous way was - generating urls like pop://fejj@ximian.com;keep_on_server/inbox - which is wrong. - -2002-03-26 Not Zed - - * camel-text-index.c (text_index_normalise): Changed to use just - g_utf8_strdown instead of utf8_normalise, to match the indexing - code. utf8_normalise is just far too expensive (saves approx 25% - total processing). - -2002-03-25 Not Zed - - * camel-text-index.c (text_index_add_name): When we add a new - name, up all of the cache limits, because we're probably going to - be adding more. - (text_index_sync): Drop the cache limits back down again, we dont - need them when looking words up. - - ** MERGE camel_index branch. - - * camel-text-index.[ch]: Added files i forgot to add (eep nearly - lost all this work!) - - * camel-block-file.c (sync_nolock): Fix an infinite loop in syncing. - -2002-03-21 Jeffrey Stedfast - - * camel-folder-summary.c (camel_message_info_new_from_header): Use - the date in the received header for the received_date. - -2002-03-22 Not Zed - - * providers/local/camel-local-folder.c - (camel_local_folder_construct): Use the right option to remove the - index file and reset the index file on creation. - (camel_local_folder_construct): Remove any existing '.ibex' files - - these are the old format index files. - - * camel-block-file.c (camel_block_file_rename): Lock io lock while - renaming. - (camel_key_file_rename): Lock around rename. - (block_file_validate_root): Implement sync flag checking. - (camel_block_file_touch_block): Turn off the sync flag if we're - touching any non-root block and write it to disk. Shoudl this - fsync()? - (sync_nolock): sync the root block only if we need to. - - * providers/local/camel-local-store.c (rename_folder): Re-enable - index rename code. Not sure how race-free it is though. - (delete_folder): Delete the index file properly. - - * camel-partition-table.c (camel_key_table_lookup): Initialise - output values to 0 before doing anything. - (camel_key_table_add): Do some range-checking on values. - - * camel-text-index.c (text_index_compress): Changed to call sync here. - (text_index_compress_nolock): and not here - stops a recursive - sync call when sync performs a compress also. - (text_index_compress_nolock): Change to _nosync, since the locking - is irrelevent (recursive lock). Fixed callers. - (text_index_add_name_to_word): If we get a failure with key table - ops, fail immediately. - (text_index_compress_nosync): Likewise. - (text_index_write_name): If the nameid is 0, do nothing. - (text_index_add_name): If we can't get a keyid, dont add it to the - partition table. - (camel_text_index_remove): Function to delete an index file. - (text_index_compress_nosync): Clean up temp files when done. - - * camel-folder-search.c (match_messages_index): New function, - split from body_contains, matches a regex against all words in an - index. - (match_message_index): Similar to above but matches against an - individual message. - (search_body_contains): Changed to use above functions for - matching - substring matches should now work on indexed data. - -2002-03-21 Not Zed - - * camel-index.c (camel_index_words/names): New virtual - methods/stubs to get a cursor of all words and names. - - * camel-text-index.c (text_index_compress_nolock): Split from - text_index_compress, so we can call the compressor while locked - also, removed lock calls. - (text_index_compress): Changed to stub which calls - text_index_compress_nolock. - (camel_text_index_key_cursor_new): New object to iterate through - a key table. - (text_index_words, text_index_names): Implement virtual functions - for iterating through all words or names. - - * camel-block-file.c: Turn off some debug. - -2002-03-20 Not Zed - - ** New body index implementation. - - * camel-index*: Code for camel index, a new class to replace ibex. - - * camel-block-file.[ch]: block-based and link based - filesystem-in-a-file classes. - - * camel-partition-table.[ch]: An implementation of a partition - table (automatically extending on-disk hash-table using ideal - hash), and a key-table, a key<>name mapping table. Used by - camelindex. - - * providers/local/*, camel-folder-summary.[ch]: Changed to use - camel-index interface rather than ibex. - -2002-03-05 Not Zed - - * providers/local/camel-maildir-summary.c (maildir_summary_check): - Do progress reporting of operations. - (maildir_summary_sync): Same here. - -2002-03-04 Not Zed - - * providers/local/camel-spoold-store.c (scan_dir): Kill a warning - with a cast. - - * providers/local/camel-*.c: Changed for ibex->camelindex. - - * camel-folder-search.c (camel_folder_search_set_summary): Init - summary_hash to point to 'static' uid strings. - (search_body_contains): Use the static uid memory to return - results rather than the values from the index library. - - * camel-folder-search.[ch]: Changed to use camelindex object. - - * camel-folder-summary.c (summary_build_content_info_message): - Use a stream to index content, also filter html mail first. - (camel_folder_summary_info_new_from_message): Use a stream - filtered to index content. - (main): Removed the test main code. Added headers for open call - (ibex must've had them before). - - * camel-folder-summary.[ch]: Changed from ibex to CamelIndex. - - * camel-mime-filter-index.c (camel_mime_filter_index_finalize): - Unref index. - - * camel-mime-filter-index.[ch]: Changed from ibex to CamelIndex. - -2002-03-19 Jeffrey Stedfast - - * camel-mime-utils.c (header_encode_param): Fix this to work - right. We need to convert the input buffer to the charset we claim - in the encoded param (duh). - -2002-03-18 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c - (connect_to_server_wrapper): Updated to use the same logic as the - POP code. - - * providers/pop3/camel-pop3-store.c (connect_to_server): No longer - takes a stls_supported argument since we no longer need it with - the new logic. - (connect_to_server_wrapper): New logic: First try connecting to - the SSL port (995 by default), if that fails with - SERVICE_UNAVAILABLE, then we attempt to connect (to port 110 by - default) and try to use STARTTLS. - -2002-03-15 Jeffrey Stedfast - - * camel-folder.h: - - * camel-private.h: Don't allow any empty structs. If - !ENABLE_THREADS, provide a gpointer dummy member. Fixes bug #6382. - -2002-03-13 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_auth): Added a - work-around for SMTP servers that can't read the RFCs and thus - implement SASL incorrectly. Oh well, that's life in the world of - mail clients I guess. - -2002-03-12 Jeffrey Stedfast - - * camel-digest-store.c (camel_digest_store_new): Now takes a url - argument. - - * camel-digest-folder.c (digest_add_multipart): Fixed some memory - corruption and also modified to use CAMEL_IS_MIME_MESSAGE() rather - than comparing content-type strings. - (digest_get_message): Fixed a logic blooper. - - * camel-folder-summary.c (camel_message_info_new_from_header): Set - the date fields of the CamelMessageInfo as well. This may even fix - some filter-related bugs where the user was trying to compare - dates. - -2002-03-11 Jeffrey Stedfast - - * camel-digest-store.c: A pretty empty store implementation to be - the parent store of a CamelDigestFolder. - - * camel-digest-folder.c: Updated to reference it's parent store. - -2002-03-11 Jeffrey Stedfast - - * camel-digest-folder.c (camel_digest_folder_new): Allow any leaf - part to be a message/rfc822 part. - (digest_get_uids): Recurse the mime structure and add all - message/rfc822 parts and use a uid scheme similar to IMAP's mime - part naming convention. - (digest_get_message): Decode the uid to get the correct mime part. - -2002-03-11 Ettore Perazzoli - - * camel-mime-utils.c: Change the order of the mailing list magic - patterns so that the more mailing-list specific ones are on the - top. - -2002-03-11 Jeffrey Stedfast - - These fixes should fix bug #21737. - - * providers/smtp/camel-smtp-transport.c - (connect_to_server_wrapper): Same as with the POP code. - - * providers/pop3/camel-pop3-store.c (connect_to_server_wrapper): - Slight restructuring of the if-statements for the USE_SSL_ALWAYS - case so that we can't possibly return TRUE unless we really did - connect successfully. - -2002-03-10 Dan Winship - - Rename the OpenSSL implementation of things to match the NSS - implementation so that callers don't need to care which one is - being used. - - * camel-tcp-stream-openssl.c: Implement CamelTcpStreamSSL, not - CamelTcpStreamOpenSSL. Rename methods as well. Replace the - camel-tcp-stream-openssl.h include with camel-tcp-stream-ssl.h. - - * camel-tcp-stream-openssl.h: Gone. - - * camel-tcp-stream-ssl.c: Add a note explaining that this - implementation is only used for NSS, and that OpenSSL's - implementation is in another file. (Should probably do some CVS - renaming magic at some point.) - - * camel-http-stream.c (http_connect): Remove OpenSSL refs; the - previously-NSS-specific code works for both now. - - * camel-remote-store.c: Likewise. - - * providers/smtp/camel-smtp-transport.c: Likewise. - - * providers/pop3/camel-pop3-store.c: Likewise. - - * Makefile.am (libcamelinclude_HEADERS): Remove - camel-tcp-stream-openssl.h - -2002-03-10 Dan Winship - - * camel-tcp-stream.c (camel_tcp_stream_get_socket): Remove this: - it couldn't be generically used, because different subclasses - returned entirely different types of data. - (camel_tcp_stream_get_local_address, - camel_tcp_stream_get_remote_address): Add these to replace what - get_socket was being used for. - (camel_tcp_address_new, camel_tcp_address_free): Utility functions - for get_{local,remote}_address. - - * providers/smtp/camel-smtp-transport.c: Change localaddr to a - CamelTcpAddress *. - (connect_to_server): Call camel_tcp_stream_get_local_address to - get the local IP address. - (smtp_disconnect): free localaddr. - (smtp_helo): Update for localaddr change. - - * camel-tcp-stream-raw.c (stream_get_socket): Remove - (stream_get_local_address, stream_get_remote_address): Implement. - - * camel-tcp-stream-ssl.c (stream_get_socket): Remove - (stream_get_local_address, stream_get_remote_address): Implement. - - * camel-tcp-stream-openssl.c (stream_get_socket): Remove - (stream_get_local_address, stream_get_remote_address): Implement. - -2002-03-08 Jeffrey Stedfast - - * providers/pop3/camel-pop3-provider.c - (camel_provider_module_init): Don't call - camel_remote_store_get_authtypes since we no longer subclass - camel-remote-store. - - * providers/pop3/camel-pop3-engine.c: Added STARTTLS to the - capabilities to look for. - (camel_pop3_engine_reget_capabilities): New function to re-get - capabilities. - - * providers/pop3/camel-pop3-store.c: Updated to not subclass - CamelRemoteStore. - (connect_to_server): Rewritten to not depend on CamelRemoteStore's - connect implementation. Also added support for STLS (aka - STARTTLS). - -2002-03-07 Jeffrey Stedfast - - * camel-pgp-mime.c (camel_pgp_mime_part_sign): Add support for - hash type RIPEMD160. - - * camel-cipher-context.h: Add RIPEMD160 hash type. - - * camel-pgp-context.c (pgp_sign): Updated to consider hash - function for pgp5 and pgp6. - (pgp_clearsign): Same. - - * camel-tcp-stream-openssl.c (stream_read): Add a timeout on the - select. - (stream_write): Same. - -2002-03-06 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (connect_to_server): Fix - to work with OpenSSL. - - * camel-tcp-stream-openssl.c: compile fixes. - (camel_tcp_stream_openssl_enable_ssl): Check to make sure that the - sockfd != -1, it's not enough to check that it is non-zero. Also - set the sockfd to -1 on fail (open_ssl_connection will close the - sockfd on fail). - -2002-03-06 Dan Winship - - * providers/smtp/camel-smtp-transport.c (smtp_construct): Make - this compile. - -2002-03-05 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (save_ssl_cert): Removed. Glory glory - hallelujah! - (ssl_bad_cert): No longer calls ssl_save_cert or - ssl_cert_is_saved. - -2002-03-05 Jeffrey Stedfast - - * camel-tcp-stream-openssl.c (camel_tcp_stream_openssl_new_raw): - Start the ssl stream off in non-ssl mode (useful for STARTTLS). - (camel_tcp_stream_openssl_enable_ssl): New function to toggle an - ssl stream into ssl mode. - (open_ssl_connection): Close the sockfd on fail so our caller - doesn't have to - this also allows us to save the original errno. - (stream_connect): If we want ssl mode, do our ssl stuff. - (camel_tcp_stream_openssl_class_init): Init some SSL stuff here - instead of in open_ssl_connection since these only ever need to be - called once. - (stream_read): Only use SSL_read if we are in ssl mode. - (stream_write): Only use SSL_write if we are in ssl mode. - - * providers/smtp/camel-smtp-transport.c (smtp_helo): Check for the - STARTTLS extension. - (connect_to_server): Try to use STARTTLS whenever possible rather - than the old way of doing things. - (connect_to_server_wrapper): Wrapper around connect_to_server() to - first try STARTTLS and then attempt normal SSL mode if we can't - connect via STARTTLS. - - * camel-tcp-stream-ssl.c (camel_tcp_stream_ssl_enable_ssl): New - function to toggle an ssl stream into ssl mode. - (camel_tcp_stream_ssl_new_raw): Start the ssl stream off in - non-ssl mode (useful for STARTTLS). - (stream_connect): Only connect in SSL mode if required. - -2002-03-01 Jeffrey Stedfast - - * camel-vtrash-folder.h: - * camel-vee-store.h: - * camel-vee-folder.h: - * camel-stream-null.h: - * camel-stream-filter.h: - * camel-store-summary.h: - * camel-news-address.h: - * camel-mime-utils.h: - * camel-mime-parser.h: - * camel-mime-filter-save.h: - * camel-mime-filter-linewrap.h: - * camel-mime-filter-index.h: - * camel-mime-filter-html.h: - * camel-mime-filter.h: - * camel-mime-filter-from.h: - * camel-mime-filter-crlf.h: - * camel-mime-filter-chomp.h: - * camel-mime-filter-charset.h: - * camel-mime-filter-bestenc.h: - * camel-mime-filter-basic.h: - * camel-internet-address.h: - * camel-folder-thread.h: - * camel-folder-summary.h: - * camel-folder-search.h: - * camel-filter-driver.h: - * camel-charset-map.h: - * camel-address.h: Add c++ armoring. - - * camel-object.h: s/class/klass - -2002-03-01 Jeffrey Stedfast - - * camel-mime-part-utils.c - (camel_mime_part_construct_content_from_parser): Reverted my - pgp/mime fixes here too. - - * camel-mime-part.c (write_to_stream): Removed my pgp/mime raw - stream hack, this is causing problems such as some messages to not - displaying, view->source not working at all, etc. - -2002-02-28 Jeffrey Stedfast - - * camel-mime-parser.c: Changed offset variables from int's to - off_t's since the system may support large files. - - * camel-mime-part-utils.c - (camel_mime_part_construct_content_from_parser): Rearrange the - save filter stuff so that we save raw streams for all mime - parts. If the mime part turns out to be a multupart, then don't - bother saving the raw stream, we only need to save the raw stream - for leaf parts. - -2002-02-27 Jeffrey Stedfast - - * camel-folder-summary.h: Don't #include camel-mime-filter-save.h, - we don't use it. - - * camel-file-utils.c: Fixed a few 'might be used uninitialized' - warnings which were real problems. - - * camel-mime-part-utils.c - (camel_mime_part_construct_content_from_parser): Save the raw mime - stream for any/all signed parts. - - * camel-mime-part.c (camel_mime_part_init): Initialize our raw - stream to NULL. - (camel_mime_part_finalize): Unref our raw stream, if we have one. - (write_to_stream): If we have a raw stream, write that out instead - of re-encoding. - - * camel-mime-filter-save.[c,h]: Rewritten to save to a stream - rather than a file. - -2002-02-28 Not Zed - - * camel-mime-utils.c (header_fold): Use the FOLD_SIZE as a - recommended folding size, but add a new FOLD_MAX_SIZE (=998, the - smtp max line size) as the hard limit for any output. - -2002-02-27 Jeffrey Stedfast - - * camel-mime-filter-chomp.c (camel_mime_filter_chomp_new): New - stream filter that chomps excess trailing whitespace from the end - of the stream. This is needed to update the PGP/MIME code to - comply with rfc3156. - - * camel-pgp-mime.c (camel_pgp_mime_part_verify): Don't attach a - from filter, if it ain't from-filtered already, then we'll just be - breaking stuff. To become rfc3156 compliant, add a chomp filter - here. - (camel_pgp_mime_part_sign): Add a chomp filter here too. - -2002-02-27 Not Zed - - * camel-mime-part.c (init_header_name_table): Changed header - formatted table to contain a pointer to an output function, and - added in-reply-to and references headers. - (write_references): New function to write out references header, - folded properly. It only approximates based on the last >, but it - should be adequate and will also handle invalid headers. - (write_fold): Function to write out headers folded. Since this is - the default it isn't required. - (write_raw): Write out an already formatted header, e.g. most of - the rest. - (write_to_stream): Lookup header output function, if we have one, - use that, otherwise fold header using basic (dumb) function. - - This is all for #14779. A better fix is probably do have the - headers always stored formatted, but that can wait. - -2002-02-25 Jeffrey Stedfast - - * camel-digest-folder.c (camel_digest_folder_new): Allow all - multiparts that contain message/rfc822 attachments. - (digest_get_uids): Only assign uids to message parts. - -2002-02-22 Jeffrey Stedfast - - * camel-mime-part.c (camel_mime_part_set_filename): Set the 'name' - parameter on the Content-Type too. Fixes bug #20779. - -2002-02-14 Jeffrey Stedfast - - * camel-pgp-context.c (pgp_sign): Pass --always-trust to gpg - (requested by users). - (pgp_clearsign): Same. - (pgp_encrypt): Here too. - -2002-02-12 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_helo): Since the - AUTH token sometimes uses '=' instead of whitespace, don't use - smtp_token_next here. - -2002-02-09 Not Zed - - * providers/pop3/camel-pop3-engine.c (get_capabilities): Duh, when - we grab the apop stamp it needs to include the <> as well, I even - read the rfc, silly me. - - * providers/pop3/camel-pop3-store.c (pop3_try_authenticate): Doh, - when iterating the authtype list, it helps to goto the next node. - Found with help from miles. - -2002-02-08 Not Zed - - * providers/local/camel-spool-summary.c - (camel_spool_summary_build_from): The day number has to be 2 chars - wide, space filled to work properly with pine, etc. - - * providers/local/camel-spoold-store.[ch]: new type of provider - 'spool directory', which lets you view external mbox dirs without - adding any extra cruft. Perhaps it should use . files to store - summaries? Still a bit experimental, there's a warning when you - select it in the account editor. Finished off most of #1185. - Can't rename or move folders. - - * camel-mime-utils.c (header_decode_date): If the date is - 100->1900 then we actually want to use it as the year in the tm - struct, not year+100. e.g. year 102 -> 2002, not 2102. - -2002-02-07 Not Zed - - * providers/local/camel-spool-store.c (get_folder): Pass path into - spool_folder_new. - - * providers/local/camel-spool-folder.c (camel_spool_folder_new): - (camel_spool_folder_construct): Take the full path to the folder - and use that as the file path, independent of the full_name we - use. - -2002-02-07 Not Zed - - * providers/local/camel-local-provider.c: Added new type, spoold - provider, spoold: for local directories. - - * providers/imap/camel-imap-store.c (get_one_folder_offline): - Create offline uri's in a compatible manner to online ones. - -2002-02-07 Dan Winship - - * camel-sasl-ntlm.c: Implementation of NTLM (aka "Secure Password - Authentication") auth, taken from soup. - - * Makefile.am (libcamel_la_SOURCES, libcamel_la_HEADERS): Add - camel-sasl-ntlm. - - * camel-sasl.c: Add refs to camel-sasl-ntlm. - - * providers/imap/camel-imap-store.c (try_auth): Use - imap_next_word() to skip over the "+ " of the continuation rather - than just "resp + 2" since Exchange (incorrectly) returns "+" - instead of "+ " for an empty continuation response. - -2002-02-06 Jeffrey Stedfast - - * camel-folder-summary.h: Remove the CAMEL_MESSAGE_NEEDS_REPLY - flag, we no longer will be using this. - -2002-02-04 Jeffrey Stedfast - - * camel-http-stream.c (stream_read): Use camel_mime_parser_read to - read internal parser data. - (camel_http_stream_get_content_type): Implemented. - (http_method_invoke): Use HTTP/1.0 instead of 1.1 - - * camel-mime-utils.c (header_decode_int): Made public. - - * camel-http-stream.[c,h]: Added. New stream for HTTP requests - (currently supported are GET and HEAD). - - * camel-tcp-stream-ssl.c (stream_connect): Call set_errno - appropriately. - -2002-01-31 Not Zed - - * camel-mime-utils.c (header_decode_domain): Oops, this was - converting foo@[blah] to foo@[ blah ], fixed. - -2002-01-30 Jeffrey Stedfast - - * providers/pop3/camel-pop3-provider.c: Use "pop" instead of - "pop3" so current configurations continue to work. - -2002-01-30 Not Zed - - * camel-sasl-login.c: Changed name from "NT Login" to simply - "Login". - - * providers/pop3/*: Entirely new pop implmentation, supporting - pipelining. - -2002-01-29 Not Zed - - * camel-data-cache.c (free_busy): We dont want to unref the - stream, instead, stop listening to the finalised events, and free - the path only. - -2002-01-25 Not Zed - - * camel-data-cache.c (stream_finalised): Remove the object from - the busy_stream hashtable, not the busy_path hashtable. - -2002-01-29 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_update_summary): Added - more kludge to an existing Exchange IMAP 5.5 kludge to work around - it returning multiple messages with the same UIDs. - -2002-01-28 Jeffrey Stedfast - - * camel-mime-message.c (process_header): Handle Resent headers - too. - - * camel-mime-message.h: Added Resent-* #defines. - - * camel-filter-driver.c (camel_filter_driver_remove_rule_by_name): - Use while (node->next) instead of while (node) - - * providers/smtp/camel-smtp-transport.c (smtp_decode_status_code): - New function to decode an enhanced status code. - (smtp_set_exception): Sets an exception based on the - Enhanced-Status-Code. - (esmtp_get_authtypes): Don't diplicate the key in the hash since - the key and value are the same. - (smtp_rcpt): Include the failed recipient in the error message to - be more helpful to the user. - - * camel-mime-utils.c (hex_decode): Make sure to allocate enough - for the NUL byte. - -2002-01-28 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_construct): - (connect_to_server): Use flags rather than a bunch of gboolean - variables. - (smtp_connect): Same. - (smtp_mail): Here too. Use the enhanced status codes if available. - (smtp_data): And again here. - (smtp_helo): Finally here. Also detect the ENHANCEDSTATUSCODES - extension. - (smtp_rcpt): Use the enhanced status codes if available. - (smtp_rset): Here too. - (smtp_quit): And finally here. - - * camel-transport.h: Removed gboolean supports_8bit since this is - pretty local to only SMTP for now. - -2002-01-24 Ettore Perazzoli - - * Makefile.am: Remove some old cruft. - -2002-01-24 Ettore Perazzoli - - * tests/folder/Makefile.am: s/MAILER_LIBS/EVOLUTION_MAIL_LIBS/. - * tests/message/Makefile.am: Likewise. - * tests/mime-filter/Makefile.am: Likewise. - * tests/misc/Makefile.am: Likewise. - * tests/smime/Makefile.am: Likewise. - * tests/stream/Makefile.am: Likewise. - -2002-01-24 Jeffrey Stedfast - - * camel-filter-driver.c (do_beep): Call the beep callback - function. - (camel_filter_driver_set_system_beep_func): New function to set - the beep callback. - -2002-01-22 Jeffrey Stedfast - - * camel-filter-driver.c (camel_filter_driver_remove_rule_by_name): - New function to remove a filter rule by name. - -2002-01-21 Jeffrey Stedfast - - * camel-filter-driver.c (do_beep): As a temporary solution, just - printf ("\a"); to make a beep :-) - - * providers/imap/camel-imap-command.c - (imap_command_strdup_vprintf): Encode the mailbox to UTF-7 here. - - * providers/imap/camel-imap-utils.c (imap_parse_list_response): - Decode the mailbox name as we parse the list response. - (imap_mailbox_decode): It's only an illegal mailbox name if it - didn't switch back to US-ASCII mode. - -2002-01-18 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c (imap_mailbox_decode): New - function to decode an IMAP mailbox name from modified UTF-7 - encoding to UTF-8. - (imap_mailbox_encode): New function to convert a mailbox name from - UTF-8 to IMAP's modified UTF-7 encoding. - -2002-01-17 Jeffrey Stedfast - - * camel-mime-filter-basic.c (filter): Stop uudecoding once the - CAMEL_UUDECODE_STATE_END state bit gets set. Set the - CAMEL_UUDECODE_STATE_BEGIN state bit once we find the begin line. - (reset): No longer have uu_begin or uulen state variables, these - are now stuffed into a single state variable. - - * camel-mime-utils.c (uudecode_step): No longer needs a uulen - argument and also keeps track of whether or not the end of the - encoded data has been found in 'state'. - (uuencode_step): Now stuffs uulen into state so that the uulen - argument is no longer needed. - (uuencode_close): Same. - -2002-01-16 Jeffrey Stedfast - - * camel-mime-filter-basic.c (filter): If we don't want to corrupt - the uuencoded data by overwriting it with base64 decoded data - afterward, we need to add a break statement! - - * camel-folder-summary.c (summary_build_content_info): Add code to - add a uu filter. - (camel_folder_summary_finalize): Unref the uuencode filter. - -2002-01-16 Jeffrey Stedfast - - * camel-mime-filter-basic.c (filter): Fixed slight logic error to - find the uuencode begin line. Fixes bug #18754. - -2002-01-15 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_send_to): Updated to - match the new send_to API. - (smtp_send): Get the from address and pass that along to - smtp_send_to(). - - * providers/sendmail/camel-sendmail-transport.c - (sendmail_send_to): Updated to match the new send_to API. - - * camel-transport.c (camel_transport_send_to): Now takes a from - argument too. - - * providers/imap/camel-imap-folder.c (imap_update_summary): Sort - the needheaders UID array and fixed to respect the - UID_SET_LIMIT. This should now finish the fixification of bug - #2529. There's still the possible issue that a command-line (The - only command-line I can think of that can still be too long is a - SEARCH command, but this can't possibly be fixed until we rewrite - the imap code to use Zucchi's ImapEngine idea). - -2002-01-14 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_expunge_uids_online): - Move the command-lock outside the loop. - -2002-01-14 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_expunge_uids_online): - Updated to use the new imap_uid_array_to_set() interface. - (imap_expunge_uids_resyncing): Same. - (do_copy): Here too. - (imap_update_summary): Added a FIXME comment to rewrite allowing - for a uid-set limitation. - (get_matching): Copy some of the logic over from - imap_uid_adday_to_set() to limit the length of the uid-set string. - (imap_sync_online): Added a comment to explain what is going on - with get_matching() since the behavior has changed slightly. - - * providers/imap/camel-imap-utils.c (imap_uid_array_to_set): - Modify the interface so that we can limit the size of the uid set - string returned. - -2002-01-14 Not Zed - - * providers/imap/camel-imap-search.c (imap_body_contains): - Rewritten to use a cache for body searches when online. Will need - some heavy testing but so far seems to be beneficial. - - * providers/imap/camel-imap-folder.c (imap_search_by_expression, - search_by_uids): dont initialise search object here. - (camel_imap_folder_new): Setup search object here with pointer to - cache dir. - -2001-12-01 Not Zed - - * camel-store-summary.[ch]: New class to store a store's folder - list in. Not yet completed. - -2002-01-11 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_update_summary): Kludge - around a bug in Exchange 5.5 that reports 2 messages with the same - UID. Fixes bug #17694. Replaces the fix from yesterday. - -2002-01-10 Jeffrey Stedfast - - * providers/local/camel-local-folder.c: If PATH_MAX doesn't exist, - use _POSIX_PATH_MAX. - - * providers/imap/camel-imap-folder.c (imap_update_summary): If mi - is NULL, don't bother updating it. Should fix bug #17694. - -2002-01-10 Jeffrey Stedfast - - * camel.h: #include camel-mime-filter-tohtml.h - - * providers/imap/camel-imap-folder.c (imap_update_summary): Kludge - around Microsoft Exchange 5.5 (bug #5348) by forgetting our - currently selected folder and re-SELECTing it so that the Exchange - server has a chance to realise it has new messages. - -2002-01-09 Jeffrey Stedfast - - * providers/local/camel-local-folder.c - (camel_local_folder_construct): If the mbox file is a symlink, - follow the symlink and get the One True Path so that we can - rewrite the mbox later without worrying about clobbering the - symlink. - -2002-01-08 Jeffrey Stedfast - - * camel-filter-search.c (TODO): There are a few sexp callbacks - that could be modified to use fms->info rather than using a - message object (like date and possibly mlist stuff) but *only* if - the date exists on the CamelMessageInfo object (since it may be - blank except for message flags). - (camel_filter_search_get_message): New internal convenience - function to make sure that the FilterMessageSearch has loaded the - message (and to load the message if this isn't the case). - (check_header): Call camel_filter_search_get_message(). - (header_exists): Same. - (header_regex): Here too. - (header_full_regex): And here. - (body_contains): Again here. - (body_regex): Here too. - (get_sent_date): Here also. - (get_received_date): Same. - (get_source): Here if we need to. - (camel_filter_search_match): Now takes a callback function/data - pair for on-demand message loading so that we don't necessarily - have to load the message if the defined filter rules don't require - it. - - * camel-filter-driver.c (camel_filter_driver_filter_folder): Don't - bother fetching the message here, let - camel_filter_driver_filter_message() worry about this. - (get_message_cb): New utility callback to fetch a message. - (camel_filter_driver_filter_message): Only fetch the message if we - absolutely need it to get a CamelMessageInfo. Instead of passing a - message object to camel_filter_search_match(), pass get_message_cb - and some user_data so that the matching code can fetch the message - on demand. - -2002-01-07 Jeffrey Stedfast - - * camel-folder.c (filter_filter): Flush the only-once actions. - - * camel-filter-driver.c (camel_filter_driver_filter_message): - Don't increment a filtered_count here any longer. - (camel_filter_driver_reset_filtered_count): Removed. - (camel_filter_driver_get_filtered_count): Removed. - (do_beep): New action. - (play_sound): New action to play a sound - (do_only_once): Another new action. - (camel_filter_driver_finalise): Free the only_once hash if the - driver has not been "flushed". - (camel_filter_driver_flush): Flush all of the only-once actions. - - * camel-charset-map.c: Moved windows-1251 to the end of the list - since it contains the euro and we'd prefer to use iso-8859-15 when - the euro is requested than a windows charset if possible. - - * camel-charset-map-private.h: Regenerated. - -2001-12-12 Jeffrey Stedfast - - * camel-folder-summary.c (content_info_load): Don't try setting a - content-type parameter if either the name or value is NULL. - - * camel-mime-utils.c (header_set_param): NULL-protection. - -2002-01-02 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (ssl_bad_cert): Do more like what mutt - does so hopefully this'll fix bug #16363 and #16300. - -2001-12-21 Jeffrey Stedfast - - * broken-date-parser.c (parse_broken_date): Completely - rewritten. It is now a load faster and a heck of a lot more - accurate, also now returns a time_t and sets the saveoffset - variable rather than returning a new char* buffer for the normal - camel date parser to re-parse. This saves a fair number of cpu - cycles :-) - - * camel-mime-utils.c (header_decode_date): Cleanup the broken date - parsing code. - -2001-12-20 Jeffrey Stedfast - - * camel-address.h: Change the prototype for camel_address_get_type - to return a CamelType (since internally this is what it returns - and also in case we decide to write a replacement for the current - CamelObject it'd be easier to drop in). - - * camel-internet-address.h: Same but for - camel_internet_address_get_type() - - * providers/smtp/camel-smtp-transport.c (smtp_send_to): Updated to - use a CamelAddress of recipients. - (smtp_send): Since smtp_send_to now takes a CamelAddress - recipients argument, our lives have been simplified and we can now - just concat To/Cc/Bcc into a recipients addr and send away. - - * providers/sendmail/camel-sendmail-transport.c - (sendmail_send_to): Updated to use a CamelAddress of recipients. - - * camel-transport.c (camel_transport_send_to): Now takes a - CamelAddress argument for the recipient list rather than a GList. - -2001-12-19 Jeffrey Stedfast - - * providers/smtp/Makefile.am: Remove the providerdir variable. - - * providers/sendmail/Makefile.am: Same. - -2001-12-17 Jeffrey Stedfast - - * camel-charset-map.c (camel_charset_iso_to_windows): New function - to map ISO charsets to the Windows charsets. - - * camel-mime-part-utils.c (broken_windows_charset): Detect Windows - charsets. - (simple_data_wrapper_construct_from_parser): Simplify a tad and - also check for iso-8859-* charsets that are really Windows - charsets. Fixes bug #12631. - -2001-12-17 Dan Winship - - * Makefile.am (INCLUDES): define CAMEL_PROVIDERDIR to be the - configure.in-defined camel_providerdir. - - * providers/Makefile.am: Remove some outdated comments - - * providers/imap/Makefile.am (camel_provider_LTLIBRARIES, - camel_provider_DATA): renamed from provider_LTLIBRARIES, - provider_DATA. - - * providers/local/Makefile.am: Likewise - - * providers/nntp/Makefile.am: Likewise - - * providers/pop3/Makefile.am: Likewise - - * providers/sendmail/Makefile.am: Likewise - - * providers/smtp/Makefile.am: Likewise - -2001-12-16 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (get_content): Reverted my - previous changes here since it doesn't actually work afterall. - - * providers/imap/camel-imap-wrapper.c (imap_wrapper_hydrate): - Update to do uudecoding when appropriate. - -2001-12-16 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (get_content): Try to use the - original boundary so luis will stop bugging me about "data - corruption". Also preserve other params in the multipart - content-type by dumping it to a string and setting it on the mime - part. - -2001-12-14 Jeffrey Stedfast - - * camel-filter-driver.c - (camel_filter_driver_reset_filtered_count): Reset the - filtered_count to zero. - (camel_filter_driver_get_filtered_count): Return the private - filtered_count value. - (camel_filter_driver_filter_message): Increment the - filtered_count. - (camel_filter_driver_set_shell_exec_func): New function to set the - shell-exec func. - (shell_exec): New ESExp filter action callback. - -2001-12-14 Jeffrey Stedfast - - * camel-pgp-mime.c (camel_pgp_mime_part_verify): Removed - x-inline-pgp-hack kludge because it doesn't work. - (camel_pgp_mime_part_decrypt): Same. - -2001-12-13 Chris Toshok - - * camel-data-cache.c: include stdlib.h (for alloca on freebsd) and - only include alloca.h if HAVE_ALLOCA_H is defined. - -2001-12-11 Zbigniew Chyla - - Fixes #17085 - - * camel-charset-map.c: Added #include . - - * camel-charset-map-private.h: - Recreated (following instructions from camel-charset-map.c) - -2001-12-11 Jeffrey Stedfast - - * camel-object.c (camel_type_register): Keep a name-to-type hash - so that we can make sure that the type has not yet been registered - (prevents a race condition such as the one in bug #16559). - - * camel-service.c (camel_service_connect): Make sure that the - connect_op is non-NULL before unregistering/unreffing it. - -2001-12-04 Jeffrey Stedfast - - * camel-mime-utils.c (header_content_type_simple): Protect against - either of the types being NULL. - -2001-12-05 Jeffrey Stedfast - - * camel-mime-filter-basic.c (filter): If complete() allocates - len+2 bytes for the out buffer, so should this. See bug #16371 for - an example case. - -2001-12-05 Jeffrey Stedfast - - * camel-sasl-digest-md5.c: iconv() returns a size_t, not an int. - - * camel-pgp-context.c: The return value of iconv() is a size_t, - not an int. - - * camel-mime-part-utils.c (convert_buffer): Always use size_t args - for iconv(). - - * camel-mime-filter-charset.c (complete): Always use size_t args - for iconv(). - (filter): Same. - - * camel-mime-utils.c (header_address_fold): Make headerlen a - size_t instead of an int. - (header_fold): Same. - (base64_encode_close): We should be returning a size_t and inlen - should also be a size_t. - (base64_encode_step): Same here. - (base64_decode_step): Here too. - (base64_encode_simple): And here... - (base64_decode_simple): Same. - (uuencode_close): We should also use size_t's here... - (uuencode_step): And here too. - (uudecode_step): And also here. - (quoted_encode_close): Same idea here. - (quoted_encode_step): Again here. - (quoted_decode_step): Here too. - (quoted_encode): Input length should be a size_t. - (rfc2047_decode_word): Same. - (g_string_append_len): Here too. - (append_8bit): " - (rfc2047_encode_word): " - (quote_word): " - (hex_decode): " - (rfc2184_decode): Use size_t's with iconv(). - (header_decode_param): Same. - -2001-12-09 Jon Trowbridge - - * camel-folder-summary.c: Add "NeedsReply" to the flag_names array - for CAMEL_MESSAGE_NEEDS_REPLY. - - * camel-folder-summary.h: Added CAMEL_MESSAGE_NEEDS_REPLY flag. - -2001-12-07 Dan Winship - - * camel-mime-message.c (camel_mime_message_set_date): Fix the - tm_gmtoff case (its sign is the opposite of "timezone"). Fixes - #14678 - -2001-11-29 Jeffrey Stedfast - - * camel-folder-search.c (search_body_contains): Don't use regex - matching. Fixes bug #16227. - - * camel-mime-message.c (best_encoding): Check the content-object's - mime type, not the mime part types. Should fix bug #15843. - -2001-11-27 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (get_content): Return NULL if - construct_from_stream fails. - (get_message): Same. - (get_message_simple): Here too. - (add_message_from_data): And here. - -2001-11-14 Not Zed - - * camel-vee-folder.c (folder_changed_remove_uid): Use the uid - rather than vuid for unmatched. Also add the uid to unmatched if - it wasn't in the unmatched_uids table at all. - (folder_changed_change): If checking for added, if the new ones - dont match, then try to add them to unmatched. Fixes #6893. - - * camel-folder-summary.c (camel_folder_summary_index): Change lock - order, always summary_lock before ref_lock. - (camel_folder_summary_array): " - (camel_folder_summary_uid): " - (camel_folder_summary_remove_uid): " Fixes a deadlock. - -2001-11-30 Not Zed - - * providers/nntp/camel-nntp-*.c: Completely new implementation of - NNTP. - - Doesn't support subscriptions yet (lists all folders), but should - be more reliable (faster?), and has an integrated cache. - - * camel-exception.c (camel_exception_new): Use e_memchunks for - exception blocks. - (camel_exception_free): Same. - - * camel-data-cache.[ch]: New object for managing on-disk caches of - anything that can be stored in a camel-stream. - - * camel-file-utils.c (camel_file_util_mkdir): New function, just a - nicer place to put this (than camel-store), should be removed from - camel-store. - (camel_file_util_safe_filename): New function to url-encode a - filename. - - * camel-mime-parser.c (drop_states): New func to drop the parser - state to initial state. - (folder_scan_init_with_fd): - (folder_scan_init_with_stream): Call above func to reset state if - the stream is changed on us so we can change streams to reuse a - parser object. - -2001-11-25 Not Zed - - * providers/nntp/camel-nntp-folder.c (nntp_folder_get_message): If - the uid doesn't have a ',' in it, fail to crash. - - * providers/nntp/camel-nntp-newsrc.c - (camel_nntp_newsrc_article_is_read): check group != NULL before - scanning. - (camel_nntp_newsrc_get_highest_article_read): " - (camel_nntp_newsrc_get_num_articles_read): " - (camel_nntp_newsrc_mark_range_read): " - - * providers/nntp/camel-nntp-store.c - (camel_nntp_store_get_overview_fmt): IF we dont have - nntp_list_follows, dont try and get a list response. - (nntp_store_get_folder_info): Set path part of folderinfo. - -2001-11-20 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (get_smtp_error_string): - Check to see that errno is non-zero before returning - g_strerror. If it's 0, then we have an unknown error. - -2001-11-26 Jeffrey Stedfast - - * camel-mime-filter-basic.c: For the uudecoding mode, garble up - the "begin " line before decoding. - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): Add a uudecoder if - the transfer encoding is x-uuencode. - - * camel-mime-part.c (write_to_stream): Handle x-uuencoded content - too. - -2001-11-19 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (stream_read): Added a check to see if - the operation has been cancelled. - (stream_write): Same. - -2001-11-19 Jeffrey Stedfast - - Updates for compliance with rfc2231 - - * camel-mime-utils.c (header_encode_param): - camel_mime_special_table[c] & IS_ESAFE should have been - !(camel_mime_special_table[c] & IS_ESAFE). Also added a few - comments for how to improve the code at some future date. - (header_decode_param): Now takes an argument rfc2184_part so our - caller can get this information as well. - (header_decode_param_list): Pass an rfc2184_part argument to - header_decode_param and also added a few comments on where to - improve on rfc2184/rfc2231 compliance. - (rfc2047_decode_word): Updated to respect the updated ABNF syntax - of rfc2047 encoded words, yay. - -2001-11-16 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c (imap_parse_body): Abort if - body == NULL. - - * camel-mime-filter-tohtml.c (camel_mime_filter_tohtml_new): New - mime filter to convert plain text to html. - -2001-11-16 Jeffrey Stedfast - - Since some mail clients like Outlook are broken, we need to set a - name parameter on pgp signed and encrypted parts. - - * camel-pgp-mime.c (camel_pgp_mime_part_encrypt): Set a name - parameter. - (camel_pgp_mime_part_sign): Same. - -2001-11-14 Jeffrey Stedfast - - * providers/imap/camel-imap-command.c - (camel_imap_command_response): If we get a BYE response, call - camel_service_disconnect() and set an exception. Also do the check - for "* BYE" first instead of passing it off imap_read_untagged() - since we'll just waste time in there mallocing left and right only - to arrive at the single response line "* BYE" again :-) - -2001-11-13 Not Zed - - * camel-filter-search.c (get_source): If we have no source string, - then use undefined, which should always evaluate to FALSE. Fix - for #15267. - -2001-11-12 Jeffrey Stedfast - - * camel-store.c (camel_store_get_folder): Added a - g_return_val_if_fail for folder_name != NULL. - -2001-11-08 Jeffrey Stedfast - - * camel-pgp-context.c (crypto_exec_with_passwd): If any of the - pipe()'s fail, clean up any pipes that may have succeeded. Also - close the password fds. - -2001-11-09 Not Zed - - * providers/imap/camel-imap-store.c (imap_auth_loop): If we get a - user cancel and that causes us to fail to authenticate, abort - rather than loop forever. Fix for #14951. - -2001-11-06 Jeffrey Stedfast - - * providers/imap/camel-imap-command.c - (camel_imap_command_continuation): Now takes a command-length - argument so we can 1) avoid duping the command string yet again, - yay. 2) we now don't have to worry about embedded nul-chars - screwing us over (we still need to avoid allowing them into the - string but at least now it won't mess us up). - - * providers/imap/camel-imap-folder.c (do_append): Instead of - appending a nul char to the end of the byte array and then passing - that off as if it were a string to - camel_imap_command_continuation, instead pass the byte-array - length since that function now takes a length argument. Yay. Also - encode any 8bit parts to avoid the possibility of sending embedded - nul chars to the imap server. - - * providers/imap/camel-imap-store.c (try_auth): Updated to pass a - command-length argument to camel_imap_command_continuation(). - -2001-11-07 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (save_ssl_cert): Oops, pass a mode - argument to the open() call. - - * camel-tcp-stream-openssl.c (save_ssl_cert): Oops, pass a mode - argument to the open() call. - -2001-11-07 Jeffrey Stedfast - - * camel-pgp-mime.c (camel_pgp_mime_part_decrypt): Add code to - kludge around any x-inline-pgp-hacks by prepending some content - headers to the decrypted data. - -2001-11-02 Jeffrey Stedfast - - * camel-data-wrapper.c (camel_data_wrapper_init): Initialize our - private mutex. - (camel_data_wrapper_finalize): Destroy our private mutex. - (write_to_stream): Lock around camel_stream_write_to_stream() so - that we don't get 2 threads trying to read from our stream at the - same time. - -2001-11-01 Not Zed - - * camel-vee-folder.c (folder_changed_change): Move all searching - operations outside of any locks except subfolder lock, same as - build_folder. Fix for #14294. - -2001-10-31 Not Zed - - * providers/local/camel-spool-folder.c (spool_get_message): Same - as below. - - * providers/local/camel-maildir-folder.c (maildir_get_message): - Same as below. - - * providers/local/camel-mbox-folder.c (mbox_get_message): Set - USER_CANCEL if failed due to EINTR. - - * camel-filter-driver.c (camel_filter_driver_filter_mbox): If - construct from parser fails due to user cancel, set USER_CANCEL on - exception. - - * camel-mime-part.c (construct_from_parser): Return error if the - parser had an io error. - - * camel-mime-message.c (construct_from_parser): Check error on - parser/return error. - - * camel-mime-parser.c (folder_scan_init): Init error number. - (camel_mime_parser_errno): New function, return errno of any io - failures. - (folder_read): Set errno if a failure occured. - (folder_seek): Same. - (folder_scan_init_with_fd): Setup errno depeding on ok/failure. - (folder_scan_init_with_stream): Same. - -2001-10-30 Not Zed - - * camel-operation.c (camel_operation_new): Dont setup cancel_fd. - (camel_operation_cancel_fd): If cancel_fd not created, set it up. - (camel_operation_cancel): Set cancel flag before sending message. - (cancel_thread): Same. - - * camel-filter-driver.c (camel_filter_driver_filter_mbox): Make - sure we unref the mimeparse when we're done (successfully). This - was leaking an fd every get-mail! :( - - * camel-lock-client.c (camel_lock_helper_init): Close all fd's - above 2. - - * providers/local/camel-mbox-folder.c (mbox_get_message): Remove - the X-Evolution header before anyone else gets to see this private - thing. Shoudl fix 11676 since we were inheriting flags from - X-Evolution headers we didn't want to. - - * camel-folder-search.c (match_message): If we can't retrieve the - message, ignore it, it can't match. - - * providers/imap/camel-imap-search.c - (camel_imap_search_class_init): Setup parent class pointer. - (imap_body_contains): If offline, just use the parent - body_contains method which will get the messages and search them - manually. - - * providers/imap/camel-imap-folder.c (imap_search_by_expression, - imap_search_by_uids): Remove offline check. - -2001-10-30 Dan Winship - - * camel-mime-part.c (free_headers): Fix this to match get_headers. - -2001-10-30 Not Zed - - * providers/local/camel-local-store.c (rename_folder): Dont try to - move ibex if we have none. - - * camel-tcp-stream-openssl.c (stream_write): Fixed compilation - errors. - -2001-10-29 Jeffrey Stedfast - - * camel-mime-utils.c (camel_mime_utils_init): Removed unused - variable. - -2001-10-30 Not Zed - - * camel-mime-utils.c (header_decode_mailbox): w(x) out some warnings. - - * providers/local/camel-local-summary.c - (camel_local_summary_load): Remove the warning about not loading - summary file - its a valid case for new folders. - -2001-10-29 Jeffrey Stedfast - - * camel-tcp-stream-openssl.c (my_SSL_write): Removed. - (stream_write): Keep looping (non-blocking case) if errno is - EAGAIN, EINTR or EWOULDBLOCK. For NONBLOCKing I/O, sync up with - CamelTcpStreamRaw. As with CamelTcpStreamRaw/SSL - make sure to - write out everything before returning. - (my_SSL_read): Removed. - (stream_read): Just call ssl_error_to_errno() and check the errno - values that we care about so we can keep the general look of all - this stream code the same. Also when checking the return value of - SSL_read, check for <0 instead of ==-1 since the man page for - SSL_read doesn't say it will return -1 on fail, it just says <0. - (stream_flush): Don't fsync() since syncing on a socket is a Bad - Thing (tm). - - * camel-tcp-stream-ssl.c (stream_write): Make sure we write out - everything just like in camel-tcp-stream-raw.c. - - * camel-stream-buffer.c (camel_stream_buffer_gets): If - camel_stream_read() returns -1, don't necessarily return -1 to our - caller since it's possible that we did actually "read" some data - (ie, we copied some pre-buffered data into the out buffer). - - * camel-stream-buffer.h: Removed CAMEL_STREAM_BUFFER_NEWLINE since - it never got used anywhere and it isn't supported anyway. - -2001-10-30 Not Zed - - * providers/imap/camel-imap-store.c - (parse_list_response_as_folder_info): If we get an empty name, - then mark that as NoSelect. Workaround fix for #13239. - -2001-10-29 Dan Winship - - * providers/imap/camel-imap-folder.c (get_message_simple, - imap_get_message): Set an X-Evolution-Source header on the - returned message so replies come from the right identity. - -2001-10-29 Not Zed - - * camel-vee-folder.c (folder_changed_change): If we're not going - to search on a changed uid, make sure we change out copy still. - Fixes #13916. - -2001-10-29 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (subscribe_folder): Don't emit - a folder_subscribed signal if we are in the process of renaming - folders. - (unsubscribe_folder): Same here but for the unsubscribe signal. - (rename_folder): Unsubscribe from the folder being renamed and any - subfolders it may have before actually renaming. Once the folder - has been renamed, re-subscribe to it and it's subfolders with the - new name. - - * camel-store.c (camel_folder_info_build): Sort the folder info's - before constructing the tree. - - * camel-mime-utils.c (header_decode_param): Minor fix - should - have been using a strNcmp when checking if it was an rfc2047 - encoded word. - - * camel-pgp-context.c (pgp_sign): Notify the user that PGP 2.6.x - is no longer supported and use camel_exception_set() instead of - setv() where appropriate. - (pgp_clearsign): Same. - (pgp_verify): And again here. - (pgp_encrypt): Here too. - (pgp_decrypt): And finally here. - -2001-10-29 Dan Winship - - * providers/imap/camel-imap-store.c (unsubscribe_folder): Don't - free the hash table key if the folder wasn't found in the hash - table. I'm not sure where the bug is/was that made it possible to - add a folder to the tree after creating it failed, but now if that - happens, it won't crash if you try to delete it again. (#11492) - - * camel-disco-store.c (camel_disco_store_status): if the service - is being connected and thinks it's online, but the session is - offline, then mark the service offline as well. Fixes 13683. - -2001-10-29 Not Zed - - * camel-mime-utils.c: Turn off w() -> warnings. - - * providers/imap/camel-imap-store.c (rename_folder): Also rename - the message cache. - (rename_folder): Fix subscribed folders table with rename(s). - - * providers/imap/camel-imap-folder.c (imap_rename): Implement, - rename the cache dir pointer. - - * providers/imap/camel-imap-message-cache.c - (camel_imap_message_cache_set_path): New method to set the path - used by a message cache. - - * camel-vee-store.c (build_info): Fix the 'is this a matching - subfolder or subfolder' logic to match camel-store - get_subfolders'. - - * camel-store.c (get_subfolders): Fix the 'is this a matching - folder or subfolder' logic. - -2001-10-28 Not Zed - - * providers/local/camel-local-store.c (rename_folder): Changed to - call ibex_move to rename it internally. - - * camel-store.c (camel_store_rename_folder): Use the right - variable, not info. - -2001-10-28 Jeffrey Stedfast - - * camel-stream-buffer.c (camel_stream_buffer_read_line): Make sure - we've actually read data before checking if p[-] is '\r' or not. - - * camel-tcp-stream-raw.c (stream_write): Same. - - * camel-stream-fs.c (stream_write): If errno isn't EAGAIN, just - exit with -1 and instead of using continue (which doesn't go to - the top of the do-while thus making our logic suck), just set w to - 0. Still seems to be a bug in select() if it's telling us the - socket is ready for data when it really isn't but oh well. - -2001-10-28 Not Zed - - * providers/local/camel-local-folder.c - (camel_local_folder_construct): Use path not protocol as the path - part of the uri of the folder_created event. - - * providers/local/camel-maildir-store.c (scan_dir): If FAST is - set, dont try and scan for unread counts. - - * providers/local/camel-local-store.c (create_folder): Implement, - just return the folderinfo of the folder matched, not all of it. - - * camel-store.c (camel_store_rename_folder): Rename the - camelfolders before emitting the folderchanged event (otherwise - vstore fails to pick up change. - -2001-10-27 Not Zed - - * camel-store.c (camel_store_init): Always use a default dir_sep - of '/'. - - * camel-store.h (struct _CamelStore): Added a dir_sep to the base - store so rename and whatnot can work, temporary fix for mixed dir - separator in folder name api's. - - * providers/imap/camel-imap-store.c (rename_folder): Finished - implementation. - (imap_connect_online): Also set the store's dir_sep here. - (imap_connect_offline): " - - * providers/local/camel-local-folder.c (local_rename): Implement - local rename of folder objects. - -2001-10-26 Not Zed - - * camel-vee-folder.c (camel_vee_folder_class_init): Hook into - rename function. - (vee_rename): Implement the veefolder rename function. - (camel_vee_folder_class_init): - (folder_changed_change): Kill a warning with a cast. - - * camel-vee-store.c (vee_rename_folder): Emit a folder_renamed - event properly, also call parent to do some rename stuff. - - * camel-store.h: Added a CamelRenameInfo for the rename event. - - * camel-folder.c (camel_folder_rename): New function to rename a - folder object. - (camel_folder_class_init): Added a renamed event. - (folder_rename): Default impl, set full_name, and set name - assuming the dir separator is '/'. - - * camel-store.c (camel_store_class_init): Added folder_renamed - event. - (camel_store_rename_folder): Rename an active folder object if we - have one, and update the folder table. - (rename_folder): Make a default implementation that handles - updating the folder tree. - -2001-10-26 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (delete_folder): Don't bother - checking ex since we can rely on the response being NULL on error. - (rename_folder): Implemented. - -2001-10-26 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_message): Check to - make sure that the dataset is non-NULL before using and/or - freeing. - - * camel-tcp-stream-raw.c (stream_write): Check for EWOULDBLOCK - too? - (stream_read): Same. - (stream_flush): Return 0 always, fsync() and tcp sockets don't - play nice :-) - - * providers/imap/camel-imap-message-cache.c - (camel_imap_message_cache_get): Lets try putting a - camel_stream_reset() here. Logic being that the stream may have - been read from since it was cached and thus our caller may try - reading from it and get no data from it since it is already at the - EOS. This may fix bug #12943. - -2001-10-25 Not Zed - - * camel-search-private.c (utf8_get): Remove the stupid warning - that should never have been there in the first place. - - * camel-sasl-digest-md5.c (digest_response): s/iconv/e_iconv/ - - * camel-pgp-context.c (pgp_verify): " - - * camel-mime-utils.c (rfc2047_decode_word, rfc2047_decode_word, - append_8bit, rfc2047_encode_word, rfc2184_decode, - header_decode_param): " - - * camel-mime-part-utils.c (convert_buffer, convert_buffer): " - - * camel-mime-filter-charset.c (reset, complete, filter): " - -2001-10-24 Not Zed - - * camel-mime-filter-basic.c (complete): For qp decoding, if the - data isn't really qp encoded, we could possible grow the buffer by - upto 2 bytes above the input size, fix allocations/assertions - appropraitely. - - * camel-vee-folder.c (folder_changed_change): If we're not - autoupdate, only search for new matches against changed uid's that - we dont already have. - -2001-10-24 Dan Winship - - * providers/imap/camel-imap-store.c (unsubscribe_folder): Don't - let fi->name be NULL. - -2001-10-24 Jeffrey Stedfast - - * camel-stream-fs.c (stream_read): Same as in the TcpStreamRaw code. - (stream_write): And again here... - - * camel-tcp-stream-raw.c (stream_read): Handle the EAGAIN error - case as well. - (stream_write): Same here, this might fix the SMTP truncation - thing? I hope? - -2001-10-23 Dan Winship - - * camel-mime-utils.c (mail_list_magic): Remove an extra * in one - of the regexps that glibc apparently doesn't mind but bsd does. - -2001-10-23 Not Zed - - * providers/local/camel-mbox-summary.c: made d(x) x recompile again. - -2001-10-22 Not Zed - - * providers/local/camel-spool-summary.c (summary_rebuild): No, use - Storing, as the other code does :p - (spool_summary_check): Check for consistency. - -2001-10-22 Jon Trowbridge - - * providers/local/camel-spool-summary.c (summary_rebuild): - s/summarising/summarizing/. - (spool_summary_check): s/summarise/summarize/. - -2001-10-22 Jeffrey Stedfast - - * camel-pgp-mime.c (camel_pgp_mime_part_verify): If we are - kludging around a inline-pgp signed part, do some charset - conversion to protect any 8bit text. - -2001-10-22 Not Zed - - * camel-filter-search.c, camel-folder-search.c (check_header): Use - search_type_mlist for mailing list searches. - - * camel.c (camel_init): call camel-mime-utils-init func. - - * camel-mime-utils.c: Changed mail mail_list_magic to include a - domain part, also pre-compile all the patterns. They are all - backward compatible except List-Id: which now uses the - mail-address-like part rather than the - plain-text part (which might've been blank anyway). - (camel_mime_utils_init): Initialisation function to setup any - static data required by camel-mime-utils at run-time. We now - setup the base64/charset class tables here, so it doesn't need to - be done statically. - (camel_mime_special_table, camel_mime_base64_rank): No longer - statically initialise these. - (main): Removed + the tests at the end of the file. - (header_raw_check_mailing_list): Dont compile regex's here, - already compiled in utils_init. Use the regex patterns to remove - leading <'s from addresses. Also, if there is a domain part - matched, add that after a '@' is added. - - * camel-search-private.c (camel_search_header_match): Match check - against all addresses in a multiple address match. Should fix - #13051. - (camel_search_header_match): Oops, missing i=0. - (camel_search_header_match): Added SEARCH_TYPE_MLIST for mlist - search types. It ignores the domain part if either (but not both) - of the values dont have it. - -2001-10-22 Dan Winship - - * camel-pgp-mime.c (camel_pgp_mime_part_verify): Add a hack: if - the multipart/signed part has a "x-inline-pgp-hack" parameter in - its Content-Type, don't pass the MIME headers as part of the data - to be verified. - -2001-10-22 Rodrigo Moya - - * Makefile.am: added $GNOME_INCLUDEDIR to INCLUDES, needed for latest - libgnome, which install headers in $(prefix)/gnome-1.0 - -2001-10-21 Jeffrey Stedfast - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): Only do the rawtext - checks if the part is a text part, otherwise don't bother wasting - cpu cycles. - - * camel-store.c (camel_folder_info_build): Updated comments to - make the code a bit more clear. - -2001-10-21 Not Zed - - * camel-store.c (CS_CLASS): Dont do the macro stuff - basically so - you can actually debug calls. - (camel_store_uri_cmp): New function to compare store objects. - - * camel-vee-folder.c (vee_folder_add_info): oops, dont free the - vuid, since its alloca'd now. - (folder_changed_change): Kill a compile warning. - -2001-10-20 Not Zed - - * camel-folder.c (move_messages_to): If no exception supplied, use - a local one. - (move_message_to): Set the seen flag also when we delete it. - -2001-10-19 Jeffrey Stedfast - - * camel-vtrash-folder.c (vtrash_move_messages_to): If the - destination folder is the vfolder source folder, then - set_message_flags on it. - -2001-10-19 Not Zed - - * camel-session.c (register_provider): When registering provider, - translate all strings. - - * camel-vee-folder.c (camel_vee_folder_remove_folder): Lock the - right lock for unmatched subfolder list stuff. If the sub folder - is deleted & part of unmatched, or the last ref to the sub folder - is gone from unmatched, blow it away completely from unmatched, - but only do it once. - (vee_folder_remove_folder): Added arg to kill unmatched - unconditionally. Also handle deleted folders, always remove - stuff. - (folder_changed_change): Lock subfolder lock for entirety of - operation, and also check to see if the subfolder is still there - before doing any fancy work (incase it got removed while we were - waiting to execute). - (folder_changed_change_uid): Use alloca for vuid, and not - sprintf(".lengths") - (vee_search_by_expression): Dont use sprintf for vuid. - (vee_search_by_uids): " - (vee_folder_add_info): " - (folder_changed_remove_uid): " - (folder_changed_change): " - (folder_changed_change_uid): Also check folder_unmatched for - changed uid's so we properly update/propagate unmatched changes. - (folder_changed_change): Ok, so dont hold the subfolder lock for - the whole duration of the changed event, although we probably - should, requires a recursive mutex. - (folder_changed_change): Change logic, we always add changed stuff - if it now matches, but dont remove it unless its auto-remove, only - propagate changes for it. - (vee_set_message_flags): Call parent method after doing our work. - (vee_set_message_user_flag): Same here. - -2001-10-18 Jeffrey Stedfast - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): If a charset isn't - specified or claims to be utf-8, check the validity of the text - and if it's invalid, set the rawtext bit to TRUE. If the charset - is x-unknown or some other x- charset, always set the rawtext bit - to TRUE. - -2001-10-18 Not Zed - - * camel-store.c (camel_store_unsubscribe_folder): If we are - unsubscribing from a folder we have loaded, set the folder - deleted, as with the delete_folder case. - - * providers/(imap|local|pop3|sendmail|smtp)/Makefile.am: Added - CAMEL_CFLAGS so we get the right iconv stuff, patch from Yanko - Kaneti - -2001-10-18 Jeffrey Stedfast - - * camel-pgp-context.c (crypto_exec_with_passwd): Make sure the - cancel_fd isn't -1. - -2001-10-18 Jeffrey Stedfast - - * providers/imap/camel-imap-message-cache.c (insert_finish): Flush - the stream here, not sure it really matters but it might - (hopefully) fix bug #12943. - - * camel-pgp-context.c (crypto_exec_with_passwd): Make - user-cancellable. - - * providers/local/camel-local-provider.c: String cleanup for bug - #6640. - - * providers/imap/camel-imap-folder.c (imap_sync_online): Fix my - Cyrus imapd workaround...instead of checking to see if info->flags - == FLAGGED, just check to see if it contains any IMAP flags. - -2001-10-17 Not Zed - - * providers/local/camel-maildir-folder.c - (camel_maildir_folder_new): Use '.' as the inbox name for filter - new messages test. - - * camel-store.c (camel_folder_info_clone): New function to clone a - folderinfo tree. - -2001-10-17 Jeffrey Stedfast - - * providers/local/camel-mh-folder.c (mh_append_message): Same as - maildir and mbox append-message. - - * providers/local/camel-maildir-folder.c (maildir_append_message): - Same as mbox append. - - * camel-exception.c (camel_exception_set): Make sure the new - description isn't the same as the old description pointer before - freeing the old one. - (camel_exception_setv): Don't free the old description until we - set the new one this way we can reuse the old description in the - new description. - - * providers/local/camel-mbox-folder.c (mbox_append_message): If - errno == EINTR, then we got a user-cancel so set the exception - appropriately so that we don't make the user shit his pants. - - * camel-filter-driver.c (do_copy): Add an optimization for when - destination folder is the same as the source folder. - -2001-10-17 Not Zed - - * providers/imap/camel-imap-store.c (get_folder_info_online): - (parse_list_response_as_folder_info): Patch from Danw, Use unread - count of -1 to mark unflagged messages. Make sure any folder we - dont lookup explicitly is marked as -1. Should fix #9947 and - friends. - - * providers/local/camel-mbox-summary.c (mbox_summary_sync): Only - touch the summary if the timestamp or size changed. - -2001-10-17 Jeffrey Stedfast - - * camel-filter-driver.c (camel_filter_driver_filter_message): Set - the DELETED flag on directly on the info if the source folder - doesn't have summary capability. - -2001-10-17 Not Zed - - * camel-tcp-stream-raw.c (stream_write): As below. - - * camel-stream-fs.c (stream_write): If not checking cancellation, - make sure we write out everything asked of us. - -2001-10-16 Jeffrey Stedfast - - * camel-pgp-context.c (pgp_verify): Rearange the order of the gpg - options slightly otherwise it might try to use "--no-tty" as the - filename to verify :-) - - * camel-object.[c,h]: If CAMEL_DEBUG is defined, print some useful - ref/unref info. - - * providers/imap/camel-imap-store.c (delete_folder): Fixed an - assignment warning. - - * camel-uid-cache.c (camel_uid_cache_new): Make sure that the - parent directory exists before trying to open the filename, if it - doesn't, create it. - -2001-10-16 Not Zed - - * camel-mime-utils.c (header_address_decode): If no content, dont - try and decode further and spit meaningless warnings. - -2001-10-16 Jeffrey Stedfast - - * camel-filter-driver.c (do_flag): Only perform the operation on - the folder if the folder has summary capability, else just poke - the info directly. Fixes the "Filters don't work" bug. - (do_score): Same. - (do_colour): And here too. - -2001-10-15 Jeffrey Stedfast - - * camel-stream-fs.c (stream_read): Save the errno before calling - fcntl so fcntl doesn't overwrite errno in case of a previous - error. - (stream_write): Same. - -2001-10-13 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_data): Replace the - Bcc headers in a single location and don't flush the data unless - the write was successful. - -2001-10-12 Jeffrey Stedfast - - * Makefile.am: Remove the stripheader filter from the build. - - * camel-mime-filter-stripheader.[c,h]: Removed. - - * providers/smtp/camel-smtp-transport.c (smtp_data): Check the - return value of camel_stream_flush to make sure it flushed the - data successfully before continuing. Don't use the stripheader - filter, it was completely broken - instead remove the header and - set it again after we send. - -2001-10-12 Not Zed - - * camel-vee-folder.c (camel_vee_folder_remove_folder): Unhook from - all events before removing folder. - (camel_vee_folder_add_folder): Hook onto delete event. - (camel_vee_folder_finalise): Unhook from deleted event for suibfolder. - (subfolder_deleted): When the folder is deleted, remove it from - the vfolder automagically. - -2001-10-11 Not Zed - - * camel-vee-folder.c (vee_search_by_uids): convert the uids list - to a subset appropriate for each subfolder before trying to search - on it. - - * camel-charset-map.[ch]: Removed charset/locale charset lookup - and iconv_open/close functions, moved to gal. Fixed all callers. - -2001-10-11 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (ssl_cert_is_saved): Same. - - * camel-tcp-stream-openssl.c (ssl_cert_is_saved): Instead of - opening the file, stat it and make sure that it belongs to us. - -2001-10-10 Jeffrey Stedfast - - * camel-tcp-stream-openssl.c (ssl_verify): Same hack as below. - - * camel-tcp-stream-ssl.c (ssl_bad_cert): Hack around the fact that - adding a cert to nss's certdb seems to not work. - -2001-10-10 Not Zed - - * camel-vee-folder.c (vee_sync): Only re-build the folder if we're - expunging. Also only clear out the changed folders list if we're - expungung and everything worked. - -2001-10-10 Jeffrey Stedfast - - * camel-charset-map.c (camel_charset_map_init): Added a hack for - Solaris systems. - -2001-10-10 Not Zed - - * providers/local/camel-maildir-store.c (scan_dir): oops, we want - get_unread_message_count, not get_message_count! - -2001-10-09 Not Zed - - * camel-service.c (camel_service_disconnect): Duplicate connect - code that unregisters a cancel op if we created one. - - * camel-operation.c (camel_operation_progress): Another go at - getting the logic right again. Make transients only update after - 5 seconds (CAMEL_OPERATION_TRANSIENT_DELAY) - (camel_operation_end): Likewise. - - * providers/local/camel-spool-folder.c (spool_search_by_uids): - Implement. - - * providers/imap/camel-imap-search.c (imap_body_contains): If - searching a sub-set of the total message count, then use a UID - range to search only specific messages. - - * camel-vee-folder.c (vee_folder_change_match): Removed. - (folder_changed_add_uid): Helper func for changed code. - (folder_changed_remove_uid): " - (folder_changed_change_uid): " - (folder_changed): Rewritten. Supports proper auto-updating of - changes, but not removals till a sync occurs. - (vee_search_by_uids): Implement. - (folder_changed): Changed to call an async threaded function to do - the actual folder updating. - - * camel-folder-summary.c (camel_flag_list_copy): New func to copy - a whole list of flags. - (camel_tag_list_copy): New func to copy a whole list of flags. - - * providers/imap/camel-imap-folder.c (imap_search_by_uids): - Implement. - - * providers/local/camel-local-folder.c (local_search_by_uids): - Implement. - - * camel-folder.c (camel_folder_search_by_uids): New function, - search a subset of uid's. - (search_by_uids): Default impl, return error. - -2001-10-08 Dan Winship - - * camel-folder.h (struct _CamelFolder): replace the ever-growing - list of gbooleans with a single guint32 for flags. - - * camel-folder.c: Update folder flag setting/checking. - - * providers/pop3/camel-pop3-folder.c (camel_pop3_folder_init): - * providers/nntp/camel-nntp-folder.c (camel_nntp_folder_new): - * providers/local/camel-spool-folder.c (spool_init, - camel_spool_folder_new): - * providers/local/camel-maildir-folder.c (camel_maildir_folder_new): - * providers/local/camel-local-folder.c (local_init): - * providers/imap/camel-imap-folder.c (camel_imap_folder_init, - camel_imap_folder_new): - * camel-vtrash-folder.c (camel_vtrash_folder_init): - * camel-vee-folder.c (camel_vee_folder_init): - * camel-digest-folder.c (camel_digest_folder_init): update folder - flag setting. - -2001-10-07 Dan Winship - - * providers/imap/camel-imap-store.c (get_folder_online): Unlock - the store before returning error. (noted by NotZed) - -2001-10-06 Jeffrey Stedfast - - * camel-mime-utils.c (header_decode_text): Fix a slight error in - logic. Just because the last word was an encoded word doesn't mean - we ignore the lwsp padding, we only ignore it if the last word and - *this* word are encoded. - -2001-10-06 Jeffrey Stedfast - - * camel-mime-filter-basic.c (filter): Implemented uuencoding and - decoding. - (complete): Implemented uuencoding and decoding. - - * camel-mime-utils.c (uuencode_close): New function to flush the - uu encoder. - (uuencode_step): New function to uuencode a block of data. - -2001-10-05 Not Zed - - * providers/imap/camel-imap-store.c (subscribe_folder): Use a - folder_subscribed event rather than a folder_created one. - (unsubscribe_folder): Similarly for unsubscribed/deleted. - (create_folder): Emit a folder_created event on the folders we - added. Not sure hsould probably check which ones are new and - which ones are just existing ones? - (delete_folder): Emit a folder_deletd event when we've deleted the - folder. Part of fix for #11831. - - * camel-store.c (camel_store_class_init): Added - folder_subscribed/unsubscribed events. - -2001-10-05 Jeffrey Stedfast - - * camel-service.c (camel_service_finalize): Turn off warnings. - (get_name): Same. - - * camel-sasl.c (sasl_challenge): Turn off warnings. - - * camel-tcp-stream.c (tcp_connect): Turn off warnings. - (tcp_getsockopt): Same. - (tcp_setsockopt): Here too. - (tcp_get_socket): And here. - - * camel-folder.c (folder_sync): Turn off warnings. - (expunge): Same. - (append_message): Here too. - (get_message): And here. - (search_by_expression): And again here. - (folder_changed): Here too. - - * camel-store.c (get_folder): Set an exception and turn off - debugging g_warnings. - (create_folder): Same. - (delete_folder): Here too. - (rename_folder): And here. - (get_trash): And here. - (get_folder_info): Same. - (free_folder_info): And again here. - (camel_folder_info_build): Here too. - (folder_subscribed): Same. - (subscribe_folder): Here too. - (unsubscribe_folder): And here. - -2001-10-05 Not Zed - - * camel-mime-utils.c (header_decode_mailbox): Try harder to get - broken names out of addresses. Unencoded ,'s in names will still - break it, but well what can you do eh? - (header_decode_mailbox): Always add .'s into address we've scanned - past a '.', even if we can't decode the next part. Fix for some - annoying bug #. - -2001-10-04 Not Zed - - * camel-store.c (camel_store_delete_folder): Change the order of - execution slightly. We delete the folder first, then call the - classes delete folder, then cleanup the hashtable afterwards. - This is so deletes of vfolders work, since vee-store uses the - folder hashtable to store all of is vfolders :-/ - -2001-10-04 Jeffrey Stedfast - - * camel-service.c (camel_service_connect): Unregister the - operation before unreffing it. - -2001-10-03 Not Zed - - * providers/imap/camel-imap-folder.c (camel_imap_folder_changed): - Remove now unused 'recents' array/freeing func. - - * camel-object.c (camel_object_trigger_event): Oops, always run - the prep function, even if we have no hooks listening. Causes - incoming imap recents to get ignored bythe camel-folder filter - inbox code. - - * providers/local/camel-local-folder.c (local_sync): Dont - explicitly save metadata, its saved in summary_sync. - - * providers/local/camel-mh-summary.c: Call superclass. - (mh_summary_check): Dont save ibex. - - * providers/local/camel-maildir-summary.c: Call superclass method. - (maildir_summary_check): Dont save ibex explictly. - - * providers/local/camel-mbox-summary.c: Call super-class sync when - done, saves summary/ibex, etc. - (mbox_summary_check): Dont save ibex. - (mbox_summary_sync): Call summary_check rather than trying to - update from our known position. - - * providers/local/camel-local-summary.c - (camel_local_summary_check): Dont save the summary or index here. - (local_summary_sync): Save the summary/index here. - - * camel-search-private.c (camel_search_build_match_regex): Added - MATCH_NEWLINE flag, -> REG_NEWLINE. - - * camel-lock-helper.c: Include to kill some warnings. - - * camel-filter-search.c (get_full_header): Put \n's between each - line we generate. - (header_full_regex): Dont drop the first argument to the command - -> empty matches! - (header_full_regex): Set match_newline for building regex. - (body_regex): And here too. These all fix #9877. - -2001-10-03 Jeffrey Stedfast - - * camel-store.c (camel_store_delete_folder): Call - camel_folder_delete() on the folder if it's "alive". - - * camel-folder.c (camel_folder_delete): Mark the folder as - deleted, perform any folder specific cleanup and emit the deleted - event. - (camel_folder_sync): Only sync the folder if it hasn't been - deleted. - (camel_folder_expunge): Same. - -2001-10-03 Dan Winship - - * providers/local/camel-local-provider.c (local_url_equal): - Strange are the ways of alloca. Fixes 11543. - -2001-10-02 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (ssl_bad_cert): Import the certificate if - the user accepts it. - -2001-10-02 Not Zed - - * providers/local/camel-local-provider.c (local_url_hash, - local_url_equal): for hashing/comparing local url's, we ignore - trailing /'s in paths (maybe shuld handle multiple /'s too). - (camel_provider_module_init): Use local_url_hash/equal for all - functions. - - * camel-sasl-digest-md5.c (digest_response): Change to - camel_charset_iconv_open/close. - - * camel-pgp-context.c (pgp_verify): Change to - camel_charset_iconv_open/close. - - * camel-mime-part-utils.c (convert_buffer): Change to - camel_charset_iconv_open(). - - * camel-mime-filter-charset.c - (camel_mime_filter_charset_new_convert, finalise): Change to - camel_charset_iconv_open, etc. - - * camel-mime-utils.c: Use the camel_charset_iconv_open/close() - functions to open/close it. - - * camel-charset-map.c (camel_charset_iconv_open): New function, - wrap iconv_open, so we can cache ic's. - (camel_charset_iconv_close): Likewise for close. - (camel_charset_map_init,shutdown): Init/free iconv cache. - -2001-10-02 Jeffrey Stedfast - - * camel-charset-map.c (camel_charset_to_iconv): Revert my - x-unknown special-case hack - this may mask other problems. - - * camel-mime-utils.c (rfc2047_decode_word): If the iconv - conversion fails, for whatever reason, retry using the user's - locale charset. - -2001-10-02 Not Zed - - * providers/local/camel-maildir-store.c (get_folder_info): Go back - to using the store url's path, not the toplevel_dir thing. - - * camel-operation.c (camel_operation_progress): Fix the progress - logic, so we dont update too often. - - * camel-object.c (camel_object_get_hooks): Change the lock to a - recursive e-mutex. - (camel_object_hook_event): Maintain list length of hook list. - (camel_object_unhook_event): " - (camel_object_unhook_event): If we are in an event, just mark the - pair as removed, without removing it. - (camel_object_trigger_event): Before running events, copy the - list, and also ignore 'removed' events. After running events, if - we're all out of events, then free up any pending-removed events. - (camel_object_free_hooks): Add some new assertions on the state of - the hook structure. - Removed the #error if threads not defined. It _should_ actually - work without threads. - (camel_object_free_hooks): Free mutex when done. - -2001-10-01 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (delete_folder): Remove any - cached messages that belonged to the deleted folder. - (subscribe_folder): Don't ever let the info->name be NULL and - don't use the stupid concat kludge to generate the URL, just use a - CamelURL to do it. This way we don't risk breaking stuff by having - a url like imap://fejj@imap//folder - - * camel-charset-map.c (camel_charset_to_iconv): If the charset is - x-unknown, return the locale_charset. - -2001-10-01 Dan Winship - - * camel-provider.h: Fix up the provider flags to specify things - more completely so we don't have to hardcode provider names in the - mailer. - - * providers/local/camel-local-provider.c: MH, mbox, and Maildir - are LOCAL. MH and mbox are no longer STORAGE by the new - definition. - - * camel-session.c (vee_provider): The vfolder store is a STORAGE. - -2001-10-01 Dan Winship - - * providers/local/camel-local-store.c (construct): Don't munge the - URL; CamelSession's caching relies on it not changing. Instead, - add a toplevel_dir field to CamelLocalStore, and set that to the - path, but always ending with /. - (camel_local_store_finalize): Free toplevel_dir - (camel_local_store_get_toplevel_dir): Return toplevel_dir rather - than url->path. - - * providers/local/*: Lots of s/url->path/toplevel_dir/ - - * providers/local/camel-spool-store.c (construct): Likewise, don't - try to strip a trailing / from url->path here, but I didn't make - the corresponding toplevel_dir change, because there's no good - reason someone should expect "/var/spool/mail/danw/" to work since - that's not a directory. - - * providers/pop3/camel-pop3-folder.c (pop3_refresh_info): if STAT - returns 0, don't bother sending UIDL. Speeds things up slightly - and also works around a bug in a particular random POP server. - (ximian bug 11369). - -2001-09-29 Jeffrey Stedfast - - * camel-pgp-context.c (pgp_sign): Add --no-secmem-warning and - --no-greeting to the gpg command-line options. - (pgp_clearsign): Same. - (pgp_verify): Here too. - (pgp_encrypt): And here. - (pgp_decrypt): And finally here. - -2001-09-28 Jeffrey Stedfast - - * camel-filter-search.c (get_source): Same here. - - * camel-mime-message.c (camel_mime_message_set_source): Don't use - the e_url_shroud hack, use CamelURL functions instead. - -2001-09-28 Jeffrey Stedfast - - * providers/nntp/camel-nntp-provider.c - (camel_provider_module_init): Init the nntp url hash and url_equal - functions. - - * providers/sendmail/camel-sendmail-provider.c - (camel_provider_module_init): Init the sendmail url hash and - url_equal functions. - - * providers/smtp/camel-smtp-provider.c - (camel_provider_module_init): Init the smtp url hash and url_equal - functions. - - * providers/pop3/camel-pop3-provider.c - (camel_provider_module_init): Init the pop3 url hash and url_equal - functions. - - * providers/imap/camel-imap-provider.c - (camel_provider_module_init): Init the imap url hash and url_equal - functions. - - * providers/local/camel-local-provider.c - (camel_provider_module_init): Init the local url hash and - url_equal functions. - - * camel-session.c (camel_session_class_init): Init the vfolder url - hash and url_equal functions. - - * camel-provider.h: Added url_hash and url_equal function pointers - to the structure. - - * camel-vtrash-folder.c (vtrash_move_messages_to): Oops, a - CamelFolder is not a CamelFolderClass. - -2001-09-28 Dan Winship - - * camel-tcp-stream-openssl.c (ssl_error_to_errno): Make this take - an SSL * instead of a CamelTcpStreamSSL *, since it can get called - from open_ssl_connection, when the CamelTcpStreamSSL isn't set up - right yet. Fixes a crash on connection failure. - -2001-09-27 Dan Winship - - * providers/imap/camel-imap-folder.c - (camel_imap_folder_fetch_data): Grab the store's command_lock - before grabbing the folder's cache_lock to prevent deadlock if - another thread is processing an EXPUNGE response. - - * providers/imap/camel-imap-folder.c - (imap_expunge_uids_resyncing): Fix a compiler warning that might - point out a real bug... - - * providers/imap/camel-imap-folder.c (get_content): and one that - doesn't - -2001-09-27 Not Zed - - * camel-service.c (camel_service_connect): Dont re-register the - connect_op if we got it by calling 'operation_registered', which - returns an already-registered one. - (camel_service_disconnect): Likewise here. This removes all the - re-registered warnings. - - * camel-object.c (camel_object_unref): Fill the finalised data - with nonsense, rather than 0's - more easily detect bad data. - (camel_object_new): Clear instance data when we retrieve it off - the list. - - * camel-object.h (_CamelObject): Added an event lock pointer for - uh, locking event stuff. Also change the hooklist hashtable into - a list. Changed all the code to handle it. Result: thread-safe - events, event-hooks, and save memory too, and SHOULD FINALLY FIX - THAT UNREAD COUNT PROBLEM. - -2001-09-27 Jeffrey Stedfast - - * camel-pgp-mime.c (camel_pgp_mime_part_decrypt): CRLF decode the - stream before parsing it into a MIME part. This fixes bug #10521. - - * camel-store.c: Remove the old folder from the vTrash folder. - -2001-09-27 Dan Winship - - * camel-service.c: Change "gboolean connected" to - "CamelServiceConnectionStatus status", which can be disconnected, - connecting, connected, or disconnecting. - (camel_service_init, camel_service_finalize): create/destroy the - connect_op_lock. Refer to service->status rather than - service->connected. - (camel_service_connect): When connecting, note the current - operation (and create a new one if there's none registered) and - mark the connection "connecting" until we succeed or fail. - (camel_service_disconnect): Likewise in reverse. - (camel_service_cancel_connect): New function to cancel a - connection attempt. - (cancel_connect): Default implementation: Call - camel_operation_cancel on the connect_op. - - * camel-disco-store.c (disco_connect): Only call - CamelRemoteStore's connect func if we're online. - (disco_cancel_connect): Fall back to offline if a connection gets - cancelled. - (disco_get_folder_info): Kludge: call connect explicitly before - deciding whether to do the online or offline version, so if the - connect fails, we fall back correctly. - - * camel-session.c (camel_session_get_service_connected): - s/svc->connected/svc->status/ - - * camel-remote-store.c (camel_remote_store_finalise): - Change service->connected check to service->status check. - (remote_connect): Don't set service->connected here: - camel_service_connect() itself does that. - - * camel-operation.c (camel_operation_registered): Deal with the - possibility that there's no registered op. - -2001-09-26 Not Zed - - * camel-filter-driver.c (camel_filter_driver_filter_message): If - we get a search error, just abort, dont try and fall back and copy - to inbox. - (camel_filter_driver_filter_message): Make sure we ALWAYS use - exceptions for important things - like moving messages to inbox! - (camel_filter_driver_filter_message): If we have the source - folder, use camel_folder_set_message_flags rather then poking the - info directly, which skips changed events. This means filtering - immediate doesn't lose changed events. - (do_flag): Same here. - (do_colour): Same thing but using set_tag. - (do_score): Same again. - (camel_filter_driver_filter_folder): Use ~0 as the 'set' arg to - set_flags, just saves typing. - (open_folder): We cache folders that we couldn't open as well as - those ones we could. Use magic token FOLDER_INVALID = - (void *)~0 as the marker. - (close_folder): Handle FOLDER_INVALID case properly. - -2001-09-26 Jeffrey Stedfast - - * camel-mime-message.c - (camel_mime_message_get_part_by_content_id): New function to - convenience Larry ;-) - (check_content_id): Oops, return !found instead of found. This - callback has to return whether or not to keep searching, not - whether or not it found what it's looking for. Do'h! - - * camel-pgp-mime.c (camel_pgp_mime_is_rfc2015_signed): block out - some code if ENABLE_PEDANTIC_PGPMIME is not defined. - -2001-09-26 Not Zed - - * camel-vee-store.c: Emptied VeeStorePrivate, member wasn't used. - - * camel-vee-folder.c (camel_vee_folder_set_expression): Lock - changed list separately. - (camel_vee_folder_remove_folder): " - (camel_vee_folder_set_folders): Use changed_lock for changed list. - (vee_refresh_info): Use changed_lock, also just grab the list, - reset it in the lock, and do the work unlocked. - (vee_sync): Use changed lock for changed list. - (folder_changed): ". All this kills a deadlock with sync/expunge. - - * camel-private.h (CamelVeeFolderPrivate): Added a new lock for - the folders-changed list. - (CamelVeeStorePrivate): Removed, defined in camel-vee-store.c, - thanks to a pedantic. - -2001-09-26 Jeffrey Stedfast - - * Makefile.am: Fix Ettore's fix. - -2001-09-25 Jeffrey Stedfast - - * camel-pgp-context.c (camel_pgp_context_new): No longer takes a - remember argument. - (pgp_sign): Only uncache the passphrase on failure. - (pgp_clearsign): Same. - (pgp_encrypt): Here too. - (pgp_decrypt): And here. - (pass_free): New function to zero the passphrase before freeing - it. - -2001-09-25 Ettore Perazzoli - - [Patch for Automake 1.5 compatibility pointed out by Richard - Boulton , as per #9258.] - - * providers/nntp/Makefile.am: Remove some commented parts that - make Automake 1.5 choke. - - * Makefile.am (camel-lock-helper): Add $(EXEEXT) for Automake 1.5 - compatibility. - -2001-09-25 Not Zed - - * camel-folder.c (get_unread_message_count): Only unref info if we - got it. - - * camel-operation.c (camel_operation_unref): Fix for !threads - enabled not ccompiling. - (camel_operation_ref): Assert refcount > 0. - (struct _CamelOperation): Removed the lock. On further - investigation, I dont think this will always work, the - registration operations assume that a lookup in the - operation_active table will return a ref, that will remain valid - until we ref it, which needn't be the case. So now i'm using a - single global lock, since we'd need to do that for unref anyway, - and every operation is fast & memory-bound. Changed all the code - to handle this. - (camel_operation_progress_count): Since the code is identical, - just call progress() for now. - (camel_operation_register): No longer refcount, use unref to - check/clear the active table. - (camel_operation_unregister): Same here. - (camel_operation_unref): Check if operation is in active table, if - so, warn, remove. - -2001-09-25 Dan Winship - - * camel-tcp-stream-openssl.c (my_SSL_read, my_SSL_write): call - SSL_read/write, looping on SSL_ERROR_WANT_READ/WRITE. I'm sure - there's a perfectly good reason that the API works this way. No, - really. - (stream_read, stream_write): use my_SSL_read and my_SSL_write. - Fixes at least ximian 8593, and probably 6024 and maybe 10366, - at least for OpenSSL. There may be a parallel NSS bug? - -2001-09-25 Not Zed - - * camel-stream-buffer.c (stream_write_all): A "safe write" - function that always writes out all data asked of it, till - finished. - (stream_write): Rewritten. What was i on when i wrote that - originally, how did it ever work with tcp streams ... - -2001-09-24 Not Zed - - * camel-folder.c (append_message): Set the exception to - FOLDER_INVALID rather than making out it worked. A fix for #7025. - (search_by_expression): Here too. - - * providers/imap/camel-imap-folder.c (imap_update_summary): In the - 'lose' case, free messages, not fetch_data twice! - - * camel-filter-search.c (check_header): If the type is encoded, - get the fallback charset from the message content-type. - - * camel-mime-part-utils.c (check_html_charset): Dont check for - charset==null before calling charset_to_iconv. - (simple_data_wrapper_construct_from_parser): " - - * camel-mime-message.c (process_header): Try use content-type - charset param as the fallback charset. - - * camel-charset-map.c (camel_charset_to_iconv): Handle name == - NULL, return NULL. - - * camel-folder-summary.c (camel_folder_summary_format_address): - (camel_folder_summary_format_string): Made private again, removed - #warning about it. Renamed to s/camel_folder//. - (summary_format_string): Take default charset param. - (camel_message_info_new_from_header, message_info_new): Decode - content-type field to get the charset parameter to use as the - default charset for decoding strings. - - * camel-search-private.c (camel_search_header_match): Pass NULL as - the charset, the locale charset is always tried. - (camel_search_header_match): Supply a default_charset parameter to - be used with TYPE_ENCODED params. - - * camel-mime-utils.c - (header_param): get rid of the g_strcasecmp crap. - (header_set_param): Same here. - (header_decode_param_list): And here. - (header_decode_text): Totally rewritten. 30% of its size. If the - word is not rfc2047 encoded, always try default_charset if - supplied, if that fails, try locale charset if it exists, if that - fails then assume latin1/7 bit ascii. - (append_8bit): Changed to return FALSE if we can't convert for - whatever reason, and dont append anything. - - * camel-mime-part.h (struct _CamelMimePart): Move content_type and - headers out of the 'private' section. - - * camel-mime-part.c (get_headers): Dont do any conversion on the - header. - (process_header): Get the content-type charset as the fallback - charset for decode_string. - (construct_from_parser): IF we have a content-type header, process - it before doing anything else, so we have access to a fallback - charset for invalid headers. - -2001-09-23 Jeffrey Stedfast - - * camel-tcp-stream-openssl.c (ssl_verify): Don't even try to alert - the user if the session isn't interactive. - (errlib_error_to_errno): Make the default errno EINTR so that we - act just like CamelTcpStreamSSL. - - * camel-pgp-context.c (pgp_sign): When the password is not - provided, set the exception to USER_CANCEL. - (pgp_clearsign): Same. - (pgp_encrypt): And here. - (pgp_decrypt): Here too. - -2001-09-21 Not Zed - - * camel-store.c (create_folder): Set the exception if - create_folder isn't implemented. - -2001-09-21 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (create_folder): Go back to - not using camel_folder_info_build() here because this seems to - break folder creation (returning nodes from the root path when it - shouldn't be?). - -2001-09-21 Not Zed - - * camel-vee-store.c (vee_get_folder_info): Force a refresh of - vfolders before storing their count. This essentially makes - 'get_folderinfo' refresh all vfolders, so that get-mail works as - expected. - - * camel-vee-folder.c (camel_vee_folder_finalise): Clear lists. - (folder_changed): If we're not autoupdating the folder, then - add this folder to the list of 'changed' folders for this vfolder. - (camel_vee_folder_set_expression): Reset the folders_changed list. - (camel_vee_folder_remove_folder): Remove the folder from the - folders_changed list. - (camel_vee_folder_set_folders): If we have a folder already, but - its changed, use this opportunity to update it. - (vee_sync): Remove any synced folders from the folders_changed - list. - (vee_refresh_info): Refresh folder, re-run queries on any changed - folders. - -2001-09-20 Not Zed - - * camel-folder-summary.c (camel_folder_summary_header_load): New - function to just load the summary. Not much use yet, until unread - counts are stored in the summary (which now looks like too much - work!). - - * camel-mime-utils.c (header_decode_mailbox): Crappy fix for - stupid mailers. If we get 'name b. name ' then treat it as - '"name b. name" '. See 8147. - (header_decode_mailbox): Another fix for really broken mailers - that have things that look like addresses followed by
- bits. - (rfc2047_encode_word): Escape ??= to avoid some bizarre warning - about trigraphs. - - * providers/local/camel-local-folder.c - (camel_local_folder_construct): Setup unread count properly, and - also setup the url properly. - - * providers/local/camel-maildir-store.c (camel_folder_info_new): - Build the path on the folderinfo. - (scan_dir): Dont include empty host part in url for folder. - (scan_dir): Lookup folder counts for any folders we currenty have - open. - (scan_dir): If we dont have the folder open, then scan the 'new' - and 'cur' folders for new and unread messages to count instead. - - * providers/local/camel-spool-store.c (get_folder_info): If we - have this folder open, then set unread from the folder itself. - (get_folder_info): Change the INBOX path to not include the - leading /. - - * providers/local/camel-spool-folder.c - (camel_spool_folder_construct): Fix path. - (camel_spool_folder_construct): Properly setup the url field when - we say we've got a new folder created. - - * providers/imap/camel-imap-store.c (unsubscribe_folder): Build - path on folderinfo. - - * camel-store.c (camel_folder_info_build_path): Prepend / to path. - - * camel-vee-folder.c (camel_vee_folder_construct): Use macro for - unmatched folder name. - (camel_vee_folder_new): " - - * camel-vee-store.c (vee_get_folder_info): Use macro for unmatched - folder name. - (vee_delete_folder): " - (vee_rename_folder): " - (vee_get_folder): Prepend / onto path. - (vee_delete_folder): Setup path in folderinfo. - (vee_get_folder_info): Fix path in folderinfo. - - * camel-vee-folder.h (CAMEL_UNMATCHED_NAME): New define for - unmatched (internal) name. - -2001-09-20 Jeffrey Stedfast - - * providers/local/camel-spool-folder.c - (camel_spool_folder_construct): And finally here. - - * providers/local/camel-local-folder.c - (camel_local_folder_construct): And here. - - * camel-vee-store.c (vee_get_folder): ANd here too. - (vee_get_folder_info): And here. - - * providers/imap/camel-imap-store.c (create_folder): Use - camel_folder_info_build() and do better error checking. - (subscribe_folder): Set the path on the folder info. - - * camel-store.c (camel_folder_info_build): Set the folder-info - path if it hasn't already been set by the caller. - (camel_folder_info_free): Free the path. - - * camel-store.h: Added a path member to the FolderInfo type. - -2001-09-20 Dan Winship - - * camel-charset-map.c (camel_charset_to_iconv): Nuke debug warning. - -2001-09-19 Jeffrey Stedfast - - * camel-pgp-context.c: Updated exception strings to be more clear. - - * camel-pgp-mime.c (pgp_mime_part_sign_restore_part): Stupid - mistake, fixes bug #9975. - - * camel-tcp-stream-ssl.c (ssl_bad_cert): Oops, don't fail if - `data' isn't a CamelService...cuz it's not supposed to be! It's a - CamelTcpStreamSSL object...doh! - -2001-09-19 Not Zed - - * General cleanup of camel debug printfs. - - * camel-lock.c (camel_lock_fcntl): Changed to return 'success' if - the error indicates file locking isn't supported on this - filesystem. Still return a warning just incase (if its the first - time). Might fix a lot of reported bugs. - - * providers/local/camel-spool-store.c (get_folder_info): Dont - include the empty // host part in the uri. This 'breaks' the - service lookup. - -2001-09-18 Jeffrey Stedfast - - * camel-mime-utils.c: Match mailing-list header List-Owner. - -2001-09-18 Not Zed - - * camel-vee-store.c (vee_get_folder): Fix the uri genereated for - the folderinfo for the folder_created event. - - * camel-store.h: Added 'total' to CamelFolderInfo. - -2000-09-18 Not Zed - - * providers/local/camel-maildir-folder.c - (camel_maildir_folder_new): If filter inbox is set on the store, - and we're opening inbox '', then enable filtering on new messages. - - * providers/local/camel-local-folder.c - (camel_local_folder_construct): After loading the summary, check - it, and only abort if that fails. Also maintain the changes - count. - - * providers/local/camel-local-summary.c - (camel_local_summary_load): Remove summary_check code from here. - (camel_local_summary_check): Sync index/summary here, if we were - successful. - - * providers/local/camel-spool-folder.c - (camel_spool_folder_new): If we have filter-new-messages-on-inbox - set and we just opened inbox, turn on filtering on this folder. - (camel_spool_folder_construct): Keep track of changes for the - folder, so that filter-new-messages works right (?) - - * providers/local/camel-spool-store.c (get_folder): Pass 'INBOX' - as the folder name, not the path. - - * camel-folder-search.c (search_not): Modified patch from - since the summary is messageinfo's, not - strings. - - ** Ok so the problem with the stuff below is that maildir/spool - 'summary_load' throws away all events, including recents, joy eh? - - * providers/local/camel-maildir-summary.c (maildir_summary_check): - Add new messages to the recent changeinfo. - - * providers/local/camel-spool-summary.c: Mark 'new' message as - recent, for later processing if required (i.e. 'filter new - messages'). - - * camel-store.c (construct): new function, cascade up construct - method and check for 'filter' param, and set accordingly for any - one that might want it. - - * providers/imap/camel-imap-store.c (construct): map the - param_filter_inbox flag to the store->flags as - CAMEL_STORE_FILTER_INBOX. - - * camel-store.h (CAMEL_STORE_FILTER_INBOX): new flag to tell it to - filter inbox. - - * providers/imap/camel-imap-folder.h: Removed do_filtering flag - from CamelImapFolder. - - * providers/imap/camel-imap-folder.c (imap_update_summary): Remove - the 'recents' parameter, use the 'changes' parameter instead to - convey this info. - (camel_imap_folder_changed): Changed for update_summary api - change. Now always just emit the changed event if we have any - changes to report, filtering code removed, handled upstream. - (filter_proc): - (filter_free): Removed old filtering code. - (camel_imap_folder_new): Set the filter_recent flag on the folder - if we're the inbox and filtering of inbox is enabled. - - * camel-folder.c (folder_changed): If we have 'recent' messages, - and are set to filter recents, then freeze the folder and launch a - thread to do the processing (or similar if threading not enabled). - (thaw): Make sure we emit the changed signal outside of owning the - lock and if things have changed. Also, no longer bother - downgrading folder_changed events to message_changed events. - - * camel-folder.h (struct _CamelFolder): Added filter_recent flag - -> signifies all recent messages in folder should be filtered. - - * camel-session.c: (camel_session_thread_msg_new, - camel_session_thread_msg_free, camel_session_thread_queue, - camel_session_thread_wait): code to handle async operations as - part of camel processing. - (camel_session_finalise): free thread_lock, destroy thread, active - hash, etc. - (camel_session_init): init thread, active hash, etc. - (camel_session_class_init): Init virtual functions. - (session_thread_msg_new, session_thread_msg_free, - session_thread_destroy, session_thread_received, - session_thread_queue, session_thread_wait): default implementation - of session threads stuff. - -2001-09-17 Not Zed - - * camel-folder.c (camel_folder_change_info_recent_uid): New - function to add a 'recent' uid to the change info. - (camel_folder_change_info_clear): Clear recent list. - (camel_folder_change_info_free): Free recent list. - (camel_folder_change_info_new): Setup recent list. - - * camel-folder.h: Added a uid_recent item to the folder_changed - event data. - - * providers/local/camel-maildir-store.c (scan_dir): Free new in - the right block. - - * providers/local/camel-local-provider.c: Add local config entries - to filter on new messages in spool and maildir provider. - - * camel-vee-folder.c (vee_folder_construct): Remove the assertion - which stops ? in names from being allowed. - -2001-09-18 Dan Winship - - * camel-data-wrapper.c (camel_data_wrapper_is_offline): Virtualize - this. - - * camel-medium.c (is_offline): A medium is offline if its content - object is offline. - - * camel-multipart.c (is_offline): A multipart is offline if any of - its subparts are offline. - -2001-09-18 Jeffrey Stedfast - - * camel-charset-map.c: Added korean charset conversion. - -2001-09-17 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (delete_folder): Don't process - the ImapResponse data, we don't want to block forever on data we - don't care about... - (create_folder): Use get_folders_online() instead of - get_folder_info_online(). - - * camel-folder.c: Reverted previous changes. - -2001-09-17 JP Rosevear - - * Makefile.am: Helpful install-exec-hook debugging output - -2001-09-16 Jeffrey Stedfast - - * camel-folder.c (camel_folder_get_uri): New function to get the - URI of a folder. - (get_uri): Default implementation. - -2001-09-14 Not Zed - - * camel-vee-folder.c (camel_vee_folder_set_folders): New function, - set the complete list of folders on a vfolder, all at once. - (camel_vee_folder_set_expression): If we set the query to be the - same thing, dont do anything. - - * camel-vee-store.c (camel_vee_store_init): Turn off vtrash for - this store. - - * camel-store.c (camel_store_init): Enable vtrash by default via - flags. - (camel_store_get_trash): REturn NULL if the store doesn't support - vtrash. - (init_trash): Dont init if store doesn't support vtrash. - - * camel-store.h: Add a new flags CAMEL_STORE_VTRASH -> store - supports vtrash. - -2001-09-13 Not Zed - - * camel-vee-store.c (vee_get_folder_info): Implement. - (build_info): Used to build a folder record from the folders - hashtable. - (vee_delete_folder): Implemented, remove folder from hashtable. - (vee_rename_folder): Implemented, remove old folder from - hashtable, add new one and rename its guts too. - - * camel-store.c (camel_store_rename_folder): Do nothing if we're - not asked to actually change names. Also dont do the renamed - cache check till after we've called the subclass. - (camel_store_delete_folder): Call the subclass delete firs,t then - make sure the cache is right. - - * camel-vee-folder.c (vee_folder_construct): Remove support for - name?query syntax to setup vfolder. Abort if such syntax is used. - (camel_vee_folder_new): Removed code that handles ? syntax, etc. - (vee_folder_build_folder): Handle unset expression, treat it as an - empty search. - (camel_vee_folder_set_expression): Oops, actually set the - expression. - - * camel-vtrash-folder.c (camel_vtrash_folder_new): Dont use - name?query syntax to setup vfolder, but set the expression - directly. Also fixes a small memleak. - -2001-09-12 Not Zed - - * camel-store.c (camel_store_delete_folder): Fixed warnings with a - cast. - (camel_store_rename_folder): " - -2001-09-14 Jeffrey Stedfast - - * camel-url.c (camel_url_set_param): Use g_datalist_set_data_full - so that the data will be free'd when we clear the list. - -2001-09-14 Dan Winship - - * camel-file-utils.c (camel_file_util_encode_string, - camel_file_util_decode_string): Don't claim failure when - reading/writing the empty string. - -2001-09-14 JP Rosevear - - * Makefile.am: use install hook instead of install rule to - guarantee we run after installation - -2001-09-13 Jeffrey Stedfast - - * camel-filter-driver.c (camel_filter_driver_filter_folder): Don't - reuse the exception if it has already been set. - (camel_filter_driver_filter_message): Same here. Also use the new - return value from camel_filter_search_match(). - - * camel-filter-search.c (camel_filter_search_match): Return an - integer (matched, no-match, or error). - - * providers/local/camel-mbox-folder.c (mbox_append_message): Do - error-checking based on function return values rather than - exceptions as it's possible for them to be NULL. - (mbox_get_message): Same. - - * providers/imap/camel-imap-folder.c (imap_append_offline): Pass - an exception to the cache. - (imap_append_online): Same. - (imap_append_resyncing): Here too. - (imap_copy_offline): And here. - (handle_copyuid): Pass NULL as the exception here... - (parse_fetch_response): And finally here. - - * providers/imap/camel-imap-message-cache.c - (camel_imap_message_cache_insert): - (insert_setup): - (camel_imap_message_cache_insert_stream): - (camel_imap_message_cache_insert_wrapper): - (camel_imap_message_cache_copy): Take an exception argument and - set it on error. - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): Convert the charset - to the iconv-friendly name. - - * camel-charset-map.c (camel_charset_to_iconv): Add code to - convert windows-[cp]#### charsets to their iconv-friendly format - of cp####. - - * camel-pgp-context.c (crypto_exec_with_passwd): Return -1 on - failure. - -2001-09-12 Larry Ewing - - * camel-filter-driver.c (camel_filter_driver_filter_mbox): free - the source url in the nonfailure case. - -2001-09-12 Not Zed - - * camel-folder-search.h: Change the 'not' virtual method from an - immediate e-sexp function to a non-immediate one, which is what it - should be. - - * camel-folder-search.c (search_not): Implement a 'not' function - ourselves. If 'not' on a vector value, then not over all items - in the summary. - (builtings[]): Change the 'not' builtin to be a non-immediate - function. - -2001-09-12 Jeffrey Stedfast - - * camel-filter-driver.c (camel_filter_driver_filter_mbox): Unref - the message info. - -2001-09-10 Not Zed - - * providers/local/camel-maildir-store.c (get_folder_info): Pass in - a hashtalbe used for finding visited nodes. - (inode_hash): - (inode_equal): - (inode_free): Helper functions for visited node checks, hashes on - inode + device number. - (scan_dir): Dont re-visited directories we've already visited, use - inodes + device number. - Also, if the folder doesn't contain cur/tmp/new, mark it as - noselect, but continue to recurse folders, if asked. - - * camel-folder.c (move_messages_to): Progress reporting while - moving messages. - - * camel-store.c (camel_store_delete_folder): Make sure we remove - the folder from our vtrash, if we have it in our opened set, and - also remove it from our hashtable. - (camel_store_rename_folder): Remove the old folder name from the - folder cahce, if it is there. - -2001-09-10 Jeffrey Stedfast - - * camel-charset-map.c (camel_charset_to_iconv): Get rid of the - g_warning, we no longer really need that. - -2001-09-10 Not Zed - - * providers/imap/camel-imap-store.c (camel_imap_msg_new): Forgot - to return the newly allocated msg. - -2001-09-08 Not Zed - - * providers/local/camel-spool-summary.c (spool_summary_sync_full): - Likewise. - - * providers/local/camel-mbox-summary.c (mbox_summary_sync_full): - Fix the wording. - - * camel-tcp-stream-raw.c (stream_read): Save errno around fcntl - call in cancellable read case. Also, loop while we get EINTR. - This might fix some weird reconnect behaviour with pop. - (stream_write): " - -2001-09-07 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (ssl_bad_cert): #if 0 out the code that - was hopefully going to fix bug #5325 because the functions I used - seem to have been deprecated. *sigh*. - - * camel-remote-store.c (camel_remote_store_finalise): Disconnect - from the service here otherwise the locks will be destroyed and by - the time CamelService finalizes we'll crash or hang. - - * providers/smtp/camel-smtp-transport.c (smtp_data): Make sure to - unref the mime filters when we finish with them. - -2001-09-07 Ettore Perazzoli - - * providers/local/camel-mbox-summary.c (mbox_summary_sync_full): - s/Synchronising/Synchronizing/. - (mbox_summary_sync_quick): Likewise. - (summary_rebuild): s/Summarising/Summarizing/. - -2001-09-07 Jeffrey Stedfast - - * camel-multipart.c (camel_multipart_set_boundary): Take a const - char * instead of a char *. - - * camel-mime-part-utils.c - (camel_mime_part_construct_content_from_parser): Reuse the - original boundary instead of generating our own. - -2001-09-06 Not Zed - - * providers/imap/camel-imap-folder.c (filter_proc): Thread - function to perform filtering. - (filter_free): Free the filter object. - (camel_imap_folder_changed): If we have threads enabled, then - queue up a request to perform filtering. For bug #4422. - - * providers/imap/camel-imap-store.c (camel_imap_msg_new): Create a - new 'imap msg'. - (camel_imap_msg_queue): Queue an 'imap msg'. - (async_received): Handle receiving of imap msg in async thread. - (async_destroy): Handle destroying of imap msg. - (camel_imap_store_finalize): Destroy thread when done. - (camel_imap_store_init): Setup thread. - - * providers/imap/camel-imap-store.h: Added an ethread to the - store, for async processing. - -2001-09-06 Jeffrey Stedfast - - * camel-remote-store.c (remote_recv_line): Use - camel_stream_buffer_read_line() instead of duplicationing the - functionality. Also, the previous way was broken anyway. What if a - line was the same length as our buffer? Then we'd go and read a - second line and a third and so on until they weren't the same - length, leaving \r's in the middle of the buffer. - -2001-09-06 Dan Winship - - * providers/pop3/camel-pop3-store.c (pop3_get_response): Fix this - to always set an exception if it returns POP3_FAIL, as documented. - - * providers/pop3/camel-pop3-folder.c (pop3_get_message_stream): - Revert. - -2001-09-06 Jeffrey Stedfast - - * providers/pop3/camel-pop3-folder.c (pop3_get_message_stream): - Set an exception on POP3_FAIL as well. - -2001-09-06 Dan Winship - - * providers/pop3/camel-pop3-provider.c: #ifdef out the "delete - after N days" option in pop3_conf_entries, since it won't be done - for 1.0. - -2001-09-04 Jeffrey Stedfast - - * camel-remote-store.c (remote_disconnect): Too late to sync the - folders here... if this is gonna happen at all it should be done - in the provider. - - * camel-service.c (camel_service_finalize): Do a clean disconnect. - -2001-08-30 Jeffrey Stedfast - - * providers/local/camel-spool-store.c (get_inbox): Return the - default folder (ie. INBOX) rather than saying we don't support an - inbox. - - * camel-tcp-stream-ssl.c: #include pk11func.h. - (ssl_bad_cert): Use CERT_GetDefaultCertDB. - -2001-08-29 Jeffrey Stedfast - - * camel-smime-context.c (smime_sign_prepare): Do the same here as - what we did in the pgp code a moment ago. - (smime_sign_restore): And again here. - (smime_sign): And update thise code to pass in the address of the - encodings list when restoring parts. - - * camel-pgp-mime.c (pgp_mime_part_sign_prepare_part): Special-case - message/rfc822 mime parts - don't set an encoding on these, - instead traverse into their subparts and set the encodings for - those. - (pgp_mime_part_sign_restore_part): Reverse any operations done to - message/rfc822 parts in the above prepare_part() function and also - take a pointer to a GSList of encodings instead of just a GSList - so we can properly keep track of which encoding we are on. - (camel_pgp_mime_part_sign): Pass in the address to the encodings - list when restoring parts. - -2001-08-29 Not Zed - - * providers/pop3/camel-pop3-folder.c (pop3_sync): Add progress - reporting to deleting messages. Dont change the calculation to a - bloody float. Bug #6189. - -2001-08-28 Jeffrey Stedfast - - * camel-pgp-context.c (crypto_exec_with_passwd): Initialize buf - and diag_buf to NULL, hopefully this fixes the crash if the - select() times out. - (pgp_encrypt): Argh. What was I thinking? Don't use "-r recipient" - as an argument, instead use "-r" and "recipient" as 2 separate - arguments to pgp. This might fix the "gpg only encrypts to my - private key" bug? - -2001-08-28 Peter Williams - - * providers/imap/camel-imap-store.c (create_folder): Whoops. - Double-free and FMR = bad. - - * camel-remote-store.c (remote_send_string): Don't reveal the - user's IMAP password if their server supports LITERALPLUS. Also - add some more dashes to make it line up nicely :-) - -2001-08-28 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (ssl_bad_cert): If the user accepts the - certificate, add it to the database as a trusted CA. - -2001-08-28 Peter Williams - - * camel-object.c (camel_object_unref): Make the locking more - fine-grained on destruction; specifically, don't hold the - type lock while calling the finalize functions. - -2001-08-27 Jeffrey Stedfast - - * providers/local/camel-local-provider.c: Changed the - description/names of some of the local providers to try and - clarify the meanings. - - * providers/pop3/camel-pop3-provider.c: Simplify the POP - description - we want short but sweet. - - * providers/imap/camel-imap-provider.c: s/IMAPv4/IMAP - -2001-08-27 Not Zed - - * camel-mime-part-utils.c (convert_buffer): re-read the iconv man - page, and treat the return value properly. It returns the number - of non-reversible conversions performed, not the number of output - characters, sigh. - (check_html_charset): Changed to just take a buffer of data, and - not the mime parser. - (simple_data_wrapper_construct_from_parser): Since we dont need - the charset till we have all the data, search for the charset - after we've read the data, if we have html data with no charset in - the header. - (simple_data_wrapper_construct_from_parser): Remove the - seekable_source stuff. - - * Re-apply patches from before. - -2001-08-25 Not Zed - - ["Summarising" and "Synchronising" are spelt with a "s" in - ENGLISH] - - * providers/local/camel-mbox-summary.c (mbox_summary_sync_quick): - s/Synchronizing/Synchronising/. - - * providers/local/camel-mbox-summary.c (summary_rebuild): - s/Summarizing/Summarising/ - -2001-08-24 Jeffrey Stedfast - - * camel-disco-diary.c (camel_disco_diary_replay): Use fseek - instead of fseeko since we want to be portable and use ftell - rather than ftello for the same reason. - (camel_disco_diary_empty): Same here. - -2001-08-24 Peter Williams - - * Revert Not Zed's previous commits as they apparently can cause - serious data loss for POP3 users. - -2001-08-24 Ettore Perazzoli - - ["Summarizing" and "Synchronizing" are spelt with a "z" in the - default locale, that happens to be "en_US".] - - * providers/local/camel-mbox-summary.c (mbox_summary_sync_quick): - s/Synchronising/Synchronizing/. - - * providers/local/camel-mbox-summary.c (summary_rebuild): - s/Summarising/Summarizing/ - -2001-08-24 Not Zed - - * camel-mime-part-utils.c (convert_buffer): Limit the maximum - output buffer size. iconv bugs? returns E2BIG forever on some - (valid) data? - - * providers/local/camel-spool-summary.c (summary_rebuild): - Likewise. - - * providers/local/camel-mbox-summary.c (summary_rebuild): - Summarising is spelt with an s. - -2001-08-23 Not Zed - - * camel-mime-part.c (write_to_stream): If we have rawtext, then - dont do any charset conversion, only encoding/crlf conversion. - - * camel-data-wrapper.h (struct _CamelDataWrapper): Added 'rawtext' - member, says the character encoding is raw, not utf8. - - * providers/local/camel-spool-summary.c - (spool_summary_sync_quick): Synchronising is spelt with an s, not - a z. - (spool_summary_sync_full): " - - * providers/local/camel-mbox-summary.c (mbox_summary_sync_full): - No, synchronising is spelt with an s. - (mbox_summary_sync_quick): " - - * camel-mime-part-utils.c - (camel_mime_part_construct_content_from_parser): Remove the - warnings which aren't going anywhere fast. - (convert_buffer): Function to convert a bytearray of textual - content from one charset to another. If the charset doesn't exist - or fails, then do no conversion. - (simple_data_wrapper_construct_from_parser): First, read in data, - then try and convert it using the specified charset if supplied. - If that fails, then dont do any conversion, and leave as raw. - Also, if we have any x-* charsets, then dont do any processing. - -2001-08-23 Peter Williams - - * providers/local/camel-mbox-summary.c (summary_rebuild): Add a - missing \n to the end of a printf. - - * providers/local/camel-spool-summary.c (summary_rebuild): Same. - -2001-08-22 Jeffrey Stedfast - - * providers/pop3/camel-pop3-folder.c (pop3_generate_uids): - Oops. Fixed a mis-use of GPtrArray. If we set_size, then using - g_ptr_array_add will assume `size' elements have already been - initialized and will start appending on to the end. - -2001-08-21 Jeffrey Stedfast - - * camel-pgp-context.c (pgp_verify): Turn on --batch and reenable - gpg keyserver lookups. - (pgp_decrypt): Disable keyserver lookups if we are disconnected. - -2001-08-21 Dan Winship - - * camel-folder-thread.c - (camel_folder_thread_messages_new_summary): Fix the duplicate - message check so it doesn't mess up threading when a reply appears - in the folder before the message it's a reply to. Fixes bug #3357. - (camel_folder_thread_messages_new): Likewise, although I don't - think this function is used any more. - -2001-08-20 JP Rosevear - - * Makefile.am: build a static camel for the addressbook conduit - -2001-08-20 Ettore Perazzoli - - * providers/local/camel-mbox-summary.c (mbox_summary_sync_full): - s/Synchronising/Synchronizing/. - (mbox_summary_sync_quick): Likewise. * - providers/local/camel-spool-summary.c (spool_summary_sync_full): - Likewise. - (spool_summary_sync_quick): Likewise. - -2001-08-20 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (create_folder): Get the - entire directory structure for the folder we just created, meaning - if we created a folder named "test.mailbox" where test didn't - previously exist, get the listing for "test" and "test.mailbox". - - * providers/imap/camel-imap-utils.c (imap_parse_folder_name): New - function. - -2001-08-19 Chris Toshok - - * camel-store.h: #include for mode_t on freebsd. - -2001-08-19 Jeffrey Stedfast - - * providers/pop3/camel-pop3-folder.c (pop3_generate_uids): Make - sure the generated UID is non-NULL before appending it to the - array of UIDs. How would this even happen? I have no clue... - -2001-08-17 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_update_summary): Start - scanning new messages at maxuid + 1 rather than uidval + 1? Maybe - I'm missing the logic, but anyways...this might fix bug #5348. - -2001-08-16 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (imap_keepalive): If we are - online and message flags have changed in the current folder, sync - the flags else do a NOOP. This fixes bug #4666. Also lock around - the NOOP command. - - * providers/imap/camel-imap-folder.c (imap_sync_online): Don't - ever send "STORE FLAGS.SILENT ()" since Cyrus imapd doesn't like - this (and maybe others too?) so what we'll do instead is to send - "STORE -FLAGS.SILENT (\Seen \Answered \Deleted \Marked)" to clear - all the flags (since this is in essence what we want to do - anyway). - -2001-08-16 Peter Williams - - * providers/imap/camel-imap-store.c (imap_connect_online): Fix - this again. Sigh. Problem of namespace = "" may not yet be - completely solved. - -2001-08-15 Peter Williams - - * camel-tcp-stream-openssl.c (ssl_error_to_errno): New - function. Try to approximate the SSL error into errno. - (errlib_error_to_errno): New function, try to approximate - OpenSSl's error library's error (ERR_*) into errno. - (stream_read): Try to set errno using ssl_error_to_errno. - (stream_write): Same. - (open_ssl_connection): Same. - - * providers/imap/camel-imap-store.c (imap_connect_online): Oh - crap, huge killer typo. - -2001-08-14 Peter Williams - - * providers/imap/camel-imap-store.c (imap_connect_online): - Canonicalize store->namespace to end in store->dir_sep, once both - values are known. The %F-related code makes this - assumption. Probably fixes a bug reported on the mailing list. - -2001-08-13 Jeffrey Stedfast - - * camel-store.c (camel_store_get_folder): After talking to NotZed, - it turns out I was wrong after all. - (store_sync): Create a copy of the folder-cache that owns a ref on - each of the folders so that if one of the folders get's finalized - inside store_sync(), we don't run into any locking issues. This is - mostly meant to solve a problem in IMAP (#6089). - -2001-08-13 Peter Williams - - * providers/imap/camel-imap-store.c (delete_folder): Fix a leak. - - * providers/imap/camel-imap-utils.c (imap_namespace_concat): Bleah, - handle when namespace = NULL (can happen upon initial open of mailbox.) - - * providers/imap/camel-imap-command.c (imap_command_strdup_vprintf): - Don't crash when %F'ing with an empty folder name and NULL namespace. - -2001-08-13 Jeffrey Stedfast - - * camel-store.c (camel_store_get_folder): We need to be ref'ing - the folder if/when we add it to the hash. This may fix bug #6089? - (camel_store_get_folder): Nevermind, reverted the fix. - (camel_store_get_folder): No, I wasn't on crack before after - all...if we don't ref here, then we're open to a race condition - later. - -2001-08-11 Ettore Perazzoli - - * providers/local/camel-spool-summary.c (summary_rebuild): - s/summarising/summarizing/. - (summary_rebuild): Likewise. - - * providers/local/camel-mbox-summary.c (mbox_summary_sync_full): - s/summarise/summarize/. - (mbox_summary_sync_quick): Likewise. - (summary_rebuild): Likewise. - (mbox_summary_check): Likewise. - -2001-08-10 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c (imap_quote_string): Added an - assert - at this point a backtrace would be more useful than a - transaction log for debugging. - - * providers/imap/camel-imap-command.c (imap_command_start): Return - FALSE here, not NULL. - - * providers/imap/camel-imap-folder.c (imap_rescan): Don't - g_strdup() the uid into the trigger_event call. - - * providers/pop3/camel-pop3-folder.c (pop3_get_message_stream): - Set the total bytes expected to 0 if the response is empty too. - (pop3_refresh_info): Return of there was an error generating pop3 - uids. - - * camel-mime-utils.c (header_raw_check_mailing_list): regfree the - pattern before continue'ing. This was showing up quite a bit under - purify. - -2001-08-09 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c (imap_parse_string_generic): A - quoted string cannot contain \n's so check for those as well. - (imap_atom_specials): Update this to fix bug #6553. - -2001-08-08 Jon Trowbridge - - * camel-filter-search.c (get_source): Remove trailing stuff from - URLs before returning. (Done in an evil way, not in the good way - suggested by fejj. :)) (Bug #4876) - -2001-08-08 jacob berkman - - * camel-search-private.c (camel_search_header_match): check for - NULL name and addr (fixes a bug i was about to report) - -2001-08-08 Not Zed - - * camel-filter-search.c (check_header): Properly determine match - type to pass to header_match. - (address_matches_exactly): Removed, effectively added to - camel_search_header_match. - - * camel-folder-search.c (check_header): Properly determine the - match type to pass to header_match. - - * camel-search-private.c (camel_search_header_match): Add a new - parameter 'type' which is the type of header we're matching - against. ASIS means utf8 format, ADDRESS means an internet - address ('formatted'), ADDRESS_ENCODED means a raw address header, - ENCODED means rfc 2047 encoded text. - (header_match): Move original logic here, have search_header_match - call it as appropriate for the 'type' of match. - -2001-08-07 Not Zed - - * camel-session.c (camel_session_class_init): Only init the vee - provider struct once (if we're subclassed this will get called - multiple times). - - * camel-object.c (obj_finalize): Removed a bit of a debug that - crept in with jacob's poolv patch (?). - -2001-08-07 Jeffrey Stedfast - - * camel-filter-search.c (address_matches_exactly): New function to - do danw's address "is" comparison (as specified in bug #5886. - (check_header): Special-case address-type headers when we are - doing an exact match to use the address_matches_exactly function. - -2001-08-06 Jeffrey Stedfast - - * providers/pop3/camel-pop3-folder.c (pop3_get_message_stream): - Modify to take a headers_only argument which will then only fetch - message headers. - (pop3_generate_uids): Pass in TRUE for headers_only. - (pop3_get_message): Pass in FALSE for headers_only and move the - camel_operation() stuff out of get_message_stream and in to here - instead. - (pop3_generate_uids): We also need to be using i+ 1 as the id - since we are starting at 0. - -2001-08-06 Jeffrey Stedfast - - * providers/pop3/camel-pop3-folder.c (pop3_get_message_stream): - New internal function to get a message stream by message sequence - id (so that we can share code between pop3_get_message and - pop3_generate_uids). - (pop3_get_message): Use pop3_get_message_stream. - (pop3_generate_uids): New function to generate UIDs based on the - message - this fixes bug #1256. - (pop3_refresh_info): If the server doesn't support UIDL, call - pop3_generate_uids to get our list of UIDs. - - * providers/imap/camel-imap-store.c (get_folder_info_online): - Don't strstr for noselect=yes, that's just plain broken. - -2001-08-06 Dan Winship - - * providers/imap/camel-imap-folder.c (imap_rescan): Fix off-by-one - error in cleaning up deleted messages at the end of the folder. - Fixes bug #5585 and maybe others. - - * providers/imap/camel-imap-store.c (get_folder_info_online): Do a - refresh_info on the selected folder before looking at its unread - count. Should fix bug #4944. - -2001-08-06 Peter Williams - - Completely hide the namespace from everything external to the IMAP - code, which Dan W says is the way it should be. - - * providers/imap/camel-imap-command.c - (imap_command_strdup_vprintf): Add a new %F argument, which is like - %S but will add the namespace (for folder names). - (camel_imap_command): Use %F here. - - * providers/imap/camel-imap-utils.c (imap_parse_list_response): - Changed to strip out the namespec when returning *folder. In order - to do this we need to be passed the CamelImapStore. - (imap_concat): Move to here from camel-imap-store.c, un-static - (imap_namespace_concat): New function, adds the namespace to the - folder name, unless it's INBOX. - - * providers/imap/camel-imap-utils.h: Prototypes. - - * providers/imap/camel-imap-store.c (imap_connect_online): Extra - arg to imap_parse_list_response. - (imap_connect_offline): Here too. - (get_folder_status): Use %F. - (get_folder_online): Here too. - (delete_folder): Here too. - (create_folder): Here too, and arg to imap_parse_list_response. - (parse_list_response_as_folder_info): Arg to i_p_l_r. - (get_subscribed_folders_by_hand): Use %F. - (get_folders_online): Here too. - (get_folder_info_online): Instead of checking for NULL @name, check - for name = NULL or "", and set to "" instead of namespace. Pass "" - instead of namespace to camel_folder_info_build. - (subscribe_folder): Use %F. - (unsubscribe_folder): Here too. - - * providers/imap/camel-imap-folder.c (imap_get_full_name): This - now just returns folder->full_name. - (do_append): Use %F - (do_copy): Here too. - -2001-08-06 Jeffrey Stedfast - - * camel-pgp-context.c (pgp_verify): Always do --no-auto-key-retrieve. - -2001-08-03 Jeffrey Stedfast - - * camel-pgp-context.c (pgp_verify): Minor changes to the iconv - code so that it does the check in the return value of iconv() just - like the code in camel-mime-utils.c in case this fixes Bo Rosen's - gpg bugs (but I doubt this will change anything?). - -2001-08-03 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_connect): First - check to make sure that service->url->authmech is non-NULL before - passing it into strcmp to avoid a segfault. - - * camel-pgp-context.c (pgp_decrypt): Sigh, if gpg returns '1' it - means that the key is bad but it did succeede in decrypting the - block so to make users happy (even though I find this a - questionable action) we are going to ignore the error and show it - to the user anyway. This fixes bug #6136. - -2001-08-03 Not Zed - - * providers/smtp/camel-smtp-transport.c (smtp_connect): special - case popb4smtp auth before we try and connect, and do the magic - here first. - -2001-08-02 Not Zed - - * providers/smtp/camel-smtp-transport.c (smtp_connect): Check for - POPB4SMTP separate to the esmtp auth list. - (smtp_auth): If creating the sasl object means it is - already authenticated, then exit early. Sort of 'clean hack' to - help popb4smtp work. - (smtp_auth): Unref the sasl object, clean up a memleak i think. - - * providers/smtp/camel-smtp-provider.c - (camel_provider_module_init): Added POPB4SMTP auth type. - - * camel-sasl.c (camel_sasl_authtype): Added POPB4SMTP type. - - * camel-sasl-popb4smtp.c: New file for pop before smtp - 'authentication'. - - * Makefile.am (libcamel_la_SOURCES, HEADERS): Add - camel-sasl-popb4smtp.[ch]. - -2001-08-01 Not Zed - - * providers/local/camel-mbox-folder.c (mbox_lock): If we fail to - get the lock, make sure we close our locking fd, and reset it. - Fixes the crash part of 5095. - - * providers/imap/camel-imap-folder.c (camel_imap_folder_changed): - Slightly re-arranged filter/change notification logic. If we;re - filtering, freeze the folder till we're finished to smooth the ui - for new mail. - -2001-07-31 Not Zed - - * camel-folder.c (camel_folder_init): Changed mutexes to - e_mutexes, folder lock recursive. This fixes the imap filtering - bug, or at least some cases of it. - (camel_folder_finalize): Free mutexes. - - * camel-private.h (CamelFolderPrivate): Changed mutexes to - e_mutexes. - -2001-07-25 Not Zed - - * camel-folder.c (camel_folder_change_info_*): Change the - return if fail's into asserts. - (camel_folder_change_info_free): Don't let it accept a NULL - argument. This isn't g_lib so we dont have to. - -2001-07-27 Jeffrey Stedfast - - * camel-mime-utils.c (header_decode_param): Fix the fix that fixes - broken mailer behavior. We want to make sure that the user's - locale charset is non-NULL before we pass it off to - iconv_open(). If it *is* NULL, we want to use iso-8859-1. - -2001-07-26 Jeffrey Stedfast - - * camel-url.c (camel_url_free): Allow the url to be NULL just like - the libc free convention. - -2001-07-26 Dan Winship - - * providers/imap/camel-imap-command.c (camel_imap_command_start): - Send an IMAP command, but don't wait for responses. - (camel_imap_command_response): Read a single line of response from - the server. - (camel_imap_command, etc): Reimplement in terms of the new code. - - * providers/imap/camel-imap-folder.c (imap_rescan): Use - camel_imap_command_start and camel_imap_command_response, and - call camel_operation_progress after each line read from the - server. - (imap_update_summary): Likewise, although with more fudging on the - precentages... Also, fix this so that if none of the new messages - are cached, it only does a single FETCH, and if some of them are - cached, it does two FETCHes (one to get the UIDs, FLAGS, and - SIZEs, and another to get the bodies of all of the messages that - aren't cached now that it knows the relevant UIDs). This should - speed up startup a bunch (especially if you have high bandwidth - but also high latency to the IMAP server). - -2001-07-25 Dan Winship - - * camel-mime-utils.c (mail_mlist_magic): Add another Sender - pattern. - -2001-07-24 Not Zed - - * providers/imap/camel-imap-folder.c (camel_imap_folder_changed): - Change the break into a continue, we should process as many as we - can find. - - * camel-folder.c (camel_folder_move_messages_to): If we have no - uid's to copy, exit here before going any further. Some code - internally [imap] assumes there are uids to copy otherwise it can - segfault. - (camel_folder_copy_messages_to): Same. - -2001-07-24 Jeffrey Stedfast - - * camel-mime-utils.c (header_decode_param): Handle broken mailers - that send unencoded 8bit header params. And there was much - rejoicing. Rah. - - * camel-url.h (CAMEL_URL_HIDE_ALL): New #define, and there was - much rejoicing. Rah. - -2001-07-24 Not Zed - - * camel-operation.c (camel_operation_register, unregister): Added - some warnings for bad cases. - -2001-07-23 Not Zed - - * camel-operation.c (camel_operation_register): Only insert a hash - entry if we haven't already. - (camel_operation_unregister): Only remove the has entry if the id - is a real thread. - -2001-07-23 Jeffrey Stedfast - - * camel-filter-driver.c (do_move): Slight fix for when source == - destination (we don't want to do this action because on-demand - filtering would then delete the messages it supposedly "moved"). - -2001-07-23 Not Zed - - * providers/smtp/camel-smtp-transport.c (smtp_auth, smtp_helo, - send_to): Added some operation progress reporting. Actual data - transfer is 'tricky' because of the layers used. - (smtp_auth): Instead of checking exception_is_set, use - challenge==NULL to test if sasl_challenge_base64 failed. - - * providers/local/camel-mbox-summary.c (mbox_summary_sync): Remove - peters changes below and put in a better fix. These functions - already return -1 on error, just use that, and not worry about - building our own exception redundantly. - - * camel-service.c (camel_get_host_byname): Turn the progress into - a transient event. - -2001-07-20 Peter Williams - - * providers/local/camel-mbox-summary.c (mbox_summary_sync): More - usage fixes for CamelException. Check our own exception for - summary_update and xfer it out if an error occurred. - -2001-07-20 JP Rosevear - - * Pull up test fixes to get them building again - -2001-07-20 Not Zed - - * camel-charset-map.c (camel_charset_get_iconv_friendly_name): - renamed to camel_charset_to_iconv() to make it just a little more - consistent and not so long & fixed callers. - -2001-07-19 Jeffrey Stedfast - - * camel-mime-filter-charset.c - (camel_mime_filter_charset_new_convert): Convert to the - iconv-friendly charset names. - - * providers/imap/camel-imap-store.c (create_folder): Fixed a - compiler warning about returning without a value in a non-void - function. Blah. - - * camel-mime-part.c (process_header): Pass the locale charset as - the default_charset to header_decode_string(). - - * camel-folder-summary.c (camel_folder_summary_format_string): - Pass the locale charset as the default_charset to - header_decode_string(). - (content_info_new): Same. - - * camel-mime-message.c (process_header): Pass the locale charset - as the default_charset to header_decode_string(). - - * camel-mime-utils.c (append_8bit): New helper function who's - purpose is similar to append_latin1() but for 8bit text that we - are assuming is not latin1. - (header_decode_text): Now takes a default_charset parameter and - calls append_8bit when appropriate. - (header_decode_string): Also takes a default_charset parameter - now. - (header_decode_mailbox): Pass NULL as the default_charset to - header_decode_string(). - -2001-07-19 Jeffrey Stedfast - - * camel-pgp-context.c (pgp_verify): Modified to treat the return - value from camel_charset_locale_name() as a const char*. - - * camel-sasl-digest-md5.c (digest_response): Modified to treat the - return value from camel_charset_locale_name() as a const char*. - - * camel-charset-map.c (camel_charset_locale_name): Modify to - return const char* by returning the static locale_charset which is - created inside of camel_charset_map_init(). - (camel_charset_map_init): Find the locale charset here and set the - static variable. - -2001-07-19 Peter Williams - - Policy change: NULL url's are no longer allowed in - CamelFolderInfos. They used to signify that the folder was, in - IMAP jargon, NoSelect; now the same effect is achieved by adding a - "noselect=yes" parameter to the end of the URL. As far as I know, - IMAP is the only affected provider. - - * providers/imap/camel-imap-store.c (delete_folder): New - function. Implement folder deletion. - (camel_imap_store_class_init): Set the delete_folder class - function here. - (get_folder_status): New function. Utility wrapper around the - STATUS command. - (create_folder): If the parent folder is NoSelect but is empty, - delete it and recreate it as a a subfolder-containing folder. If - it is NoSelect but contains messages, set an exception. - (parse_list_response_as_folder_info): Always set the FolderInfo's - URL, but add a NoSelect parameter if it isn't selectable. - (get_folder_info_online): Change logic of removing the namespace - to reflect URL change. Same for logic of checking unread counts. - (get_folder_info_online): Use get_folder_status to simplify this. - - * camel-store.c (camel_folder_info_build): When creating dummy - parents, copy the child's URL and set the NoSelect parameter. - -2001-07-19 Jeffrey Stedfast - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): No need for - `acharset' anymore. - (check_html_charset): Return a const char* and also use - camel_charset_get_iconv_friendly_name() internally. - - * camel-mime-utils.c (rfc2047_decode_word): Remove my iso8859-1 -> - iso-8859-1 hack and use camel_charset_get_iconv_friendly_name() - instead. - (rfc2184_decode): Use camel_charset_get_iconv_friendly_name() - - * camel.c (camel_init): Call camel_charset_map_init(). - - * camel-charset-map.c (camel_charset_map_init): New function to - initialize the charset-equivalent lookup table. To be called by - camel_init(). - (camel_charset_get_iconv_friendly_name): New function to try and - convert a charset into something that iconv is more likely to - accept. - -2001-07-19 Peter Williams - - * Revert 7/11/2001 patch for IMAP INBOX filtering at NotZed's - request. - -2001-07-17 Peter Williams - - Clean up some exception misusage. - - * providers/imap/camel-imap-command.c (camel_imap_command): Use - our own internal exception for sending the string and transfer it - to @ex if anything goes wrong. - (imap_read_response): Use our own internal exception for reading - the untagged responses and blah blah blah. - - * camel-session.c (get_service): Use our own internal exception - when constructing the service and transfer it to @ex if anything - goes wrong. - - * camel-remote-store.c (remote_recv_line): Instead of having - gboolean exception, use our own internal exception and copy - it to @ex if anything goes wrong. - - * camel-store.c (store_sync): Create an internal exception - because sync_folder() checks it for validity. Transfer it to - @ex when done. - - * camel-exception.c (camel_exception_get_description): If @ex is - NULL, complain - passing NULL exceptions to Camel is okay, but - there should be no circumstances under which they're then - examined. - (camel_exception_get_id): Same here, - (camel_exception_xfer): NULL-protect and warn if transferring from - a NULL exception. - -2001-07-17 Jeffrey Stedfast - - * camel-store.c (init_trash): Use CAMEL_VTRASH_NAME. - - * camel-vtrash-folder.h: #define CAMEL_VTRASH_NAME - -2001-07-16 Dan Winship - - * providers/imap/camel-imap-command.c (camel_imap_response_free): - Given: - * 4 EXISTS - * 1 EXPUNGE - We have to pass 3, not 4 to camel_imap_folder_changed for the - exists count. Fixes ximian bug #2112 (finally!). - -2001-07-14 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (camel_imap_folder_changed): - If the message info for an expunged message is NULL, then just - break out - maybe a message was expunged that we were never - notified even existed? - -2001-07-13 Jeffrey Stedfast - - * camel-mime-utils.c (rfc2047_decode_word): Added a hack to - convert charsets in the format iso8859-1 to iso-8859-1 because it - seems to be more iconv friendly. It has been reported that on some - systems, iconv doesn't know about iso8859-1 while it *does* know - about iso-8859-1. See bug #4530. - -2001-07-13 Peter Williams - - * Makefile.am (install-exec-local): Let people install as - non-root, but give them a bigass warning so they're not allowed to - complain when it doesn't work right. - - * camel-remote-store.c (sync_remote_folder): New function: hash - table callback. - (remote_disconnect): If cleanly disconnecting, sync our - folders. Fixes deadlocks on exit (folders syncing after store - disconnects) and also makes sense. - -2001-07-13 Jeffrey Stedfast - - * camel-uid-cache.c (camel_uid_cache_new): We now use a structure - as the bucket data rather than just a cache level so set the save - state to TRUE. - (maybe_write_uid): We only save the uid if the cache levels are - the same *and* if the save state is TRUE. - (free_uid): Free the state value. - (camel_uid_cache_get_new_uids): New uids that get added to the - cache start with a save state of FALSE. - (camel_uid_cache_save_uid): Set the save state of the uid to - TRUE. What should we do if the uid isn't already in the cache? - Currently I make it add the uid, but maybe it shouldn't? - - * providers/imap/camel-imap-folder.c (imap_filter_timeout): Update - to reflect CamelFilterDriver API changes. - - * camel-filter-driver.c (camel_filter_driver_filter_folder): Take - a cache argument so we can tell the cache whether or not the uid - should be saved (meaning we have successfully filtered it). - -2001-07-12 Jeffrey Stedfast - - * camel-filter-driver.c (camel_filter_driver_filter_message): - Okay, I've decided that that user is just on crack. We don't want - to allow filtering of deleted messages or we could get some - unexpected behavior. - (do_move): Oops. My last fix needs to be after the if-statement, - not inside it. - (do_copy): And here too. - -2001-07-12 Jeffrey Stedfast - - * camel-filter-driver.c (do_move): Only set p->copied and - p->deleted if the messages are copied without an exception. - (do_copy): Same - but obviously we don't set the p->deleted here - at all. - (camel_filter_driver_filter_message): Since users complained that - they couldn't filter deleted messages for "safe keeping" (WTF? - safe keeping? why were they deleted in the first place then??), I - have taken out the code that optimized filtering by not allowing - deleted messages to be filtered. This fixes bug #4473. - - Note: Users have a warped sense of logic. - -2001-07-12 Not Zed - - * camel-mime-part-utils.c (extract_metatag_charset): Removed. - (check_html_charset): Replaced with this. - (simple_data_wrapper_construct_from_parser): Call - check_html_charset if we dont have a charset on the content-type, - and we have text/html data. - (check_html_charset): We also need to do qp/base64 decoding - ourselves, sigh. - - * camel-mime-utils.c (html_meta_param_list_decode): Removed. This - was very wrong, the rules for mail headers vastly different from - rules for decoding html elements. - (rfc2184_decode): Move the malloc inside the iconv_open worked, - otherwise we have a memleak. - - * camel-mime-filter-html.c (camel_mime_filter_html_finalize, init, - run, reset): Changed to use camelhtmlparser, and fixed a tiny - memleak. - - * camel-html-parser.c: Made the html indexer tokeniser re-usable. - ONLY TO BE USED INTERNAL TO CAMEL HOWEVER. - (tokenise_step): Slight fix to non-quoted values. - - * camel-folder-summary.c - (camel_folder_summary_info_new_from_message): Removed some code i - wasn't supposed to commit. - - * providers/local/camel-local-summary.c (local_summary_add): Only - set info->size if it is not zero. - (local_summary_add): If we dont get a size from the info passed - in, calculate it using a null stream write. Should do #4392. - -2001-07-11 Jeffrey Stedfast - - * camel-mime-part-utils.c (extract_metatag_charset): New function - to extract a meta-tag charset value if it exists. - (simple_data_wrapper_construct_from_parser): Along the same lines - as the code I previously ripped out, but this time use the - mime-parser's seek ability to help us along. Currently I read up - to a 2k buffer size - this is probably overkill, 1k is probably - plenty. - - * camel-mime-utils.c (html_meta_param_list_decode): When we get to - an `=', we must skip past it before trying to grab the param - value. duh. - -2001-07-11 Jeffrey Stedfast - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): Ripped out my code - since it was never being used since the mime parser is not using a - seekable stream (ever?) which pretty much means my code needs to - be done someplace else. - -2001-07-11 Peter Williams - - * providers/imap/camel-imap-folder.c (camel_imap_folder_changed): - Run the filter in its own thread to prevent locking issues. - (imap_filter_timeout): New function that does the filtering called - as a CamelSession timeout. - -2001-07-11 Not Zed - - * camel-filter-driver.c (camel_filter_driver_filter_mbox): Create - the messageinfo itself, so we can properly set the size. - - * camel-movemail.c (camel_movemail_solaris): Write out the from - line between each message. - -2001-07-10 Not Zed - - * providers/local/camel-local-summary.c (local_summary_add): Copy - the size across from the source message info if supplied. - - * camel-stream-null.c: Added a 'written' member which keeps track - of how much has been written to the stream. - - * camel-movemail.c (camel_movemail): If we have BROKEN_SPOOL - defined, then use the solaris movemail to quote from lines that - sendmail didn't. - (camel_movemail_solaris): Compile this in if BROKEN_SPOOL defined. - -2001-07-10 Jeffrey Stedfast - - * camel-mime-utils.c (html_meta_param_list_decode): New function - to parse an HTML meta-tag. - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): If the Content-Type - did not contain a charset parameter and it's also a text/html - part, we have 1 last place to look - in the META html tags. *sigh* - - * camel-mime-message.c (camel_mime_message_get_source): - s/gint/unsigned since that's what it should be. - -2001-07-09 Jeffrey Stedfast - - * camel-pgp-context.c (pgp_sign): Forget the passphrase if the - user has set that option. - (pgp_clearsign): Same. - (pgp_encrypt): And here... - (pgp_decrypt): And finally here. - (camel_pgp_context_new): Take a `remember' argument. - -2001-07-09 Not Zed - - * providers/local/camel-maildir-summary.c (maildir_summary_sync): - Oops, e_poolv_set free's it for us, so dont double-free here. - -2001-07-06 Not Zed - - * camel-vee-folder.c (camel_vee_folder_finalise): Changed so we - dont have the list changing under us, just going to the next node - before we call a function that might change the list is - potentially dangerous (slight mod of peters fix). Hmm, i think it - would've double-unref'd it too(?) - -2001-07-08 Chris Toshok - - * camel-tcp-stream-openssl.c (camel_tcp_stream_openssl_finalize): - openssl_table is gone. we now store/get the stream from the - SSL_CTX's app_data. - (stream_read): rework the non-blocking case to account for SSL - possibly buffering data (in which case select will block even - though data is ready to be read), and to account for FreeBSD's - strange behavior of returning -1/EAGAIN even though select said - the fd was ready to be read. - (ssl_verify): openssl_table is gone. - (open_ssl_connection): set the SSL_CTX's app_data to be the - stream, remove the openssl_table code. - -2001-07-06 Jeffrey Stedfast - - * camel-mime-utils.c (header_encode_param): Don't allow in to be - NULL, so instead of doing if (in == NULL) return;, make it a - g_return_val_if_fail and later we can make it an assert or - something. - - * providers/local/camel-maildir-store.c (get_inbox): Fixes bug - #1138. - - * providers/local/camel-mbox-summary.c - (camel_mbox_summary_build_from): Make the `day-of-month' digit - take up 2 chars by using "%2d". Fixes bug #3989 for lame mailers - like Pine. - - * camel-pgp-context.c (crypto_exec_with_passwd): Set the pipe fd's - to nonblocking. - -2001-07-06 Peter Williams - - * camel-object.c (camel_object_unref): Make sure that after the - finalization event has happened and the finalization functions - have been called that the object still has a zero refcount. - -2001-07-06 Joe Shaw - - * providers/nntp/camel-nntp-grouplist.c: Add locking to - camel_nntp_get_grouplist_from_server(). - - * providers/nntp/camel-nntp-resp-codes.h: Added - NNTP_EXTENSIONS_SUPPORTED (202). - - * providers/nntp/camel-nntp-store.c (camel_nntp_store_get_extensions): - Check for both NNTP_LIST_FOLLOWS and NNTP_EXTENSIONS_SUPPORTED from - a LIST EXTENSIONS request. (Dunno if NNTP_LIST_FOLLOWS ever comes - out of this, but that's what was already there...) Also, put some - locking around it. - (finalize): e_mutex_destroy() the command lock - (camel_nntp_store_init): e_mutex_new() the command lock. - - * providers/nntp/camel-nntp-store.h: Add locking macros. - -2001-07-05 Jeffrey Stedfast - - * camel-folder-summary.c (camel_message_info_string): Added an - assert to make sure that `mi' isn't NULL. - (camel_message_info_set_string): Same. - - * providers/imap/camel-imap-command.c (camel_imap_response_free): - Create and use a temporary CamelException for use with - camel_imap_folder_changed. - -2001-07-05 Jeffrey Stedfast - - * camel-pgp-context.c (pgp_verify): Send the - --no-auto-key-retrieve argument to gpg if we are in offline mode - so that we don't have to worry about gpg hanging if it can't - connect to the key servers, because now it shouldn't even attempt - to. - -2001-07-05 Chris Toshok - - * camel-tcp-stream-openssl.c (ssl_verify): use - X509_STORE_CTX_get_ex_data to get at the SSL* - don't use the - X509_STORE_CTX to look up our stream, since it's not what we used - to insert our stream into the hashtable. - (open_ssl_connection): insert the stream into the hashtable before - calling SSL_connect, as this can cause ssl_verify to be called, - and we need to look up the stream there. remove the stream from - the hashtable if there's an error connecting. - (stream_connect): pass the CamelTcpStreamOpenSSL* to - open_ssl_connection since it handles the hashtable stuff. remove - hashtable stuff from here. - -2001-07-05 Jeffrey Stedfast - - * camel-folder.c (camel_folder_copy_messages_to): if source == - dest, just no-op. - -2001-07-05 Peter Williams - - * camel-vee-folder.c (camel_vee_folder_finalise): Move this before the - camel_vee_folder_remove_folder because that function modifies p->folders - messing up our iteration. - (camel_vee_folder_finalise): Don't unref our summary; camel-folder now - does this. - - * camel-object.h (CamelObject): Add a 'destroying' flag to CamelObject. - - * camel-object.c (obj_init): Clear 'destroying'. - (camel_object_unref): If 'destroying' then do not send the finalize - event and do not call finalize functions. Otherwise, set destroying - so just in case we get refed (eg event code) we don't get doubly - finalized. - -2001-07-05 Not Zed - - * camel-mime-filter-basic.c (filter): Fix the assertion slightly, - if we have a little bit of input the output size could be larger, - since we store upto 3 chars in the state. - - * camel-folder-summary.c - (camel_folder_summary_info_new_from_message): When indexing a new - record, create a pseudo word 'ibexindexed' so we can always tell - that a message has already been idnexed, even if it contains no - words of its own. Things like maildir use this check to see if - its already been processed, and it matters if it is incorrect in - this case (not just wasted cycles). - (camel_message_info_dup_to): Assign the to->strings from the - e_poolv_cpy() call, since it may allocaote a new poolv if the - lengths do not match. - - (camel_folder_summary_info_new_from_parser): And same here. - - * providers/local/camel-maildir-summary.c (maildir_summary_sync): - Changed the logicfor epoolv code to be different, we dont need to - update hash references or any tricky stuff. - (maildir_summary_check): Samehere. - - * camel-folder-summary.h: Removed include of e-memory.h. - -2001-07-03 Joe Shaw - - * providers/nntp/camel-nntp-resp-codes.h: Added NNTP_NO_PERMISSION - (502) to the list of response codes. - - * providers/nntp/camel-nntp-store.c (nntp_store_connect): If we - receive a NNTP_NO_PERMISSION, don't get into an infinite loop trying - to reconnect, get extensions, etc. Just give up and return FALSE. - -2001-07-03 Dan Winship - - * providers/imap/camel-imap-message-cache.c - (camel_imap_message_cache_clear): Doh. Don't remove things from - the hash table while foreach'ing it. (And can't use foreach_remove - either because we have to remove them in a weird order). Fixes - #3618. - - * providers/imap/camel-imap-folder.c (imap_get_message): If the - server returns OK from the FETCH BODY, but there's no parseable - BODY response, it's probably because there's an UN-parseable BODY - response, implying the message is badly formatted, MIMEwise. In - that case, fall back to fetching the message as a single part. - -2001-07-02 Sam Creasey - - * providers/nntp/camel-nntp-folder.c: Implemented - nntp_folder_search_by_expression and - nntp_folder_search_free. Basic search functionality e.g. unread - marking now works for NNTP folders. - - * camel_filter_search.c (get_size): Added get-size sexp directive - to get the size of a message for filters. - - * providers/nntp/camel-nntp-folder.c (camel_nntp_folder_new): - Always check with the NNTP server after summary load -- this - function now always expires old summary entries and syncs with - the news server. - - * providers/nntp/camel-nntp-utils.c (camel_nntp_get_headers): - Only fetch headers for articles not already logged in - the summary file. - - * providers/nntp/camel-nntp-grouplist.c - (camel_nntp_get_grouplist_from_*): change from g_list_append() - to g_list_prepend() + g_list_reverse. Traversing 40,000 - element linked lists sucks. - - * providers/nntp/camel-nntp-store.c (camel_nntp_command): - Should the NNTP connection die with - CAMEL_EXCEPTION_SERVICE_NOT_CONNECTED, make a single retry - attempt. Timing out the NNTP link is less painful this way. - -2001-07-02 Peter Williams - - * README (Introduction): Add comment noting that Camel actually - exists now :-) - -2001-07-02 Dan Winship - - * camel-session.c (camel_session_get_filter_driver): new method to - get an application-initialized filter driver. - - * camel-filter-driver.c (camel_filter_driver_new): Remove the - get_folder function and data args from here... - (camel_filter_driver_set_folder_func): ...and add this function to - set/change them. - - * providers/imap/camel-imap-folder.c (camel_imap_folder_new): If - this folder is INBOX and we're filtering INBOX, set a flag on the - folder for later. - (imap_update_summary): Add another argument (GPtrArray *recents), - and if it's non-NULL, add the uids of any \Recent new messages to - it. - (camel_imap_folder_changed): If doing filtering in this folder, - create a recents array and pass it to imap_update_summary. Then - get a filter driver and use it to filter the recent messages. - - * providers/imap/camel-imap-summary.h: - * providers/imap/camel-imap-utils.c (imap_parse_flag_list): Add - support for the \Recent flag. - - * providers/imap/camel-imap-provider.c (imap_conf_entries): enable - the "filter" option. - - * camel-types.h: add CamelFilterDriver typedef here - -2001-07-02 Not Zed - - * camel-lock-client.c (camel_lock_helper_init): properly return - error if we can't create pipes. - - * camel-folder-summary.c (summary_build_content_info): re-enable - html indexing. - - * camel-mime-filter-html.c: Completely re-implemented using a - custom parser. - -2001-07-02 Dan Winship - - * tests/misc/url.c (main): Change a camel_exception_clear to - camel_exception_init to fix a sometimes-crash - -2001-06-29 Jeffrey Stedfast - - * camel-mime-utils.c: Added Originator: header as a header to look - for when looking for the mailing list. - - * tests/mime-filter/Makefile.am: Build the test-crlf test program. - - * tests/mime-filter/test-crlf.c: New test suite for the crlf - filter. - - * camel-mime-filter-crlf.c (filter): Fixed to correctly encode and - decode dots. - -2001-06-28 Peter Williams - - * camel-mime-filter-stripheader.c: New file. Filter that strips a - header from mime output. - - * camel-mime-filter-stripheader.h: New file. Header for the above. - - * providers/smtp/camel-smtp-transport.c (smtp_data): Use the - stripheader filter to remove the "Bcc" header. - - * Makefile.am: Add the stripheader files. - - * tests/lib/Makefile.am (INCLUDES): Get this to compile again. - - * tests/mime-filter/test-stripheader.c: New file. Test suite for - the CamelMimeFilterStripHeader. - - * tests/mime-filter/Makefile.am: New test section: mime filters. - -2001-06-28 Jeffrey Stedfast - - * camel-mime-utils.c (header_decode_param_list): Fix a memory - leak. Also if the decoded value is NULL, that means it wasn't - encoded so we don't want to toss the old value. - (header_param_list_format_append): Correctly wrap long parameter - values according to rfc2184. - -2001-06-28 Dan Winship - - * providers/imap/camel-imap-folder.c (imap_refresh_info): If the - folder is frozen, don't refresh, just record that we need to do it - later. - (imap_append_online): If the APPEND doesn't trigger an immediate - EXISTS response (because the folder isn't the selected folder, or - because the server doesn't do that until the next command), call - imap_refresh_info on the folder. - (imap_copy_online): Likewise. (Replacing the unconditional NOOP - that was there before, which absolutely killed filter performance - by forcing the IMAP provider to switch back and forth between - folders after every copy or move.) - (imap_thaw): If the folder needs a refresh, do it. - - * camel-folder.c (camel_folder_is_frozen): New method - -2001-06-27 Jeffrey Stedfast - - * camel-transport.c (camel_transport_init): Initialize the private - send_lock. - (camel_transport_finalize): Free the private send_lock. - (camel_transport_get_type): Set the init and finalize functions. - (camel_transport_send): Lock the transport. - (camel_transport_send_to): Same. - - * camel-private.h: Add CAMEL_TRANSPORT_(UN)LOCK macros. - -2001-06-27 Jeffrey Stedfast - - * tests/folder/test9.c (main): Updated to match the current API. - - * tests/folder/test3.c: #include since we use - gtk_init(). - - * camel-internet-address.c - (camel_internet_address_encode_address): Use the new - header_address_fold. - - * camel-mime-utils.c: Removed some old #if 0'd code of mine. - (rfc2047_encode_word): If enclen is 0, don't write an encoded word - token (=?iso-8859-7?Q??= would be an invalid token). - (header_address_fold): New function to wrap address headers - - header_fold() was force-wrapping rfc2047 encoded words which was - making the test suite fail. The *real* solution, however, is to - not create rfc2047 encoded words longer than 72 chars. - -2001-06-26 Jeffrey Stedfast - - * camel-filter-driver.c (open_folder): Since we want an error - opening a folder to result in the message being copied to Inbox - (assuming no other filters get a chance to `move` it), don't - record any exceptions that may occur in this function. - -2001-06-26 Dan Winship - - * providers/imap/camel-imap-folder.c (camel_imap_folder_selected, - imap_append_offline, imap_append_online, - camel_imap_folder_changed): lock the cache around accesses - - * providers/imap/camel-imap-store.c (get_folder_online): ref the - newly-created folder (as current_folder) before calling - camel_imap_folder_selected, in case that needs to do something - that causes another folder to become current... - - * camel-service.c (camel_service_get_url): D'oh. - s/FALSE/CAMEL_URL_HIDE_PASSWORD/ - -2001-06-25 Jeffrey Stedfast - - * camel-filter-search.c (get_source): g_strdup() the message - source here or we will have problems later when we go to free the - result ;-) - -2001-06-25 Dan Winship - - * providers/imap/camel-imap-store.c (try_auth): Fix this: IMAP - doesn't allow an extra argument to AUTHENTICATE to avoid a useless - round trip like some other SASL bindings do. - - * providers/imap/camel-imap-command.c (imap_read_response): Deal - with IMAP servers that (incorrectly) return "+\r\n" rather than - "+ \r\n" for an empty continuation response. - (camel_imap_response_extract_continuation): Likewise. - -2001-06-21 Jeffrey Stedfast - - * camel-mime-utils.c (word_types_compatable): New function that - decides if 2 word types are mergeable. An atom and a qstring are - mergeable; 2 qstrings are mergeable; and 2 encoded words are - mergeable. - (header_encode_phrase_merge_words): If 2 words are merged, the new - word type is the MAX of the combined types. This means that if we - merge a qstring and an atom, the resulting word type is a - qstring. - - * camel-internet-address.c (internet_format): - s/g_string_sprintfa/g_string_append since this makes more sense in - this particular case. - (internet_encode): Same here. - -2001-06-21 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_send): Use - camel_address_length() rather than casting and accessing data - members. - -2001-06-20 Jeffrey Stedfast - - * camel-mime-utils.c (header_raw_check_mailing_list): If the first - char of the mailing-list name is '<', chop it off to make Ettore - happy. Fixes bug #2153. - -2001-06-19 Not Zed - - * camel-lock-helper.c (unlock_id): Fixed a bug when not running - setuid it wouldn't unlock. - - * camel-movemail.c (camel_movemail): use new - locking daemon, also return an error code. - -2001-06-18 Jeffrey Stedfast - - Note: Except for the info_free(), the NULL checks are - g_return's. I felt that since g_free() handles NULL that our - _free() functions should also. - - * camel-folder.c (camel_folder_change_info_free): Check to make - sure that the info pointer isn't NULL. - (camel_folder_change_info_change_uid): Same. - (camel_folder_change_info_changed): Same. - (camel_folder_change_info_remove_uid): Same. - (camel_folder_change_info_add_uid): Same. - (camel_folder_change_info_build_diff): Same. - (camel_folder_change_info_cat): Same. - (camel_folder_change_info_add_source): Same. - (camel_folder_change_info_add_source_list): Same. - (camel_folder_change_info_add_update): Same. - (camel_folder_change_info_add_update_list): Same. - -2001-06-18 Dan Winship - - * tests/stream/Makefile.am (LDADD): - * tests/smime/Makefile.am (LDADD): - * tests/misc/Makefile.am (LDADD): - * tests/message/Makefile.am (LDADD): - * tests/folder/Makefile.am (LDADD): Remove DB3_LDADD - - * Makefile.am (install-exec-local): Set camel-lock-help setgid or - setuid as needed - -2001-06-18 Not Zed - - * camel-folder-summary.c - (camel_folder_summary_info_new_from_parser): Only create a missing - uid if we have indexing turned on. - - * camel-lock-helper.c (setup_process): Function to setup - process/sanity/security checks. Change to the real uid as soon as - we can. - (lock_path): First try to lock as the real uid, if that fails, try - the root uid. - (unlock_id): Unlock as the uid we created the lock as. - - * Makefile.am (INCLUDES): Added -DCAMEL_SBINDIR for lock helper - location. - - * providers/local/camel-spool-folder.c (spool_lock): Implemented, - using lock helper locking. Need to work out if the locking - requires a root created lock? - (spool_unlock): Likewise. - -2001-06-15 Not Zed - - * camel-lock-helper.c: Setuid Lock helper process. Creates and manages - .locks, keeping them active, removing them, etc. What real perms it - needs is a little system dependent. - -2001-06-14 Not Zed - - * providers/local/camel-maildir-store.c (get_folder_info): Implement. - (scan_dir): Does the work of scanning for maildir directories. - -2001-06-13 Not Zed - - * providers/local/camel-spool-store.c (get_folder_info): - Implemented, just returns a hardcoded INBOX folder. - (free_folder_info): implemented, free's the 1 possible level of - folder info. - - * providers/local/camel-spool-folder.c - (camel_spool_folder_construct): Set the real unread message - count on the folder_created thing. - -2001-06-15 Dan Winship - - * providers/imap/camel-imap-message-cache.c - (camel_imap_message_cache_max_uid): Return the largest real UID in - the cache (as an integer). Eventually to be used for an - optimization in the new-message fetch code. - (cache_put): Keep track of max_uid. - -2001-06-14 Jeffrey Stedfast - - * camel-mime-utils.c: Added Mailing-List header regex so that we - can do mlist magic on that header. - -2001-05-28 Jeffrey Stedfast - - * camel-mime-utils.c (header_decode_param): Properly handle - correct and incorrect (for the common case, ie Outlook and - Netscape/Mozilla) rfc2184 values. - (header_decode_rfc2184_param): Get the param name and see if we - should expect a rfc2184 parameter value. - (rfc2184_decode): Decode a rfc2184 value. - (hex_decode): hex decode a string. - (header_decode_param_list): Handle rfc2184 encoded parameters (ie - parameters that have been split and perhaps encoded). - (header_param_list_format_append): Encode the value before seeing - if it will fit on the line. If the value does get encoded, be sure - to put a '*' before the equal-sign. - (header_encode_param): New function to rfc2184 encode a parameter - value (maybe it should be renamed?) - -2001-06-14 Jeffrey Stedfast - - * camel-mime-part.c (init_header_name_table): Don't try to format - the Reply-To header - we don't want to wrap the reply-to address. - -2001-06-12 Not Zed - - * providers/local/camel-spool-*.[ch]: A new provider, for spool - mailboxes. Mostly a cut and paste of the mbox code, but not a - subclass CamelLocal*. Not tested a lot, doesn't lock yet, use - with extreme caution. - - * tests/lib/folders.c (test_folder_message_ops): Added spool arg, - spool folders can't be deleted, renamed, etc. - (test_folder_basic): Same. - - * tests/folder/test2.c (main): Added checks for spool type. - - * tests/[message|stream|folder|misc|smime]/Makefile.am (LDADD): - Added db3 flags, so make check compiles, doesn't run though. - -2001-05-24 Not Zed - - * providers/local/camel-local-provider.c - (camel_provider_module_init): Added spool provider. - -2001-06-07 Jon Trowbridge - - * camel-filter-driver.c (camel_filter_driver_filter_folder): Add a - separator between the service url and the folder name, if needed. - - * camel-filter-driver.c (camel_filter_driver_filter_mbox): Added - an argument, so that the original source URI of the mbox can be - passed in. This is needed because this function is called - post-movemail, so we are never reading from the original mbox - anymore. Without the original mbox URI, the X-Evolution-Source - tag gets set incorrectly and filter-on-source will fail to work. - (camel_filter_driver_filter_message): Also take an extra arg - for the original source URI. It is the original URI, not the - source URI, that is used for filtering and for setting the - X-Evolution-Source tag. - -2001-06-05 Dan Winship - - * providers/imap/camel-imap-folder.c (imap_rescan): Don't fetch - the UID and FLAGS of messages we don't know about yet, since - they'll just get discarded. - -2001-06-01 Jeffrey Stedfast - - * tests/smime/pgp.c: Fix to not get into a recursive loop in - get_type(). - - * tests/smime/pgp-mime.c: Same. - -2001-05-31 Jeffrey Stedfast - - * camel-smime-context.c: Numerous fixes to get it to compile. - - * camel.h: Added camel-cipher-context.h, camel-cms-context.h, - camel-smime-context.h, and camel-smime-utils.h - - * camel-cms-context.[c,h]: New virtual class for manipulating - cryptographic message syntax messages (like S/MIME). - - * camel-smime-context.[c,h]: Modified to inherit from the - CamelCMSContext class rather than the CamelCipherContext class. - - * camel-smime.[c,h]: Removed - just use camel-smime-context - directly. - - * camel-smime-utils.[c,h]: New source files. Moved the 2 useful - functions from camel-smime.[c,h] into here. - -2001-05-30 Dan Winship - - * camel-charset-map.c: Redo the BUILD_MAP code to not depend on - libunicode. Now it only generates a map of "popular" 8bit - encodings. (It's not worthwhile to support obscure encodings, - because any mailer that supports them will support UTF8 too. And - Chinese and Japanese use mostly the same UTF8 characters so you - need to decide between those encodings based on the locale or - the charset of the message you're replying to or the input - method you used. So this is sufficient for camel_charset_best's - use.) - - * camel-charset-map-private.h: Regenerated. - - * camel.c (camel_shutdown): Move #ifdefs around to prevent a - warning. - -2001-05-29 Dan Winship - - * camel-disco-diary.c: Code for logging and replaying offline - operations. - - * camel-disco-store.c (disco_construct): Set disco->status here - (where we can base it on the session's offline status) rather than - at init time. - (disco_connect): If we connect online and have a non-empty diary, - switch to RESYNCING mode and replay the diary to the server. - (disco_get_folder, disco_get_folder_info): Add _resyncing - variants. - - * camel-disco-folder.c (disco_sync, disco_expunge_uids, - disco_append_message, disco_copy_messages_to, - disco_move_messages_to): Add _resyncing variants to switches. - (disco_expunge_uids, disco_append_message, disco_copy_messages_to, - disco_move_messages_to): Remove #ifdef'ed out diary code: let the - provider do it. - (disco_append_message): Redo the append methods to no longer - return the UID, since we're no longer doing the logging from here. - - * providers/imap/camel-imap-store.c (imap_connect_online, - imap_connect_offline): Create a CamelDiscoDiary. - (imap_disconnect_offline): And free it. - - * providers/imap/camel-imap-folder.c (camel_imap_folder_selected): - If RESYNCING, don't do any sort of checking that the remote folder - matches the summary, beyond making sure that the UIDVALIDITY is - correct. - (imap_rescan): Add a missing camel_folder_summary_info_free when - removing a UID from the summary. - (imap_expunge_uids_offline): Implement. Fairly simple. - (imap_expunge_uids_resyncing): Implement. If the store supports - UIDPLUS, we can just use imap_expunge_uids_online. If not, we need - to temporarily undelete any messages marked deleted on the server - that aren't supposed to get expunged. - (imap_append_offline): Implement, using cache and summary - operations, and triggering the folder_changed event by hand. - (imap_append_resyncing): Implement. Redo imap_append_online a bit - in the process to make them able to share more code. - (imap_copy_offline): Implement. - (imap_copy_online): Move parts of this out into a helper. - (imap_copy_resyncing): Implement. In most cases this is just like - imap_copy_online, but if you are copying a message that was itself - copied or appended into the folder, and the server doesn't do - UIDPLUS, it will be necessary to replace at least part of the copy - operation with one or more appends. - - * providers/imap/camel-imap-command.c (imap_read_response): Don't - record the current folder in the response when in RESYNCING mode. - (This means that EXISTS and EXPUNGE responses won't be processed, - which is needed because the summary may not match the folder at - this point.) - (imap_read_response): On error, call - camel_imap_response_free_without_processing, not - camel_imap_response_free. - - * providers/imap/camel-imap-utils.c (imap_uid_array_to_set): Make - this work better when operating on UIDs that aren't in the summary. - - * providers/imap/camel-imap-summary.c - (camel_imap_summary_add_offline): New routine used by - imap_append_offline and imap_copy_offline to create new summary - entries. - -2001-05-28 Jeffrey Stedfast - - * camel-mime-utils.c (header_set_param): Use g_strcasecmp() - because some systems don't have strcasecmp(). Also, when removing - a param, make sure to free the param->name too. - -2001-05-27 Dan Winship - - * tests/lib/messages.c (test_message_read_file): Fix an fd leak - - * tests/lib/session.c, tests/lib/session.h: a CamelSession - subclass for the test programs. - - * tests/lib/Makefile.am: include session.[ch] - - * tests/folder/test*.c: Use a CamelTestSession from libcameltest - instead of cut+pasting everywhere. - - * tests/misc/url.c (main): Update for a camel_url_new change at - some point. - - * tests/*/.cvsignore: Add stuff. - - * camel-mime-utils.c (rfc2047_encode_word): Fix a silly ==/!= - mixup. - -2001-05-26 Dan Winship - - * providers/imap/camel-imap-folder.c: Add a "need_rescan" flag - saying if we want to rescan the entire folder for flag changes - next time it's selected. - (camel_imap_folder_init): Set need_rescan TRUE. - (camel_imap_folder_selected): If need_rescan is TRUE, call - imap_rescan. - (imap_refresh_info): Only do a full rescan if need_rescan is TRUE. - Otherwise just do a NOOP, making this a MUCH more lightweight - operation. Also, don't call imap_rescan directly if the folder - isn't selected, since that could end up causing the folder to be - scanned *twice* (imap_rescan -> camel_imap_command -> - camel_imap_folder_selected -> imap_rescan). - (imap_rescan): Set need_rescan FALSE. - (imap_sync_online): Don't NOOP if no changes were pushed: the - caller will call refresh_info if it wants to poll for changes. - Fixes evolution-mail doing lots of unnecessary extra work at - quit time. - - * providers/imap/camel-imap-store.c (refresh_folder_info): Set - need_rescan on each folder before calling refresh_info. - -2001-05-25 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_auth): Oops. Use a - strNcmp to make sure the response begins with a 334 code, not a - strcmp. Duh. - - * providers/local/camel-maildir-folder.c (maildir_append_message): - remove the summary info so we are not out-of-sync with the maildir - folder. - - * providers/local/camel-mh-folder.c (mh_append_message): remove - the summary info so we are not out-of-sync with the mh folder. - - * providers/local/camel-mbox-folder.c (mbox_append_message): - remove the summary info so we are not out-of-sync with the mbox. - -2001-05-24 Jeffrey Stedfast - - * camel-smime-context.c (camel_smime_context_new): Oops, I spelled - the get-default-db function name wrong. - -2001-05-23 Jeffrey Stedfast - - * providers/local/camel-local-folder.c - (camel_local_folder_construct): s/folder_deleted/folder_created - - result of a bad copy/paste. - - * providers/imap/camel-imap-search.c (imap_body_contains): - Optimize the match "" case. - -2001-05-21 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (get_folder_info_online): - Store the CamelFolderInfo tree that was returned from - camel_folder_info_build() in a new variable, 'tree', rather than - 'fi' since we later use 'fi' when syncing folders. Not only does - this fix a memory leak, but it also fixes the bug where the user - would only see the last folder in the folder list and/or it's - subfolders. - -2001-05-16 Jeffrey Stedfast - - * camel-session.c (camel_session_forget_password): The service can - be NULL here too, thanks to Wayne Davis for pointing this out. - - * camel-smime-context.c (camel_smime_context_new): We don't need - to be passed the certdb path anymore. - -2001-05-16 Dan Winship - - * camel-medium.c (camel_medium_get_headers): New function to - return an array of all headers. - (camel_medium_free_headers): And free them. - - * camel-mime-part.c (get_headers, free_headers): Implement this - for CamelMimePart. (Works for CamelMimeMessage too.) - -2001-05-15 Jeffrey Stedfast - - * camel-smime-context.c (camel_smime_context_finalise): Don't - close or free (it wasn't allocated) the certdb. - (camel_smime_context_new): If we get a NULL certdb handle, then - don't bother trying to create a new certdb handle since NSS_Init* - should have done that. - -2001-05-15 Jeffrey Stedfast - - * Makefile.am: Don't use EXTRA_GNOME_*, use the new CAMEL_* - variables so we don't link in tons of extra cruft that we don't - need. - - * tests/smime/pkcs7.c: Added to the test suite - tests the S/MIME - pkcs7 functions. - -2001-05-14 Jeffrey Stedfast - - * camel-smime-context.c: Lots of fixes to get this to compile. - - * camel-smime.c (camel_smime_part_verify): Updated to pass in a - hash argument to camel_smime_verify(). - - * camel-pgp-mime.c (camel_pgp_mime_part_verify): Update according - to the changes in the context API. - - * camel-pgp-context.c (pgp_verify): Updated to take a - CamelCipherHash argument. - - * camel-cipher-context.c (camel_cipher_verify): Now takes a hash - argument since the S/MIME code needs this. - - * Makefile.am: Add camel-smime-context.[c,h] and camel-smime.[c,h] - to the build. - - * camel-smime.[c,h]: New source files for manipulating S/MIME - message parts. - -2001-05-14 Jon Trowbridge - - * camel-search-private.c (utf8_get): Replicate the semantics of - the libunicode utf8 functions by returning NULL in the arg - on invalid utf8. - - * camel-pgp-context.c (pgp_verify): Check for valid utf8, - terminate loop if something looks wrong. - - * camel-mime-utils.c (header_encode_phrase_get_words): Properly - check for invalid utf8. - (header_encode_string): Properly check for invalid utf8. - - * camel-charset-map.c (camel_charset_step): Properly check for - invalid utf8. - -2001-05-14 Jeffrey Stedfast - - * tests/folder/test9.c: - * tests/folder/test8.c: - * tests/folder/test7.c: - * tests/folder/test6.c: - * tests/folder/test5.c: - * tests/folder/test4.c: - * tests/folder/test3.c: - * tests/folder/test2.c: - * tests/folder/test1.c: - * tests/smime/pgp-mime.c: - * tests/smime/pgp.c: Subclass CamelSession since we can no longer - specify the passwd callback any other way and update code - accordingly. - -2001-05-11 Dan Winship - - * camel-mime-utils.c (header_location_decode): Decode - Content-Location, either correctly or Netscape-generated-brokenly. - - * camel-mime-part.c (camel_mime_part_set_content_location, - camel_mime_part_get_content_location, etc): Deal with - Content-Location header. - -2001-05-11 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_auth): Don't check - the initial auth response until we get into the while-loop - otherwise we have problems if the SASL mechanism supported a - client initiated challenge (like PLAIN and LOGIN do). - -2001-05-11 Dan Winship - - * camel-stream-null.c (camel_stream_null_new): Make this return - CamelStream * (like the other stream new functions) instead of - CamelStreamNull * - -2001-05-10 Chris Toshok - - * camel-tcp-stream-ssl.c (stream_connect): call SSL_Enable after - the SSL_ImportFD and before PR_Connect. Otherwise, NSS aborts - during the connect. - -2001-05-10 Jeffrey Stedfast - - * camel-session.c (camel_session_get_password): Don't abort if the - Service is NULL, this is perfectly valid for cipher contexts. - -2001-05-09 Peter Williams - - * providers/imap/camel-imap-folder.c (imap_move_messages_to): Pass - appropriate parameters to CF_CLASS and add comment explaining why - my initial attempt at a solution didn't work. - -2001-05-09 Dan Winship - - * camel-disco-store.c (camel_disco_set_status): Set the - disconnected status. - (camel_disco_store_can_work_offline): Return whether or not a - given CamelDiscoStore can work offline or not. - - * camel-disco-folder.c (camel_disco_folder_cache_message): - Explicitly tell a folder to cache a message. (Better than using - get_message, because for IMAP that doesn't guarantee you'll get - all the message parts.) - (camel_disco_folder_prepare_for_offline): Prepare a folder for - offline use by caching all messages meeting given search criteria - (and doing anything else the particular folder implementation - needs). - - * camel-session.c (camel_session_set_online, - camel_session_is_online): A session-wide online/offline toggle. - (camel_session_init): Set online to TRUE. - - * providers/imap/camel-imap-store.c (can_work_offline): - Implementation of CamelDiscoStore::can_work_offline. (Checks that - the store has been used online at least once.) - (imap_get_folder_online, imap_get_folder_offline): Deal with - request for "inbox" properly. ("Don't you mean... 'INBOX'?"). - - * providers/imap/camel-imap-folder.c (imap_cache_message): - Implementation of CamelDiscoFolder::cache_message. - - * camel.h: Add camel-disco-store.h and camel-disco-folder.h - -2001-05-09 Jeffrey Stedfast - - * camel-mime-part.c (camel_mime_part_set_content_id): Wrap the - content-id with <>'s. - -2001-05-04 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (connect_to_server): Add - support for using OpenSSL. - - * camel-remote-store.c (remote_connect): Add support for using the - OpenSSL implementation. - - * camel-tcp-stream-ssl.c (ssl_bad_cert): Hmmmm, don't pass in a - NULL as the last argument to alert_user - prototype doesn't take - that argument anymore? - - * camel-tcp-stream-openssl.c (camel_tcp_stream_openssl_finalize): - (ssl_verify): Use a global hash table to try and lookup the - CamelTcpStreamOpenSSL object given the ssl context since OpenSSL - doesn't think one needs to pass data around, we should all be - living in a world of global variables, duh! - -2001-05-06 Dan Winship - - * Makefile.am (libcamelinclude_HEADERS): Fix another build - problem. (Um, anyone else could have done this...) - -2001-05-04 Dan Winship - - * providers/imap/camel-imap-store.c (get_folder_online): Fix up - refcounting on current_folder. - - * camel-disco-folder.c, camel-disco-store.h: Remove - CamelDiscoDiary refs that weren't supposed to escape yet. - -2001-05-03 Dan Winship - - * camel-disco-store.c: new abstract class for disconnectable - remote stores - - * camel-disco-folder.c: new abstract class for folders on - disconnectable stores. - - * Makefile.am: Add camel-disco-folder.[ch] and - camel-disco-store.[ch]. - - * providers/imap/camel-imap-store.c: Make this a subclass of - CamelDiscoStore, and fix up the offline interfaces for the changes - since they were first written (particularly the fact that some - IMAP stores don't just use subscribed folders). - - * providers/imap/camel-imap-folder.c: Make this a subclass of - CamelDiscoFolder, although most ops still fail in disconnected - mode. - - * camel-store.c (camel_store_get_folder_info): Change gboolean, - gboolean, gboolean to guint32 in the prototype for this function. - - * providers/local/camel-local-store.c (get_folder_info): Update - for prototype change. - -2001-05-02 Dan Winship - - * providers/imap/camel-imap-store.h: Clean this up a bit. Add a - "tag_prefix" member. Move "useful_lsub" into capabilities. - - * providers/imap/camel-imap-store.c (camel_imap_store_init): - Initialize the tag_prefix, based on a static variable. - - * providers/imap/camel-imap-command.c (camel_imap_command): Use - the store's tag_prefix character rather than "A" at the start of - the tag. Makes the verbose debug output easier to parse when - connected to multiple IMAP servers. (Well, unless you're connected - to more than 26 servers...) - - * providers/imap/camel-imap-utils.c (imap_uid_array_to_set): Fix - this up... it was losing count in some cases and giving a more - verbose answer than it needed to. - - * providers/pop3/camel-pop3-store.c: Rescue the KPOP code from bit - rot. - -2001-05-01 Dan Winship - - * providers/imap/camel-imap-command.c (camel_imap_command): Redo - command locking. Since command_lock is recursive, we can just get - a lock here, and release it either on error, or when the caller - frees the response data. (This simplifies a lot of stuff, and - fixes some problems with camel_imap_folder_changed being called - without the command_lock locked because of the 2001-03-22 change.) - - (camel_imap_response_free): - (camel_imap_response_free_without_processing): - (camel_imap_response_extract): - (camel_imap_response_extract_continuation): These all take a - CamelImapStore now as well, to deal with locking. - - * providers/imap/camel-imap-private.h: Add - CAMEL_IMAP_STORE_ASSERT_LOCKED, which defaults to a noop, but can - be made to call e_mutex_assert_locked. - - * providers/imap/camel-imap-folder.c, camel-imap-search.c, - camel-imap-store.c: Simplify using new locking stuff. Add a few - CAMEL_IMAP_STORE_ASSERT_LOCKED checks. - -2001-05-01 Dan Winship - - Support the IMAP UIDPLUS extension (RFC 2359), which lets you - resync after disconnected operation more efficiently, but also - makes it possible to do appends and moves/copies more efficiently - now. - - * providers/imap/camel-imap-folder.c (imap_append_message): If the - server supports UIDPLUS, grab the APPENDUID response and cache the - message into the folder's message cache. - (imap_copy_messages_to): Likewise, for COPYUID, copy any message - parts we have cached between the source and destination folder - caches. - (imap_get_message): If the entire message is already in the cache, - just return that rather than building it from parts. - (imap_update_summary): Fetch just the "UID FLAGS RFC822.SIZE" of - the new messages first, then only fetch the headers for messages - where we don't already have the headers cached. - - * providers/imap/camel-imap-message-cache.c: Add gtk-doc comments. - (cache_put): Fix refcounting stuff here. - (camel_imap_message_cache_insert_stream, - camel_imap_message_cache_insert_wrapper): New. - (camel_imap_message_cache_get): Fix a bug here so the memory - caching actually works. - (camel_imap_message_cache_copy): New routine, used by - imap_copy_messages_to. - - * providers/imap/camel-imap-utils.c (imap_uid_set_to_array): - Inverse operation of imap_uid_array_to_set. Used to parse COPYUID - response. - -2001-04-30 Dan Winship - - * providers/imap/camel-imap-utils.c (imap_uid_array_to_set): - New-and-improved version of get_uid_set() from - camel-imap-folder.c. Looks at the summary as it goes so that if - you ask for messages 5, 6, 8, and 9, and there is no message 7, - then you get "5:9" instead of "5:6,8:9" - - * providers/imap/camel-imap-folder.c (imap_copy_messages_to): Use - imap_uid_array_to_set() rather than get_uid_set(). - (get_uid_set): Gone - -2001-04-27 Dan Winship - - * camel-session.c: Redo this a lot so that instead of having a - class full of callbacks, we have a subclassable class. Also, - replace the increasingly horrifying - camel_session_query_authenticator with three new routines, - camel_session_get_password, camel_session_forget_password, and - camel_session_alert_user. - - * camel-pgp-context.c: - * camel-pkcs7-context.c: - * camel-smime-context.c: - * providers/imap/camel-imap-store.c: - * providers/pop3/camel-pop3-store.c: - * providers/smtp/camel-smtp-transport.c: - Use camel_session_get_password / camel_session_forget_password. - - * camel-tcp-stream-ssl.c (ssl_bad_cert): Use - camel_session_alert_user. - -2001-04-26 Jeffrey Stedfast - - * camel.c (camel_init): Automagically call camel_shutdown() - atexit() ;-) - (camel_init): Also initialize NSS databases as read/write for - S/MIME and if NSS fails to init, try initializing with volatile - databases. - - * camel-file-utils.h: #include for off_t. - -2001-04-26 Dan Winship - - * camel-file-utils.c: New file, with the int, string, time_t, and - off_t encode/decode routines from camel-folder-summary.c moved - here and renamed, for the enjoyment of non-CamelFolderSummary - subclasses. - - * Makefile.am (libcamel_la_SOURCES): Add camel-file-utils.c - (libcamelinclude_HEADERS): and camel-file-utils.h - - * camel-folder-summary.c: Remove functions that were moved to - camel-file-utils.c, update uses of them for the new names. - (camel_folder_summary_{en,de}code_token are still here.) - - * providers/local/camel-mbox-summary.c: Use camel_file_util_* - names - - * providers/imap/camel-imap-summary.c: Use camel_file_util_* names - - * providers/imap/camel-imap-store.c (imap_store_setup_online, - imap_store_setup_offline): Use camel_file_util_* names, which - makes much more sense since this isn't folder summary stuff. - -2001-04-26 Dan Winship - - * Makefile.am (INCLUDES): Remove UNICODE_CFLAGS (and some other - stuff that's redundant with EXTRA_GNOME_CFLAGS) - (libcamel_la_LIBADD): Replace UNICODE_LIBS with GAL_LIBS. - - * camel-search-private.c: - * camel-pgp-context.c: - * camel-mime-utils.c: Use gunicode interfaces rather than - libunicode. - - * camel-charset-map.c: Use gunicode rather than libunicode. (The - charmap-regen code still depends on libunicode though.) - - * camel-mime-filter-charset.h: - * tests/message/test2.c (convert): Use iconv rather than - unicode_iconv. - - * providers/smtp/Makefile.am (libcamelsmtp_la_LIBADD): - * providers/pop3/Makefile.am (libcamelpop3_la_LIBADD): - * providers/local/Makefile.am (libcamellocal_la_LIBADD): Remove - UNICODE_LIBS. - - * camel.c (camel_init): Remove call to unicode_init. - - * camel-mime-parser.c: Remove unused unicode.h include. - -2001-04-26 Dan Winship - - * camel-service.c (get_host): Use e_gethostbyname_r. - (camel_service_gethost): Remove unused var. - -2001-04-26 Not Zed - - * Applied jacob's patches for e-poolv stuff. - -2001-04-23 Jeffrey Stedfast - - * camel.h: Add camel-vee-folder.h and camel-digest-folder.h - - * camel-digest-folder.[c,h]: New class that can be used to browse - a multipart/digest message as if it were a CamelFolder. - -2001-04-22 Jeffrey Stedfast - - * camel-pgp-context.c (pgp_verify): Oops, don't use the return - value of iconv() as a string length, it only tells us the number - of non-reversable character conversions. This fixes it so we - actually see the gpg output in the message viewer. - -2001-04-23 Mikael Hallendal - - * providers/nntp/Makefile.am (INCLUDES): - Changed GTK_INCLUDEDIR to EXTRA_GNOME_CFLAGS. - -2001-04-20 Jeffrey Stedfast - - * camel-smime-context.c (smime_sign): Implemented using the - secmime.h convenience functions. - (smime_clearsign): We just error our here, there is no clearsign - for smime. - (smime_verify): Copied code over from the pkcs7 verify - same - state, ugly and unknown :-) - (smime_encrypt): Implemented using the secmime.h convenience - functions. - (smime_decrypt): Same as the code in pkcs7-context. - -2001-04-19 Jeffrey Stedfast - - * camel-pkcs7-context.c (pkcs7_sign): Implemented. - (pkcs7_clearsign): Implemented. - (get_zero_len_passwd): Convenience function to try a 0-length key - on the certificate db - if this works then there is no need to - prompt the user. - (get_password): Callback to get the password. - (camel_cipher_hash_to_nss): Convenience function to convert a - CamelCipherHash to an NSS HASH_HashType. - (nss_hash_to_sec_oid): Converts a HASH_HashType to a SecOidTag. - (pkcs7_digest): Digest function for use with pkcs7_sign(). - (sign_encode_cb): Callback to write the signed data to the output - stream. - (pkcs7_verify): Hacked on a bit more but am still a bit on the - confused side. This might work but I wouldn't hold my breath. The - sign/clearsign should be close if not correct, but this one...god - only knows. - (pkcs7_decrypt): Implemented. - (pkcs7_encrypt): Implemented (mostly, still need to handle when - 'sign' is TRUE). - -2001-04-18 Dan Winship - - * providers/imap/camel-imap-store.c (camel_imap_store_finalize): - Free base_url and storage_path. - - * providers/pop3/camel-pop3-store.c (finalize): Free the - implementation string. - (camel_pop3_command): Clarify documentation to mention that - @ex isn't set (and *@ret is) on CAMEL_POP3_ERR. - (connect_to_server): Set @ex properly on CAMEL_POP3_ERR. - - * providers/pop3/camel-pop3-folder.c (pop3_refresh_info, - pop3_get_message): Set @ex properly on CAMEL_POP3_ERR. - -2001-04-17 Jeffrey Stedfast - - * camel-pkcs7-context.[c,h]: New source files to handle Pkcs7 - encryption, decryption, signing, and verifying. Not yet - complete. I'm sensing this is going to take a while seeing as how - NSS is just so well documented. - -2001-04-17 Dan Winship - - * camel-filter-driver.c (camel_filter_driver_filter_message): Fix - a memory leak in the error case. - -2001-04-16 Jeffrey Stedfast - - * providers/local/camel-mbox-summary.c (summary_rebuild): Don't we - want to tell where we are by using the start of the message? I - think this should be using camel_mime_parser_tell_start_from() - instead. Also divide by the size *before* multiplying by 100 so - that we don't overflow the int which was giving us negative values - for our progress status (oops). - -2001-04-16 Jeffrey Stedfast - - * camel-operation.c: Added a prototype for stamp(). - - * camel-charset-map.c (camel_charset_locale_name): #include - string.h so we don't get a warning about strchr being undefined - and also init charset to NULL. - - * camel-pgp-context.c (pgp_verify): Go back to doing the utf8 - conversion by hand so that we don't depend on gal. - - * Makefile.am: Remove the EXTRA_GNOME_CFLAGS include. - - * camel-store.c (camel_mkdir_hier): Convenience function that it - seems a number of camel-store implementations used gal for. - - * providers/nntp/camel-nntp-store.c (ensure_news_dir_exists): Lets - not depend on gal for just e_mkdir_hier() - use camel_mkdir_hier() - instead. - - * providers/nntp/camel-imap-store.c: Lets not depend on gal for - just e_mkdir_hier() - use camel_mkdir_hier() instead. - - * camel-session.c (camel_session_get_storage_path): Don't depend - on e_mkdir_heir() anymore, use the CamelStore version. - - * camel-folder-search.h: Removed gal dependency, why was this even - there in the first place? - - * providers/imap/camel-imap-folder.c: Don't need gal/util/e-util.h - here, so remove it. - - * string-utils.c (strstrcase): New function, well more like old - function brought back to life so we don't have to depend on gal. - - * providers/imap/camel-imap-store.c (imap_store_setup_online): Use - strstrcase rather than e_strstrcase so we don't depend on gal. - (get_unread_online): Same here. - - * providers/smtp/camel-smtp-transport.c (smtp_helo): Use - strstrcase. - -2001-04-15 Jeffrey Stedfast - - * camel-mime-utils.c (header_raw_check_mailing_list): regex - doesn't set errno and regcomp returns 0 on success and any other - value for an error (so don't *just* check for -1). - -2001-04-14 Jeffrey Stedfast - - * camel-cipher-context.c: Check to make sure the context is a - valid context in all the user functions. - -2001-04-13 Jon Trowbridge - - * providers/imap/camel-imap-store.c (imap_disconnect): - s/imap_store/store/, fixing a typo that was causing the build to - fail. - - * camel-filter-search.c (get_source): Make the (previously unused) - get-source command actually do the right thing, properly shrouding - any passed-in source and falling back to use the source attached - to the mime message. - -2001-04-13 Dan Winship - - * camel-object.c (camel_object_hook_event): - * camel-uid-cache.c (camel_uid_cache_get_new_uids): - * camel-url.c (camel_url_new_with_base): Plug leaks. - - * camel-remote-store.c (camel_remote_store_init): Don't - re-initialize the folders hash table. - - * providers/imap/camel-imap-store.c (imap_disconnect): Free - authtypes since they'll be re-read on re-connect. - (get_folder_info): Free folderinfos that we're discarding from the - list. - -2001-04-12 Jeffrey Stedfast - - * camel-pgp-context.c (camel_pgp_context_get_type): Oops, lets not - get into a recursive call here ;-) - - * tests/smime/pgp.c: Updated to reflect changes to the PGP code. - - * tests/smime/pgp-mime.c: Same. - -2001-04-12 Jeffrey Stedfast - - * camel-pgp-mime.c: Updated to reflect the few changes made to the - CamelPgpContext class. - - * camel-pgp-context.c: Updated to subclass of CamelCipherContext. - - * camel-cipher-context.[c,h]: New base class for - CamelPgpContext. Also contains the replacement for - CamelPgpValidity, CamelCipherValidity. - -2001-04-12 Dan Winship - - * camel-mime-filter-crlf.c (filter): Fix a pair of array bounds - reads noted by purify - -2001-04-12 Jeffrey Stedfast - - * camel.h: #include the pgp stuff. - -2001-04-12 Dan Winship - - * providers/imap/camel-imap-message-cache.c - (camel_imap_message_cache_remove): - * camel-url.c (camel_url_to_string): Plug memory leaks. - -2001-04-11 Dan Winship - - * providers/imap/camel-imap-utils.c (imap_parse_string_generic): - Simplify peterw's imap_is_atom_char fix. - -2001-04-11 Jeffrey Stedfast - - * tests/smime/Makefile.am: Added pgp-mime.c to the tests. - - * tests/smime/pgp-mime.c: Test suite for camel-pgp-mime.c functions. - - * Makefile.am: Add camel-pgp-mime.[c,h] to the build. - - * camel-pgp-mime.c: Made a number of fixes to get it to compile - and also fixed a few logic errors (mostly forgetting to reset - streams) so that it worked (thanks to the pgp-mime test program). - -2001-04-11 JP Rosevear - - * providers/imap/Makefile.am: user GNOME_INCLUDEDIR since gnome - files are included in the top level camel headers and the gtk - include dir is now versioned and such - - * providers/local/Makefile.am: ditto - - * providers/pop3/Makefile.am: ditto - - * providers/smtp/Makefile.am: ditto - - * providers/sendmail/Makefile.am: ditto - - * camel-service.c: use five arg version of gethostbyname_r if - appropriate - (camel_get_host_byname): check if msg->herr is non-zero instead of - checking if msg->hp is null since we may not always have msg->hp - -2001-04-11 Jeffrey Stedfast - - * camel-sasl-digest-md5.c (digest_response): Use - camel_charset_locale_name() to get the locale charset rather than - checking the CHARSET environment variable. This is a much less - ugly hack. Also: If we fail to be able to convert to UTF8, then - disavow all knowledge of the charset parameter. - - * camel-charset-map.c (camel_charset_locale_name): New function to - return the locale charset (or NULL if US-ASCII). - -2001-04-11 Jeffrey Stedfast - - * camel-pgp-context.c (camel_pgp_verify): Use - e_utf8_from_locale_string() rather than trying to do it manually - since Lauris's version works much better. - -2001-04-06 Jeffrey Stedfast - - * Makefile.am: Added camel-pgp-context.[c,h] to the build. Also - added tests/smime/pgp.c and Makefile.am - - * tests/smime/pgp.c: New test suite for PGP functions. - - * camel-pgp-context.c: Various fixes to get it to build. - -2001-04-07 Peter Williams - - * providers/imap/camel-imap-utils.c (imap_parse_string_generic): It - would be a good idea to recognize '\0'. Before, this code was running - off the ends of strings and intermittently coredumping (if it didn't - hit an imap_atom_char first) -- whoops! - -2001-04-05 Not Zed - - * merge from evolution-0-10-branch to evolution-0-10-merge-0 - -2001-04-03 Jeffrey Stedfast - - * Makefile.am: Added tests/ back in - - * camel-mime-utils.c (header_decode_text): Ignore whitespace - between encoded words (there were a few cases where it didn't - before). - (header_encode_string): Preserve whitespace between words that are - to be encoded by encoding them too. - (header_encode_phrase): Same here but with phrases. - -2001-04-03 Dan Winship - - * providers/imap/camel-imap-folder.c (imap_sync): If we don't - change any flags or expunge, send a NOOP to give the server a - chance to send EXISTS, etc, messages. - (imap_get_message): If the server_level < IMAP4rev1, always fetch - messages all-at-once, since they don't support the [#.MIME] - syntax. - (imap_update_summary): When reading message flags, set the - server_flags field as well, and don't overwrite any flags set by - camel_folder_summary_info_new_from_message. Might help with some - of the flag problems... - -2001-04-02 Dan Winship - - * camel-service.h: Remove the "quick_login" member, which is - unnecessary. - - * providers/smtp/camel-smtp-transport.c (smtp_auth): Remove the - references to quick_login and fix this to use the CamelSasl - interfaces correctly to do the same thing. - (connect_to_server): Split this out of smtp_connect - (smtp_connect): Use connect_to_server. When re-EHLO'ing after - auth, ignore errors. - (query_auth_types): Use connect_to_server rather than - smtp_connect, so it doesn't try to authenticate. Add LOGIN - authtype to the list of authtypes to check for. - - * providers/smtp/camel-smtp-provider.c - (camel_provider_module_init): Add LOGIN authtype to the authtypes - list explicitly. - - * camel-sasl.c (camel_sasl_authtype_list): Don't list LOGIN here: - it's not a real SASL authtype and is only used for SMTP. - - * camel-sasl-plain.c: - * camel-sasl-login.c: - * camel-sasl-kerberos4.c: - * camel-sasl-cram-md5.c: - * camel-sasl-anonymous.c: - * providers/pop3/camel-pop3-provider.c: Remove "quick_login" - argument from authtypes. - -2001-04-02 Gediminas Paulauskas - - * camel-filter-driver.c: marked missing report status' for translation. - -2001-04-02 Jeffrey Stedfast - - * camel-pgp-context.c (camel_pgp_sign): mutex lock & unlock the - context. - (camel_pgp_clearsign): Same. - (camel_pgp_verify): Same. - (camel_pgp_encrypt): Same. - (camel_pgp_decrypt): And finally here... - - * camel-pgp-context.h: Update the function prototypes to match - those found in camel-pgp-context.c. - - * camel-pgp-context.c: Updated. - - * camel-pgp-mime.c (camel_pgp_mime_part_sign): Implemented. - (camel_pgp_mime_part_verify): Implemented. - (camel_pgp_mime_part_encrypt): Implemented. - (camel_pgp_mime_part_decrypt): Implemented. - -2001-04-01 Jeffrey Stedfast - - * camel-sasl-login.[c,h]: New files to handle the LOGIN SASL - mechanism. - - * camel-sasl-plain.c: Removed the definition of - camel_sasl_login_authtype. - - * camel-sasl.c (camel_sasl_new): Oops. I thought LOGIN was an - alias to PLAIN. I was wrong. These two SASL objects have to be - separate. - - * providers/smtp/camel-smtp-transport.c (smtp_auth): Updated to - check for and use authmech->quick_login when available. - -2001-04-01 Jeffrey Stedfast - - * providers/pop3/camel-pop3-provider.c: Updated the authtypes here - too. - - * camel-sasl-plain.c: - * camel-sasl-anonymous.c: - * camel-sasl-digest-md5.c: - * camel-sasl-cram-md5.c: - * camel-sasl-kerberos4.c: Updated the authtype values. - - * camel-service.h: Added another field to CamelServiceAuthType - that specifies whether or not the mechanism supports "quick auth" - which means that the client can send the initial challenge in the - AUTH request. - - * camel-sasl.c (camel_sasl_new): Add support for LOGIN. - (camel_sasl_authtype_list): Here too. - (camel_sasl_authtype): And finally here. - - * camel-sasl-plain.c: Define camel_sasl_login_authtype. - - * providers/smtp/camel-smtp-transport.c (smtp_auth): Only unref - the SASL object if it exists. - -2001-03-30 Dan Winship - - * providers/pop3/camel-pop3-store.c (connect_to_server, - query_auth_types, pop3_connect): Move things around here to make - this all work right again (so you don't get prompted for a - password when checking the supported authtypes.) - -2001-03-30 Jon Trowbridge - - * camel-mime-message.c (camel_mime_message_set_source): Shrould - our source URL before putting it into X-Evolution-Source. - -2001-03-29 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (get_folder_info): Don't - blindly append "/INBOX", construct a CamelURL and set the path - that way. - (parse_list_response_as_folder_info): Don't blindly append - "/", construct a CamelURL and set the path that way - instead. - (get_folders_offline): And again here. - -2001-03-30 Not Zed - - * camel-service.c (camel_get_host_byname): Dont overwrite an - exception if we got one already. Added camel_operation status to - it, and comment out some debug. - -2001-03-29 Not Zed - - * providers/smtp/camel-smtp-transport.c (smtp_connect): Free host - name info when done ... blah blah. - - * camel-sasl-kerberos4.c (krb4_challenge): Free host name info - after we're done with it. - - * camel-sasl-digest-md5.c (digest_md5_challenge): Free host name - info after we're done with it. - - * camel-remote-store.c (remote_connect): Free the host name info - from get_host after we're finished with it. - - * camel-service.c (camel_get_host_byname): New function to - lookup a name, and still be cancellable. - (camel_free_host): And a function to free the structure - returned. - (camel_service_gethost): Call get_host_byname for this. - -2001-03-29 Jon Trowbridge - - * camel-filter-driver.c (camel_filter_driver_filter_message): Save - the source URL using camel_mime_message_set_source. - - * camel-mime-message.c (camel_mime_message_set_source): Renamed - camel_mime_message_set_identity to this. Sets the X-Evolution-Source - header. - (camel_mime_message_get_source): Returns the X-Evolution-Source - header. - -2001-03-29 Kjartan Maraas - - * broken-date-parser.c: #include , and - * broken-date-parser.h: Remove all includes but - * camel-address.h: Added #include - * camel-data-wrapper.c: Move system includes to the top. - * camel-data-wrapper.h: #include - * camel-exception.c: #ifdef HAVE_CONFIG_H - * camel-exception.h: Remove #include - * camel-filter-driver.c: #ifdef HAVE_CONFIG_H and move system - headers to top. Mark strings in camel_exception_set*() for i18n. - * camel-filter-driver.h: #include - * camel-filter-search.c: #ifdef HAVE_CONFIG_H - * camel-folder-search.c: #include - * camel-folder-search.h: Header shuffling - * camel-folder-summary.h: Same here - * camel-folder-thread.c: #ifdef HAVE_CONFIG_H - * camel-folder.c: Here too. - * camel-folder.h: #include - * camel-internet-address.c: Move system headers up - * camel-lock.c: #ifdef HAVE_CONFIG_H - * camel-medium.c: Same here - * camel-mime-filter-bestenc.c: Move system headers up - * camel-mime-filter-from.c: Same here - * camel-mime-filter-linewrap.c: And here - * camel-mime-filter.c: #include to fix warnings from new gcc - * camel-mime-filter.h: System headers moved up - * camel-mime-message.c: Here too. #ifdef HAVE_CONFIG_H added - * camel-mime-part-utils.c: #ifdef HAVE_CONFIG_H added - * camel-mime-part.c: Here too, and shuffle headers - * camel-mime-utils.c: #ifdef HAVE_CONFIG_H. Remove const from two - variables to remove warning. - * camel-mime-utils.h: Shuffle headers - * camel-movemail.c: #ifdef HAVE_CONFIG_H. Mark string in camel_exception_set - * camel-multipart.c: #ifdef HAVE_CONFIG_H. Added includes to remove - warnings from new gcc - * camel-object.c: #ifdef HAVE_CONFIG_H - * camel-object.h: Shuffle headers - * camel-operation.c: #ifdef HAVE_CONFIG_H - * camel-provider.c: #ifdef HAVE_CONFIG_H. Shuffle headers. Mark a string - * camel-remote-store.c: #ifdef HAVE_CONFIG_H - * camel-sasl-anonymous.c: #ifdef HAVE_CONFIG_H. #include - * camel-sasl-cram-md5.c: #ifdef HAVE_CONFIG_H. #include and - to remove warnings. - * camel-sasl-digest-md5.c: #ifdef HAVE_CONFIG_H. shuffle headers - * camel-sasl-digest-md5.h: Shuffle headers. - * camel-sasl-kerberos4.c: #ifdef HAVE_CONFIG_H. Shuffle headers. - * camel-sasl-kerberos4.h: Shuffle headers. - * camel-sasl-plain.c: #ifdef HAVE_CONFIG_H. Shuffle - * camel-sasl.c: #ifdef HAVE_CONFIG_H. #include - * camel-search-private.c: #include - * camel-seekable-stream.c: #ifdef HAVE_CONFIG_H - * camel-seekable-stream.h: Shuffle - * camel-seekable-substream.c: #ifdef HAVE_CONFIG_H - * camel-service.c: Same - * camel-service.h: Shuffle - * camel-session.c: #ifdef HAVE_CONFIG_H - * camel-store.c: Same - * camel-stream-buffer.c: Here too - * camel-stream-buffer.h: Shuffle - * camel-stream-filter.c: #include - * camel-stream-fs.c: #ifdef HAVE_CONFIG_H - * camel-stream-fs.h: Shuffle headers - * camel-stream-mem.c: Same as above - * camel-stream-mem.h: Here too - * camel-stream-null.c: #ifdef HAVE_CONFIG_H - * camel-stream.c: Here too - * camel-stream.h: Shuffle - * camel-tcp-stream-openssl.c: #ifdef HAVE_CONFIG_H - * camel-tcp-stream-raw.c: Same here. and move local includes down - * camel-tcp-stream-ssl.c: Same as above - * camel-tcp-stream.c: #ifdef HAVE_CONFIG_H - * camel-tcp-stream.h: move local include down - * camel-transport.c: #ifdef HAVE_CONFIG_H - * camel-transport.h: #include - * camel-uid-cache.c: #ifdef HAVE_CONFIG_H. Shuffle headers - * camel-uid-cache.h: Shuffle - * camel-url.c: #ifdef HAVE_CONFIG_H - * camel-vee-folder.c: #ifdef HAVE_CONFIG_H. Shuffle headers - * camel-vee-folder.h: #include - * camel-vee-store.h: Same here - * camel.c: #ifdef HAVE_CONFIG_H - * gstring-util.c: Here too - * hash-table-utils.c: Remove #include - * hash-table-utils.h: #include it here instead. - * string-utils.c: #ifdef HAVE_CONFIG_H - * providers/cache/camel-cache-map.c: #ifdef HAVE_CONFIG_H, shuffle - headers and mark strings in camel_exception_set*() - * providers/cache/camel-cache-provider.c: #ifdef HAVE_CONFIG_H - * providers/cache/camel-cache-store.c: Same here, and mark a string. - * providers/imap/camel-imap-command.c: #ifdef HAVE_CONFIG_H - * providers/imap/camel-imap-command.h: Shuffle header - * providers/imap/camel-imap-folder.c: #ifdef HAVE_CONFIG_H - * providers/imap/camel-imap-message-cache.c: #ifdef HAVE_CONFIG_H - * providers/imap/camel-imap-provider.c: #ifdef HAVE_CONFIG_H and - #include - * providers/imap/camel-imap-search.c: #ifdef HAVE_CONFIG_H - * providers/imap/camel-imap-store.c: #ifdef HAVE_CONFIG_H and mark - a string. - * providers/imap/camel-imap-summary.c: Shuffle headers - * providers/imap/camel-imap-wrapper.c: #ifdef HAVE_CONFIG_H. Shuffle - * providers/local/camel-local-folder.c: #ifdef HAVE_CONFIG_H - * providers/local/camel-local-provider.c: #ifdef HAVE_CONFIG_H - * providers/local/camel-local-store.c: Same here - * providers/local/camel-local-summary.c: Here too, shuffle, mark a string - * providers/local/camel-maildir-folder.c: #ifdef HAVE_CONFIG_H - * providers/local/camel-maildir-store.c: Same - * providers/local/camel-maildir-summary.c: Here too - * providers/local/camel-mbox-summary.c: And here - * providers/local/camel-mbox-store.c: And here - * providers/local/camel-mbox-summary.c: #include - * providers/local/camel-mh-folder.c: #ifdef HAVE_CONFIG_H - * providers/local/camel-mh-store.c: same - * providers/local/camel-mh-summary.c: #ifdef HAVE_CONFIG_H, shuffle headers - and mark a string for translation. - * providers/nntp/camel-nntp-auth.c: #include - * providers/nntp/camel-nntp-store.c: Remove superfluous arg to - CAMEL_SERVICE_CLASS to make it compile - * providers/pop3/camel-pop3-provider.c: #ifdef HAVE_CONFIG_H - * providers/pop3/camel-pop3-store.c: Same here - * providers/sendmail/camel-sendmail-provider.c: Here too - * providers/sendmail/camel-sendmail-transport.c: Here too - * providers/smtp/camel-smtp-provider.c: Same - * providers/smtp/camel-smtp-transport.c: #ifdef HAVE_CONFIG_H, mark - strings for translations. - -2001-03-29 Dan Winship - - * camel-url.c (camel_url_to_string): change "gboolean show_passwd" - to "guint32 flags". - - * tests/misc/url.c (main): Update calls to camel_url_to_string - - * providers/imap/camel-imap-store.c (construct): Call - camel_url_to_string with flags to hide password, authtype, and - params to create the base_url. - (etc): Update for the fact that the base_url no longer has the "/" - at the end. - - * camel-service.c (construct): Update calls to camel_url_to_string - (pass CAMEL_URL_HIDE_PASSWORD) - -2001-04-03 Jeffrey Stedfast - - * camel-mime-utils.c (header_decode_text): Ignore whitespace - between encoded words (there were a few cases where it didn't - before). - (header_encode_string): Preserve whitespace between words that are - to be encoded by encoding them too. - (header_encode_phrase): Same here but with phrases. - -2001-04-04 Kjartan Maraas - - * camel-filter-driver.c: Added #include . Marked - a bunch of strings for translation. - * camel-folder-search.c: Added #include . - * camel-folder-summary.c: Same here. - * camel-movemail.c: Marked strings for translation. - * camel-provider.c: Same here. - * camel-search-private.c: #include - * camel-vee-folder.c: Mark string for translation. - * providers/local/camel-mbox-summary.c: #include - -2001-04-03 Dan Winship - - * providers/imap/camel-imap-folder.c (imap_sync): If we don't - change any flags or expunge, send a NOOP to give the server a - chance to send EXISTS, etc, messages. - (imap_get_message): If the server_level < IMAP4rev1, always fetch - messages all-at-once, since they don't support the [#.MIME] - syntax. - -2001-04-01 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (get_folder_info): Don't - blindly append "/INBOX", construct a CamelURL and set the path - that way. - (parse_list_response_as_folder_info): Don't blindly append - "/", construct a CamelURL and set the path that way - instead. - (get_folders_offline): And again here. - -2001-03-31 Not Zed - - * camel-operation.c (struct _status_stack): change stamp to - unsigned to avoid overflow. - (camel_operation_end): - (camel_operation_progress_count): - (camel_operation_progress): Double the delay before transient - events start showing their own progress. - -2001-03-30 Not Zed - - * providers/pop3/camel-pop3-folder.c (pop3_get_message): Change - the pop download into a transient event. - - * camel-operation.c (stamp): Get a timestamp that changes 4x a - second (or rather, arbitrarily more often than 1/second). - (camel_operation_progress): Use stamp() for time updates. - (camel_operation_progress_count): " - (camel_operation_start): Store the status as a struct status_stack - item. - (camel_operation_start_transient): New function to start a - transient event, which is only reported if it runs for too - long/and is reset afterwards. - (camel_operation_progress): - (camel_operation_progress_count): Fix for status_stack changes, - and account for transient updates. - - * camel-filter-driver.c (camel_filter_driver_filter_folder): When - we remove things (set deleted), always set seen too, to mirror - interface behaviour when you delete. - (camel_filter_driver_filter_message): And same here too. - -2001-03-30 Dan Winship - - * providers/pop3/camel-pop3-store.c (connect_to_server, - query_auth_types, pop3_connect): Move things around here to make - this all work right again (so you don't get prompted for a - password when checking the supported authtypes.) - -2001-03-29 Dan Winship - - * camel-url.c (camel_url_to_string): change "gboolean show_passwd" - to "guint32 flags". - - * tests/misc/url.c (main): Update calls to camel_url_to_string - - * providers/imap/camel-imap-store.c (construct): Call - camel_url_to_string with flags to hide password, authtype, and - params to create the base_url. - (etc): Update for the fact that the base_url no longer has the "/" - at the end. - - * camel-service.c (construct): Update calls to camel_url_to_string - (pass CAMEL_URL_HIDE_PASSWORD) - -2001-03-28 Jeffrey Stedfast - - * camel-pgp-context.[c,h]: New class for PGP encrypting, - decrypting, signing and verifying. Next I'll be moving the - contents of mail/mail-crypto into Camel. These files will - basically replace mail/openpgp-utils.[c,h]. - -2001-03-29 Not Zed - - * camel-folder-search.c (search_body_contains): Optimise the match - "" case, just match everything in the folder (if we have it). - - * camel-vtrash-folder.c (vtrash_move_messages_to): Access the - folder directly from the message info. - (vtrash_move_messages_to): I think we also need to call the real - move_messages_to, and not try and bypass the lock, since we dont - have the lock for that folder. - - * camel-vee-folder.h: Move CamelVeeMessageInfo to public, so - subclasses can get to it. - - * camel-vee-folder.c (camel_vee_folder_add_folder): Dont let you - add a vfolder to itself. - (folder_changed): - (vee_folder_remove_folder): - (vee_folder_build_folder): Copy changes before triggering changed - events, so we can do them outside of locks. - (camel_vee_folder_get_message_folder): Removed function. - (camel_vee_folder_hash_folder): Made public (renamed from - hash_folder), simply for subclasses (probably not needed). - (vee_expunge): Oops, call the class sync, not superclass sync. - (vee_sync): Remove some accidental debug. - -2001-03-27 Jeffrey Stedfast - - * camel-service.c (get_path): Add the port (if user defined) to - the path to fix bug #1996. - - Danw: I'm iffy on the "fix" so I'd like you to comment. - -2001-03-27 Jeffrey Stedfast - - * providers/pop3/camel-pop3-folder.c (pop3_sync): If we aren't - going to even check the resp/free buffer that gets returned from - camel_pop3_command, don't even bother using it. Send in NULL - instead. - (pop3_get_message): Check to make sure that the `result' string is - non-NULL. It's possible that some POP servers may return with - "+OK\r\n..." rather than the expected - "+OK ### octets\r\n..." - -2001-03-27 Not Zed - - * camel-folder-summary.c (camel_folder_summary_finalize): Unref - the html filter when done. - (summary_build_content_info): Disable using the html parser to - help index html mails until it gets sorted out. - - * camel-vee-folder.c (folder_changed): Fix a cut n paste bug, we - want uid_removed not uid_changed deref, fixes bug #1999. - -2001-03-27 Dan Winship - - * camel-sasl.c (camel_sasl_authtype_list): add an argument to say - whether or not you want "PLAIN" in the list (so you don't end up - with "Password" twice in the config dialog). - - * providers/imap/camel-imap-provider.c (camel_provider_module_init): - * providers/imap/camel-imap-store.c (query_auth_types): We don't - want PLAIN. - - * providers/smtp/camel-smtp-provider.c (camel_provider_module_init): - * providers/smtp/camel-smtp-transport.c (query_auth_types): But we - do. - -2001-03-27 Dan Winship - - * camel-provider.h: Add an "extra_conf" field to CamelProvider - with structures and defines and stuff, for providers to specify - additional configuration options that they want. Also add a - "supports ssl" flag to the provider flags. - - * camel-url.c (camel_url_new_with_base): Fix parsing of params. - (output_param): And unparsing... - - * camel-remote-store.c: add a "default_ssl_port" field. - (remote_construct): If the URL has the "use_ssl" parameter, set - the store's use_ssl flag. - (remote_connect): If using SSL and no port specified, use the - default_ssl_port rather than the default_port. - - * providers/smtp/camel-smtp-provider.c (smtp_provider): add - CAMEL_PROVIDER_SUPPORTS_SSL and CAMEL_URL_ALLOW_USER. (The config - gui code knows that the ALLOW_USER and ALLOW_AUTH go together.) - (ssmtp_provider): gone - - * providers/smtp/camel-smtp-transport.c (smtp_construct): Set a - flag if "use_ssl" param is set. - (smtp_connect): Check the CamelSmtpTransport use_ssl flag rather - than checking if this is smtp or ssmtp. - - * providers/imap/camel-imap-provider.c (imap_conf_entries): Add a - bunch of IMAP-specific configuration options, like "check for new - mail in all folders" (default TRUE), "show only subscribed - folders" (default TRUE), "ignore server-supplied namespace", and - "apply filters to INBOX" (not yet implemented). - (imap_provider): We support SSL and we no longer allow a path in - the URL. (namespace is handled via extra_conf) - (simap_provider): Gone - - * providers/imap/camel-imap-store.c (camel_imap_store_init): Set - default_ssl_port, don't set CAMEL_STORE_SUBSCRIPTIONS here - (construct): remove simap stuff, deal with "use_lsub", - "namespace", "check_all", and "filter" parameters. Set base_url - to not include params. - (imap_store_setup_online): Don't ask for the namespace if it was - set explicitly. Don't get subscribed folders if !use_lsub. - (imap_concat): Fix a bug. - (get_folder_info): Support for not checking all folders. - - * providers/imap/camel-imap-folder.c (imap_get_full_name): Rewrite - to use imap_store->namespace, not service->url->path - - * providers/pop3/camel-pop3-provider.c (pop3_conf_entries): "keep - on server" (currently still implemented by the mailer code, not - here), "delete after N days" (not yet implemented). - (pop3_provider): we support SSL - (spop_provider): gone - - * providers/pop3/camel-pop3-store.c (camel_pop3_store_init): Set - default_ssl_port - (pop3_connect): Remove spop code - -2001-03-26 Jeffrey Stedfast - - * camel-vee-folder.c (vee_folder_construct): Move all of the - camel_vee_folder_construct() internals here. - (camel_vee_folder_construct): This function basically becomes a - wrapper for vee_folder_construct and also checks to make sure that - the UNMATCHED vfodler is constructed otherwise constructs it. - (camel_vee_folder_new): Call vee_folder_construct() instead so - that we don't get into a dead-lock. - -2001-03-26 Jeffrey Stedfast - - * camel-store.c (init_trash): Use camel_vtrash_folder_new() to - create the vtrash folder now. - - * camel-vtrash-folder.[c,h]: New subclass of CamelVeeFolder for - our vTrash folders. - - * camel-folder.c (camel_folder_copy_messages_to): Don't watch for - vtrash folders anymore. - (camel_folder_move_messages_to): Same. - - * camel-vee-folder.c (camel_vee_folder_class_init): Update. - (vee_move_messages_to): Rewrite to use the new move API. - - * camel-filter-driver.c (do_copy): Updated to reflect - copy_message_to changes. Create a temporary uid array and use - that. - (do_move): Same. - (camel_filter_driver_filter_message): And again, here... - - * providers/imap/camel-imap-folder.c (imap_copy_messages_to): - Update to the new API. - (imap_move_messages_to): Same. - (get_uid_set): New function to create a `set' string based on an - array of UIDs for use with imap_copy_messages_to. - - * camel-folder.c (camel_folder_copy_messages_to): Replaces - camel_folder_copy_message_to - (camel_folder_move_message_to): Replaces - camel_folder_move_message_to. - -2001-03-27 Not Zed - - * camel-vee-store.c (vee_get_folder): Added folder_created event - here. - - * camel-vee-folder.c (unmatched_finalise): Removed, moved into - main finalise code. - (message_changed): Just create a new change entry and promote it - to a folder_changed thing. - (vee_sync): Always rebuild folder on sync, even when not expunge. - (folder_changed): If not autoupdating, make sure we remove any - removed entries. - (vee_folder_build_folder): - (vee_folder_remove_folder): NOP if we're called on - folder_unmatched. - (vee_search_by_expression): Only search each folder once. Should - we also order the result in summary order? - -2001-03-20 Not Zed - - * camel-store.c (init_trash): Fix calling for vee_folder_new(). - - * camel-folder-summary.c (camel_folder_summary_remove_index): - Optimise slightly, use ptr_array_remove_index rather than have to - search for the index by using summary_remove. - - * camel-vee-folder.h: Removed local member from VeeFolder, since - it was never used. - - * camel-vee-store.c (camel_vee_store_finalise): Setup finalise - function. - - * camel-vee-folder.c (camel_vee_folder_set_expression): New - function to set the query of an existing vfolder. - (camel_vee_folder_construct): New function for - convenience/subclasses. - (camel_vee_folder_new): Removed exception parameter, no longer - needed (since we dont search yet). - (camel_vee_folder_new): Changed to use folder_construct, and no - longer raise the folder created signal. - (vee_folder_build_folder): Make it return error on exception, so - we can work without exceptions. - (vee_folder_remove_folder): Use remove index rather than - remove_uid, this is ok since we have the summary locked for our - own access. - (camel_vee_folder_add_folder): Only add the folder to the - unmatched private if it is not a private folder. - (camel_vee_folder_remove_folder): Only remove the folder from - unmatched if it is not private. - (vee_expunge): Just call sync with expunge set. - (vee_sync): If expunging, also refresh the search. - (vee_folder_build_folder): We do our own locking now, removed from - callers, also trigger changed events here too (within locks), - fixed callers appropriately. - (vee_folder_remove_folder): Do our own locking, and trigger - changed events. - (vee_folder_add_info): Renamed of vee_folder_add, we now take a - hash of the folder name, rather than use the folders address. - (hash_folder): Convert a folder name into an 8 character hash. - (vee_get_message, vee_search_by_expression, vee_set_message_flags, - vee_set_message_user_flag, vee_move_message_to): Changed the uid - to be an 8 byte hash + original uid, with no ':' anymore. - -2001-03-26 Jeffrey Stedfast - - * camel-mime-utils.c (header_decode_text): When writing the last - token (if not rfc2047 encoded), don't use g_string_append_len, use - append_latin1. - - * camel-mime-message.c (write_to_stream): Don't spew a warning if - the message-id wasn't set by the application, not a big deal since - we create one right here. - -2001-03-26 Dan Winship - - * providers/imap/camel-imap-command.c (camel_imap_command): keep a - reference on the store's current_folder. - - * providers/imap/camel-imap-store.c (camel_imap_store_finalize): - (imap_disconnect): unref the current_folder before clearing it. - - * camel-url.c (camel_url_get_param): Add missing accessor. - - * camel-session.c (camel_session_get_provider): New. Return - the provider for a URL. - -2001-03-25 Dan Winship - - * camel-url.c (camel_url_new_with_base): New URL parser with full - RFC1808 relative URL support. Yum. - (camel_url_new): Wrapper around camel_url_new_with_base now. - - * tests/Makefile.am: add misc subdir - - * tests/misc/url.c: relative URL test cases from RFC 1808 - -2001-03-25 Jeffrey Stedfast - - * camel-filter-driver.c (do_copy): Don't use copy_to if the source - folder doesn't support summary info's. - (do_move): Same. - (camel_filter_driver_filter_message): And again here. I think - this will fix the problem of "colour" tags not staying with the - message when it's copied to a folder during the filter process. - -2001-03-24 Jeffrey Stedfast - - * camel-sasl-digest-md5.c (digest_response): Do charset conversion - on the username param here if needed. - (parse_server_challenge): Protect against possibly empty-string - charset values. - -2001-03-23 Jon Trowbridge - - * camel-filter-driver.c (camel_filter_driver_filter_message): - Don't call camel_mime_message_set_identity. (The call is - commented out, left over from some earlier experimentation that I - want to be able to remember later...) - - * camel-mime-message.c (camel_mime_message_set_identity): Added. - A function to set the X-Evolution-Identity header. - -2001-03-22 Dan Winship - - * providers/imap/camel-imap-command.c (imap_read_response): Don't - look at untagged responses other than "* BYE"... - (camel_imap_response_free): ...do it here instead... - (camel_imap_response_free_without_processing): ...but not here. - - * providers/imap/camel-imap-folder.c (camel_imap_folder_selected): - Remove the "EXISTS" line from the response so - camel_imap_response_free won't try to process it. - (camel_imap_folder_selected): If we get an EXISTS response mixed - in with the FETCH responses, record the new EXISTS value. - Use camel_imap_response_free_without_processing so that an EXISTS - response won't cause a loop. - (imap_rescan): Use camel_imap_response_free_without_processing. - (imap_update_summary): Use - camel_imap_response_free_without_processing. If an EXISTS response - shows up, call imap_update_summary again to get the new messages. - (imap_protocol_get_summary_specifier): Use BODY.PEEK[0], not - RFC822.HEADER for prev IMAP4rev1, since the FETCH parser won't - deal with RFC822.HEADER responses. - - * providers/imap/camel-imap-store.c (get_folder_info): Fix an - uninitialized variable - -2001-03-21 Dan Winship - - * camel-provider.h: (CamelProvider) add a "GList *authtypes", so - you can get the list of authtypes used by a provider without - needing to have an actual CamelService object handy. (Will be - needed by the new config druid.) - (CAMEL_PROVIDER_ALLOWS, CAMEL_PROVIDER_NEEDS): New macros to test - the URL part stuff, since the way it works is too complicated and - everyone always does it wrong. - - * camel-service.c (camel_service_query_auth_types): Remove the - @connected arg again: if you don't want to connect, you can just - get the list of authtypes off the provider. - (camel_service_free_auth_types): Remove this. All existing - implementations do authtypes the same way, so just say the caller - should "g_list_free" the list. (Oh, look, removing this function - doesn't actually cause the mailer to not build. How 'bout that.) - (construct, get_path): Use the new URL part macros. - - * camel-remote-store.c (remote_query_auth_types): Update - (remote_free_auth_types): Nuke - (camel_remote_store_authtype_list): New function for use by - subclasses. - - * providers/imap/camel-imap-provider.c: - * providers/pop3/camel-pop3-provider.c: - * providers/smtp/camel-smtp-provider.c: Update CamelProvider - structures. - (camel_provider_module_init): Put all the SSL parts together so - there's only 1 #ifdef. Set up the provider authtypes field using - the SASL, CamelRemoteStore, and standard authtypes, as - appropriate. Copy that from the normal provider to the SSL - provider. - - * providers/local/camel-local-provider.c: - * providers/sendmail/camel-sendmail-provider.c: - * camel-session.c: Update CamelProvider structures. - - * providers/imap/camel-imap-store.c (query_auth_types): - * providers/pop3/camel-pop3-store.c (query_auth_types): Update - - * providers/smtp/camel-smtp-store.c (query_auth_types): Update. - Remove the no_authtype, because that's what "ALLOW_AUTH" rather - than "NEED_AUTH" means. - (free_auth_types): Nuke. - -2001-03-21 Jeffrey Stedfast - - * camel-filter-driver.c (camel_filter_driver_filter_message): - Return -1 on fail. - (camel_filter_driver_filter_folder): Same. - (camel_filter_driver_filter_mbox): Same. - (camel_filter_driver_filter_folder): Return -1 if an exception was - set as well. - -2001-03-19 Jeffrey Stedfast - - * camel-tcp-stream-openssl.c (camel_tcp_stream_openssl_finalize): - Free the expected host. - (camel_tcp_stream_openssl_new): Now takes a Service and an - expected_host. Set them. - -2001-03-20 Dan Winship - - * providers/imap/camel-imap-store.c - (camel_imap_store_check_online): Function to check if the store is - online and set an exception if not. Currently controlled by an - environment variable, but eventually there will be both a global - (session-level) setting and a per-store setting. - (construct): Set up storage_path and base_url here rather than at - connect-time. - (imap_auth_loop): Split out from imap_connect. - (imap_setup_online): Split out from imap_connect. Do the - post-authentication connection setup, and cache the results to - disk. - (imap_setup_offline): Set up a CamelImapStore with information - saved from a previous imap_setup_online. - (imap_connect): If online, do connect_to_server(), - imap_auth_loop(), and imap_setup_online(). Otherwise, do - imap_setup_offline(). - (get_folder, get_folder_info): Add offline support. - (create_folder, subscribe_folder, unsubscribe_folder): Disable - these when offline (for now). - - * providers/imap/camel-imap-folder.c (camel_imap_folder_new): - Remove the sync'ing-with-server stuff... it's done by - camel_imap_folder_selected now, which only gets called if the - store is online. - (camel_imap_folder_selected): add the code removed from - camel_imap_folder_new. Besides simplifying the folder_new and - summary_new code, this also means now that we'll DTRT if a - folder's UIDVALIDITY changes while we're connected. Also, when - that happens, clear the message cache explicitly. - (imap_refresh_info, imap_sync): These are no-ops when offline. - (imap_expunge, imap_append_message, imap_copy_message_to, - imap_search_by_expression): These don't yet work offline. - (imap_get_message, camel_imap_folder_fetch_data): Return an error - when trying to fetch a non-cached body part when we're offline. - - * providers/imap/camel-imap-summary.c (camel_imap_summary_new): - Rewrite to not check the validity here. (We'll do it from - camel_imap_folder_selected instead.) - - * providers/imap/camel-imap-command.c (camel_imap_command): Call - camel_imap_folder_selected even when the selection is all we're - doing, to match the changes in camel-imap-folder.c. - - * providers/imap/camel-imap-message-cache.c - (camel_imap_message_cache_clear): New function to clear out a - message cache. - -2001-03-19 Christopher James Lahey - - * Makefile.am (INCLUDES): Added $(EXTRA_GNOME_CFLAGS) - -2001-03-19 Jeffrey Stedfast - - * providers/pop3/camel-pop3-store.c (pop3_connect): Set the errbuf - to NULL after freeing it? I don't think this should fix bug #1801 - but I guess it can't hurt. - -2001-03-18 Jeffrey Stedfast - - * camel-remote-store.c (remote_recv_line): Protect against a - possibly NULL exception. - - * camel-filter-driver.c (camel_filter_driver_filter_message): - Document and modify to return a boolean value denoting whether or - not errors occured during processing. - (camel_filter_driver_filter_mbox): Same as above and also modified - to check return codes of filter_message rather than relying only - on whether or not the exception was set (as it's possible to pass - in NULL for the exception). - (camel_filter_driver_filter_folder): Same as above. - - * camel-mime-utils.c (header_param_list_format_append): Quote the - param value if it contains whitespace as well. - -2001-03-17 Jeffrey Stedfast - - * Makefile.am: Don't include system include dir. - - * camel.c: Use quotes around the nss.h include so it doesn't try - to use the systen nss.h file. - - * camel-tcp-stream-ssl.c: Same here. - -2001-03-17 Not Zed - - * providers/local/camel-maildir-summary.c (maildir_summary_sync): - Modified patch from Dan Berger to re-check - the maildir directory for new/updated messages at sync time. - - * camel-folder.c (camel_folder_ref_message_info): Implemented. - (ref_message_info): And default implementation. - - * camel-folder.h: Added ref_message_info virtual method. - -2001-03-16 Not Zed - - * camel-folder-thread.c - (camel_folder_thread_messages_new_summary): New function to create - a thread tree from a supplied summary array. - (camel_folder_thread_messages_destroy): Handle thread trees - generated by the above function properly. - -2001-03-16 Jeffrey Stedfast - - * camel-private.h: Same. - - * camel-remote-store.h: Fixed #include to use <>'s instead of ""'s - -2001-03-16 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (ssl_bad_cert): Print info about the - issuer of the certificate. - - * providers/smtp/camel-smtp-transport.c (smtp_connect): Use - camel_tcp_stream_get_socket(). - - * camel-tcp-stream-openssl.c (stream_get_socket): Implemented. - - * camel-tcp-stream-ssl.c (stream_get_socket): Implemented. - - * camel-tcp-stream-raw.c (stream_get_socket): Implemented. - - * camel-tcp-stream.c (camel_tcp_stream_get_socket): New function. - -2001-03-16 Kjartan Maraas - - * providers/pop3/camel-pop3-folder.c: Added #include - -2001-03-16 Dan Winship - - * camel-mime-utils.c (header_msgid_generate): Don't use - getdomainname: it's NIS crap, not DNS. - -2001-03-15 Jeffrey Stedfast - - * camel.c (camel_init): Don't use the hardcoded cert db directory, - use the one passed in. - - * camel-tcp-stream-ssl.c (ssl_get_client_auth): Wrote the default - implementation. Not that we'll use this though, since this is the - default implementation provided by NSS anyway. This more or less - serves as a reference in case we want to change anything. - (ssl_auth_cert): Same. - (ssl_bad_cert): Changed the prompt string and free it when we're - done. - -2001-03-15 Dan Winship - - First batch of disconnected IMAP-related stuff. This adds local - caching of message parts, but NOT any actual disconnected support. - (But it should speed up IMAP use.) - - * providers/imap/camel-imap-message-cache.c: New class for caching - message data to disk, and removing it when it's no longer - relevant. Will eventually also support merging message parts - together to save on files. Or maybe using a db instead of files? - - * providers/imap/camel-imap-private.h: Add a cache_lock to - CamelImapFolderPrivate. This lock must be recursive, so make both - locks EMutexes rather than GMutex. - - * providers/imap/camel-imap-folder.c (parse_fetch_response): "The - only FETCH response parser you need!" Replaces the various - almost-correct bits of code formerly scattered throughout this - file with a single fully-correct function that can handle any - FETCH response at any time, so we don't get confused by seeing a - flags update when we were only expecting a message body, etc. - (camel_imap_folder_fetch_data): FETCH a message body part either - from the cache or the server - (camel_imap_folder_changed): Remove expunged messages from the - message cache. - (camel_imap_folder_new): Change to take a directory instead of a - summary file name. Create a CamelImapMessageCache for the folder. - (imap_finalize): Unref the message cache. - (camel_imap_folder_selected, imap_rescan, get_content, - get_message, imap_get_message, imap_update_summary): Redone a - bunch to use parse_fetch_data, CamelImapMessageCache, etc. - - * providers/imap/camel-imap-store.c (get_folder): Pass directory - name to camel_imap_folder_new, not summary filename. Use - e_path_to_physical to generate a path with /subfolders/ inserted - between directory components. - - * providers/imap/camel-imap-wrapper.c (camel_imap_wrapper_new): - Call camel_imap_folder_fetch_data (with cache_only TRUE) and if - the data is cached, return an online datawrapper rather than an - offline one. - (write_to_stream): Use camel_imap_folder_fetch_data (with - cache_only FALSE) here too - - * providers/imap/camel-imap-utils.c (imap_skip_list): Renamed from - skip_list and made non-static. - -2001-03-15 Jeffrey Stedfast - - * camel-tcp-stream-ssl.h: Uninclude prnetdb.h since it's not - needed here. - - * providers/smtp/camel-smtp-transport.c: #include prnetdb.h here - instead of making camel-tcp-stream-ssl.h include it. Prevents some - header bloat. - - * providers/smtp/Makefile.am: Include the NSPR_CFLAGS and - NSS_CFLAGS. - -2001-03-14 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_connect): Update for - using CamelTcpStreams and also for using SSL. - - * providers/smtp/libcamelsmtp.urls: defined "ssmtp" - - * providers/smtp/camel-smtp-provider.c: Defined the Secure SMTP - provider. - (camel_provider_module_init): Register the Secure SMTP provider. - -2001-03-14 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (imap_connect): Check for - "simap" instead of "imaps". - - * providers/pop3/camel-pop3-store.c (pop3_connect): Change the - port to be 995 for spop. - - * providers/pop3/libcamelpop3.urls: Change to "spop". - - * providers/imap/libcamelimap.urls: Change "imaps" to "simap" to - correspond to /etc/services. - -2001-03-14 Jeffrey Stedfast - - * providers/pop3/camel-pop3-store.c (pop3_connect): Check to see - if we are using "pops" and then set the appropriate SSL settings. - - * providers/pop3/libcamelpop3.urls: Add "pops" - - * providers/pop3/camel-pop3-provider.c: Defined the pops provider. - (camel_provider_module_init): Register the pops provider. - -2001-03-14 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (camel_tcp_stream_ssl_new): Ya know what? - Lets not ref the service because otherwise we'll start having the - same problems we had back with vtrash. Besides, since the store - owns the stream, it's not like the store is going anywhere without - the stream anyway. - (camel_tcp_stream_ssl_finalize): No need to unref the service. - -2001-03-14 Jeffrey Stedfast - - * camel-remote-store.c (remote_connect): Pass the service into the - SSL stream, not the session. - - * camel-tcp-stream-ssl.c (camel_tcp_stream_ssl_init): Set the - service to NULL. - (camel_tcp_stream_ssl_finalize): Unref the service. - (camel_tcp_stream_ssl_new): Takes a CamelService arg now rather - than a CamelSession arg. - -2001-03-14 Jeffrey Stedfast - - * camel.c (camel_init): So it turns out that NSS_Init *isn't* - idempotent, so we have to protect against initializing it more - than once(contrary to what their design specs suggest). - - * camel-session.c (camel_session_get_service): Use - camel_exception_is_set() - Makes no difference but it's more - consistant with how we normally do it. - - * camel-provider.h (CAMEL_URL_ALLOW_SSL): We don't need this. - - * providers/imap/camel-imap-provider.c: Define the imaps provider. - (camel_provider_module_init): Register the imaps provider. - - * camel-provider.c (camel_provider_init): Only add the protocol to - the hash table if it's non empty. Also, g_strdup() the filename - into the hash table. - - * providers/imap/camel-imap-store.c (camel_imap_store_init): Eek! - So the service's URL isn't set until after this is - initialized. This means we can't check for SSL here. - (imap_connect): Set the SSL options here instead. - -2001-03-14 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c: Numerous fixes to get it to build - correctly with NSS enabled. - - * camel-remote-store.c (remote_connect): Pass in the session and - expected host args, oops. - - * camel-provider.h (CAMEL_URL_ALLOW_SSL): Defined. - - * providers/imap/camel-imap-store.c (camel_imap_store_init): Check - to see if we are supposed to use SSL and set the options - accordingly. - (imap_connect): Return FALSE here instead of NULL. - - * providers/imap/camel-imap-provider.c: Add CAMEL_URL_ALLOW_SSL. - - * providers/imap/libcamelimap.urls: Add "imaps" which is the - protocol for Secure IMAP. - -2001-03-14 Jeffrey Stedfast - - * camel-tcp-stream-openssl.[c,h]: Added - - * Makefile.am: Added camel-tcp-stream-openssl.[c,h] to the build. - - * camel-types.h: Added CamelTcpStreamSSL and CamelTcpStreamOpenSSL - -2001-03-14 Not Zed - - * camel-mime-filter-charset.c (filter, complete): re-constify - inbuf, to remove a warning. - - * camel-mime-parser.c (folder_scan_step): When we're out of data, - run the filter_complete. For some reason the logic that was there - was never being run, always try it now, i think it was to work - around a buggy filter, rather than fix it the right way. - - * camel-folder-summary.c (summary_build_content_info): If indexing - html parts, use the html filter to convert it to some indexable - format. - (summary_build_content_info): Reset the filters before adding them - back to the stream, if they get re-used in a given instance - (likely). - - * Makefile.am (libcamelinclude_HEADERS): Added - camel-mime-filter-html.[ch]. - (INCLUDES): Added xml clags - -2001-03-05 Not Zed - - * camel-folder-search.c (camel_folder_search_class_init): Setup a - new function, "uid" which matches uids. - (search_uid): Implement the "match uid" command. - -2001-03-13 Jeffrey Stedfast - - * camel-mime-utils.c: Check for a new type of mailing list header. - -2001-03-13 Jeffrey Stedfast - - * camel-tcp-stream-raw.c (stream_read): Made cancellable. - (stream_write): Same. - (stream_connect): Removed checks for DIVINE_INTERVENTION as the - code worked fine. - - * camel-tcp-stream-ssl.c (stream_write): get rid of 'w' as it - wasn't really needed. - (set_errno): New function to set errno based on the NSPR error - code. - (stream_read): If an error occured, call set_errno(). - (stream_write): Same. - -2001-03-13 Jeffrey Stedfast - - * Makefile.am: Added camel-tcp-stream-ssl to the build. - - * camel-remote-store.h: Add a use_ssl member to the - CamelRemoteStore object. - -2001-03-13 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (camel_tcp_stream_ssl_get_type): - Oops. Make this a subclass of CamelTcpStream, not CamelStream. - - * camel-types.h: Add the defs for CamelTcpStream and - CamelTcpStreamRaw - - * Makefile.am: Add camel-tcp-stream and camel-tcp-stream-raw to - the build. - - * camel-remote-store.c (remote_connect): Update to use - CamelTcpStreams. - - * camel-tcp-stream-raw.c (stream_connect): Made cancellable by - copying the currently used code in camel-remote-store.c. - (stream_setsockopt): Oops, flags = fcntl (..., GET_FL); - (camel_tcp_stream_raw_get_type): Oops. Make this a subclass of - CamelTcpStream, not CamelStream. - -2001-03-13 Jeffrey Stedfast - - * camel.c (camel_init): Since all of the Mozilla libs (including - NSPR and NSS) correctly handle reinitializations, we might as well - init both NSPR and NSS in camel_init so we can be sure of that - these libs have been initialized. - (camel_shutdown): New function to call the NSS cleanup stuff. - -2001-03-13 Jeffrey Stedfast - - * camel-folder.c (camel_folder_copy_message_to): Don't allow the - user to copy a message to or from the vtrash folder. Set an - exception if they try. - (camel_folder_move_message_to): This one is a bit more - complicated: 1) If the user tried to move a message from the - vtrash into the original folder, just undelete the message. 2) If - the user tries to move the message to the vtrash folder, then just - mark the message as deleted. 3) If the user tries to move the - message from the vTrash to a folder other than the original, use - the original folder as the source. As another optimization, I've - made it so that if the user tries to move a message to the same - folder, just no-op. - (move_message_to): Unset the deleted flag before moving (assuming - it's there). - (copy_message_to): Same. - - * camel-vee-folder.c (camel_vee_folder_get_message_folder): New - convenience function to get the folder from which the message uid - is derived from. - -2001-03-13 Dan Winship - - * providers/imap/camel-imap-store.c (imap_connect): When trying - again after a failed password attempt, check if the connection got - dropped (which Courier will do) and deal accordingly. - - * providers/sendmail/camel-sendmail-transport.c (sendmail_send_to, - sendmail_send): More fixing for exim: It can't deal with "-tif", - you need to say "-t -i -f". - -2001-03-12 Jeffrey Stedfast - - * camel-store.c (init_trash): Rename the folder to "Trash" and - i18nify it. - -2001-03-09 Jeffrey Stedfast - - * camel-tcp-stream-ssl.h: Comment out everything unless HAVE_NSS - is defined. - - * camel-tcp-stream-ssl.c (stream_read): Don't use errno, use - nspr's error code stuff. - (stream_write): Same. - -2001-03-09 Jeffrey Stedfast - - * camel-session.c (camel_session_query_authenticator): Created a - new mode (CAMEL_AUTHENTICATOR_ACCEPT) which is a Yes/No prompt to - the user. This will be needed by the SSL/TLS code to come. Also - changed the return value to a gpointer rather than a char* to - allow the returning of TRUE/FALSE values. - - * camel.c: Wrap stuff with HAVE_NSS - -2001-03-09 Dan Winship - - * providers/sendmail/camel-sendmail-transport.c (sendmail_send, - sendmail_send_to): Remove the "-U" for now, because it breaks - exim's "sendmail" wrapper. (And it doesn't actually do all that - much to sendmail's behavior, and it was working fine before - anyway.) - - * camel-mime-utils.c (header_fold): Fix a bug that could make this - walk off the end of a string. (The bug has been there since - December... maybe this will fix some unreproduceable crashes?) - -2001-03-08 Jeffrey Stedfast - - * camel-store.c (camel_store_get_folder): Changes so that the - folder gets added to the vtrash reguardless of whether or not the - store is holding it's own folder lookup hash. - (init_trash): Oops, lets try locking the cache before we go and - add all the cached folders to the vtrash. - -2001-03-08 Jeffrey Stedfast - These fixes make it so that the CamelStore does not actually hold - a ref on it's vTrash folder. The vTrash folder is now created ONLY - when it is requested. This solves the problem of not being able to - unref a Store and have it disconnect/finalize like we expect it to. - - * camel-store.c (init_trash): When we create the vtrash, add all - previously opened folders to it and hook on to the finalize event - so that we can then set the store->vtrash to NULL. - (get_trash): If a vtrash folder for the store doesn't exist, - init_trash() and then try. - (construct): No longer need this. - (camel_store_class_init): Don't override the construct method. - (camel_store_finalize): We no longer hold a ref on the vtrash so - don't unref it. - -2001-03-07 Jeffrey Stedfast - - * providers/pop3/camel-pop3-store.c (init_trash): Implement. - (get_trash): Implement. - (camel_pop3_store_class_init): Override the default init_trash and - get_trash virtual functions. Hopefully this should fix the problem - of pop3 sotre's not disconnecting after the send&recv code - finishes downloading mail. - - Wonder if I should override the default implementation for the - mbox, mh, and maildir too? - -2001-03-07 Dan Winship - - * camel-remote-store.c (camel_remote_store_connected): Return the - return value of camel_service_connect rather than returning - !camel_exception_is_set(), since that will be wrong if ex==NULL... - Fixes a crash in the IMAP keepalive code, but this same problem - probably exists in other places too... - (remote_recv_line): Fix another problem... - - * providers/local/camel-mbox-provider.c: - * providers/vee/.cvsignore: - * providers/vee/libcamelvee.urls: Remove some unused stuff - -2001-03-06 Jeffrey Stedfast - - * camel-sasl-digest-md5.c (compute_response): Redone so as to save - on memory allocations and speed. - -2001-03-05 Jeffrey Stedfast - - * camel-sasl-plain.c (plain_challenge): Don't return NULL if the - token is non-NULL. This is why: - - sending : AUTH PLAIN - received: 334 ok. go on. <-- this is why - sending : ZGZPaQpAZ214Lm5ldBBnb29jYXI= - received: 235 {mp005-rz3} go ahead - - * camel-sasl.c (camel_sasl_authtype): Add the PLAIN type here. - (camel_sasl_authtype_list): And here too. - - * camel-sasl-plain.c: Initialize the camel_sasl_plain_authtype. - - * camel-sasl-plain.h: extern the camel_sasl_plain_authtype. - -2001-03-05 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (imap_connect): i18n'd some - strings in here. - - * providers/smtp/camel-smtp-transport.c (smtp_connect): Keep - trying to authenticate until either we succeed or until the user - cancels. - -2001-03-04 Jeffrey Stedfast - - * camel-mime-utils.c: Wrote a new version of header_fold() that - takes a 'force' option and uses another new function called - header_fold_next_space() in place of strchr(inptr, ' ') to get the - next whitespace char. The idea of header_fold_next_space() is to - not treat spaces between a set of quotes as a space - this way it - will be possible to fold (for example) the Content-Type MIME - header without worrying about breaking up a boundary string. - Note: This code is #if 0'd out until Zucchi approves of the patch. - Another Note: We will probably still want to use the "don't fold - this header" hash lookup for headers like the Message-Id and - possibly a few others. - -2001-03-04 Jeffrey Stedfast - - * camel-internet-address.c - (camel_internet_address_encode_address): Make sure there is a - space between the name and the address tokens. - - * camel-mime-utils.c (rfc2047_decode_word): encoded string - segments need to be at least 8 chars (7 doesn't leave room for an - ecoding value. To be more realistic, even 8 chars isn't enough as - this assumes there is no charset nor any encoded text. If the - encoding value is not 'Q' or 'B', then return NULL. This fixes bug - #1689. - -2001-03-03 Not Zed - - * camel-vee-folder.c (vee_folder_remove_folder): New function to - remove a folder from a vfolder. - (camel_vee_folder_remove_folder): New public function to remove a - folder from a vfolder. - -2001-03-02 Jeffrey Stedfast - - * providers/smtp/camel-smtp-provider.c: Doh! Set the - CAMEL_URL_ALLOW_AUTH flag. - - * providers/smtp/camel-smtp-transport.c (get_smtp_error_string): - Updated with the extended AUTH return codes. - -2001-03-02 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (try_auth): Don't forget to - unref the SASL object. - - * providers/smtp/camel-smtp-transport.c (query_auth_types): - Implemented. - (smtp_auth): Implemented. - (smtp_helo): Don't bother parsing the authtypes if we already have - them. - (smtp_connect): call smtp_auth() here if we found any authtypes. - (smtp_disconnect): Updated as I now use a hash table for the - supported authtypes rather than a linked list. - (esmtp_get_authtypes): modify to use a hash table instead of a - linked list and also use isspace() rather than == ' '. - -2001-03-02 Dan Winship - - * providers/sendmail/camel-sendmail-transport.c (sendmail_send_to, - sendmail_send): Use "-f" to set the envelope from address so - bounces go to the right place. Also, pass "-U" since the man page - says we're supposed to... - -2001-03-01 Jeffrey Stedfast - - * camel-sasl.c: #include "camel-sasl-digest-md5.h" - (camel_sasl_authtype_list): add DIGEST-MD5 stuff here. - (camel_sasl_authtype): And here too. - (camel_sasl_new): And here... - - * camel-sasl-digest-md5.[c,h]: new SASL class for DIGEST-MD5 (has - been tested and proven to work). - -2001-03-01 Dan Winship - - * camel-sasl.c (camel_sasl_challenge): Take a GByteArray as input - as well. Comment that you can pass %NULL for @token to get the - initial auth data for mechanisms that are client-initiated. - (camel_sasl_challenge_base64): Convenience function for protocols - that use base64-encoded SASL. - (camel_sasl_authenticated): Implement this... (it was prototyped - already) - (camel_sasl_new): Function to take a service name, a mechanism - name, and a CamelService, and return a CamelSasl for it. - (camel_sasl_authtype, camel_sasl_authtype_list): Functions to - return CamelServiceAuthType information about SASL mechanisms, to - allow providers to deal with them generically. - - * camel-sasl-anonymous.c, camel-sasl-plain.c: Update/simplify for - CamelSasl changes. Both of these are single-round - (client-initiated) mechanisms, so they don't need to keep state. - (camel_sasl_plain_new): Removed; use camel_sasl_new instead. - (Can't get rid of camel_sasl_anonymous_new though...) - - * camel-sasl-cram-md5.c: Update/simplify for CamelSasl changes. - (camel_sasl_cram_md5_new): Removed; use camel_sasl_new instead. - (cram_md5_challenge): Use md5_get_digest where possible, and - various other minor simplifications. CRAM-MD5 only has a single - round, so there's no need to keep track of state. This code is now - tested (against Cyrus IMAPd) and known to work. - - * camel-sasl-kerberos4.h: Update/simplify for CamelSasl changes. - Make only a single #ifdef HAVE_KRB4. Remove stuff from priv that - isn't needed between rounds. - (camel_sasl_kerberos4_new): Removed; use camel_sasl_new instead - (krb4_challenge): Fix up the logic I broke in my previous "at - least make it compile" fixes, update to match other changes, and - remove IMAP-isms that shouldn't be in the generic code. This still - isn't tested, because we're stuck behind a NAT right now... - - * providers/imap/camel-imap-store.c: Add an "authtypes" hash table - to CamelImapStore recording the supported authtypes. - (connect_to_server): Record supported authtypes in the authtypes - hash rather than the capabilities bitmask, since now the IMAP code - is no longer responsible for keeping track of which authtypes we - support. - (query_auth_types): Use camel_sasl_authtype_list to get the - SASL-supported authtypes. - (try_auth): New function to try a SASL auth mechanism. Sort of - formerly imap_try_kerberos_v4_auth. - (imap_connect): Get rid of the krb4-specific bits and genericize - them for any SASL authtype. - - * providers/imap/Makefile.am: Remove camel-imap-auth.[ch] (moved - into camel-imap-store.c since it's now constant size) and the - KRB4_CFLAGS and KRB4_LDFLAGS references. - -2001-03-01 Jeffrey Stedfast - - * camel-sasl-anonymous.c (anon_challenge): Don't base64 encode the - data, leave that up to the provider to do if it needs to. Also - save on some memory allocations and stuff. - - * camel-sasl-cram-md5.c (cram_md5_challenge): Same here. Also get - rid of the need for the temp buf as we can just write it to the - GByteArray. - -2001-03-02 Not Zed - - * camel-mime-utils.c (rfc2047_encode_word, rfc2047_decode_word): - Reconstify variables to match iconv. - - * camel-search-private.c (camel_ustrstrcase): Change some - assertions back into valid returns. - -2001-03-01 Dan Winship - - * Makefile.am (libcamel_la_LIBADD, INCLUDES): camel depends on - krb4 now (where available), for camel-sasl-kerberos4.c - - * camel-sasl-kerberos4.[ch]: Make this at least compile. Dunno if - it works yet. - -2001-03-01 Peter Williams - - * camel-url.c (camel_url_new): Assert url_string != NULL. - -2001-02-28 Jeffrey Stedfast - - * Makefile.am: Added camel-sasl-anonymous.[c,h] to the build. - - * camel-sasl-anonymous.[c,h]: new SASL class for ANONYMOUS - - * camel-sasl-plain.c (plain_challenge): Oops, have a state for - setting sasl->authenticated = TRUE; - - * camel-sasl-cram-md5.c (cram_md5_challenge): Same here. - -2001-02-28 Jeffrey Stedfast - - * camel-mime-utils.c (header_decode_date): A fix for broken - mailers that send 2-digit years (ie "Wed, 28 Feb 01 - 04:59:41"). Fixes bug #1633. - - * camel-filter-driver.c (camel_filter_driver_filter_folder): Check - to make sure message isn't NULL. - -2001-02-28 Dan Winship - - * camel-remote-store.c (remote_recv_line): If we get back 0 bytes - from camel_stream_buffer_gets, that means the socket got - disconnected, so set an exception. (Noticed because of a message - that crashes our IMAP server when you try to look at it. :) - -2001-02-28 Jeffrey Stedfast - - * Makefile.am: Added camel-sasl*.[c,h] to the build. - - * camel-sasl.[c,h]: new "abstract" SASL class - - * camel-sasl-kerberos4.[c,h]: new SASL class for KERBEROS_V4 - - * camel-sasl-cram-md5.[c,h]: new SASL class for CRAM-MD5 - - * camel-sasl-plain.[c,h]: new SASL class for PLAIN - - * providers/imap/camel-imap-auth.c: Removed the base64 functions. - - * camel-mime-utils.c (base64_encode_simple): Moved here from - camel-imap-auth.c - (base64_decode_simple): Same. - -2001-02-26 Dan Winship - - * providers/imap/camel-imap-folder.c (imap_sync): Group messages - into sets with the same flags and use the IMAP message set - notation rather than doing a separate STORE FLAGS for each one. - This cuts the network traffic down to just a handful of commands - per sync rather than one per changed message. Removed the progress - notification stuff since it's no longer meaningful and should - hopefully be unnecessary. - (imap_copy_message_to): move the former sync_message function - into here, since it's no longer shared with imap_sync. - -2001-02-26 Jeffrey Stedfast - - * camel-mime-utils.c: Made thread-safe and moved to above the test - code. - - * camel-mime-message.c (camel_mime_message_init): Set the - message_id to NULL. - (camel_mime_message_finalize): Free the message_id. - (camel_mime_message_set_message_id): New function to set the - Message-Id. - (camel_mime_message_get_message_id): New function to get the - Message-Id. - (process_header): Decode the message-id. - -2001-02-24 Jeffrey Stedfast - - * camel-store.c (construct): init the vTrash folder here instead - of in store_init. - (camel_store_class_init): init service_class->construct. - (camel_store_finalize): We only need to unref the vtrash folder. - (init_trash): don't create a vstore since we don't need it. - -2001-02-23 Jeffrey Stedfast - - * camel-store.c (camel_store_class_init): init get_trash and - init_trash. - (camel_store_init): call the virtual init_trash function. - (camel_store_finalize): unref the vtrash folder/store if present. - (camel_store_get_folder): Add the new folder to the vtrash - vfolder. - (init_trash): default implementation of init_trash. - (get_trash): default implementation of get_trash. - - * camel-vee-store.c (vee_init_trash): No-op. - (vee_get_trash): return NULL - -2001-02-23 Not Zed - - * camel-folder-summary.c (camel_message_info_new_from_header): - Doh, cut and paste problem, use mlist not cc. - - * camel-folder.c (move_message_to): - (copy_message_to): If the source folder doesn't support a - summary, dont try and get the message info from it. - - * camel-filter-search.c (check_header): Implement a pseudo-header - "x-camel-mlist" which just looks up in the message info for a - match. - - * camel-folder-search.c (check_header): Add pseudo-header - "x-camel-mlist" which can be used to match on mailing list. - - * providers/imap/camel-imap-folder.c (imap_sync): Add some - internal progress reporting. - (imap_rescan): Do some progress reporting. - - * camel-mime-part.c (init_header_name_table): Add the message-id - to the formatted table, so we dont try and wrap it, and break it. - -2001-02-22 Jeffrey Stedfast - - * camel-folder.h: Remove the 'FIXME: remove because this isn't - required...' comment for copy_message_to since we now need and - cherish its existance in the filter-driver code ;-) - - * camel-filter-driver.c (camel_filter_driver_filter_message): Now - takes a UID and CamelFolder arguments (which can be NULL) to allow - for possible optimizations when copying messages between folders - on the same store. - (camel_filter_driver_filter_mbox): Updated (passes NULL for both - since this case can't be optimized anyway). - (camel_filter_driver_filter_folder): Updated to pass in the uid - and folder of the message. - -2001-02-22 Dan Winship - - * providers/imap/camel-imap-summary.h (CAMEL_IMAP_SERVER_FLAGS): - #define this as the set of all IMAP system flags - - * providers/imap/camel-imap-folder.c (sync_message): after syncing - flags, set server_flags to (flags & CAMEL_IMAP_SERVER_FLAGS) - rather than just "flags", since any other flags won't have been - synced. Prevents the CAMEL_MESSAGE_ATTACHMENTS flag from getting - lost. - -2001-02-22 Not Zed - - * providers/vee/*: Removed all files. - - * camel-private.h: Move camel-vee-private.h stuff into here. - - * camel-session.c: Move the vee_provider here, and initialise it - always as part of a session. The vfolder provider is always - available. - - * providers/Makefile.am: Remove "vee" from the build list, now - built as part of the main library. - - * Makefile.am (libcamelinclude_HEADERS): - (libcamel_la_SOURCES): Added camel-vee-store.[ch], - camel-vee-folder.[ch]. - - * providers/vee/camel-vee-folder.c (vee_folder_build): Removed, - not used. - (camel_vee_folder_new): Removed call to build_folder. - (vee_get_message): Dont try and free the mi if we didn't get it. - - * camel-folder.c (camel_folder_change_info_new): Added a hash - table of what we have in the lists, plus moved private things into - private pointer. - (camel_folder_change_info_add_source): Fixed up private accesses. - (camel_folder_change_info_add_uid): Changed to use a hashtable to - see if we already have the uid, etc. - (camel_folder_change_info_remove_uid): Similar. - (change_info_remove): Likewise. - (camel_folder_change_info_clear): Fixes for privatisations. - (camel_folder_change_info_free): " - -2001-02-21 Dan Winship - - * providers/imap/camel-imap-folder.c (fetch_medium): Fixes for - IMAP4-pre-rev1 from Torsten Schulz. - -2001-02-20 Not Zed - - * camel-mime-utils.c (mail_list_magic): Take the ^Header: part out - of the expression, since we look that up ourselves. - (header_raw_check_mailing_list): When getting the match, get match - 1, not match 0, we dont want the full string match. - - * camel-folder-summary.c (CAMEL_FOLDER_SUMMARY_VERSION): Bumped - for summary change. - (message_info_new): Extract the mlist info from the headers. - (message_info_load): Load mlist from summary. - (message_info_save): Save mlist to summary. - (message_info_free): Save the mlist entry. - (camel_message_info_new_from_header): Extract mailing list header. - (camel_message_info_dup_to): Copy the mlist entry. - (camel_message_info_free): Free mlist. - (message_info_dump): Dump the mlist. - - * camel-folder-summary.h: Add an mlist (mailing list) string to - the summary. - -2001-02-19 Not Zed - - * providers/vee/camel-vee-folder.c (camel_vee_folder_new): Added - flags argument. - (message_changed): Add support for the auto-update flag, in which - case we auto-match the content as it changes. - (camel_vee_folder_init): Remoive "DYNAMIC" optionality - (camel_vee_folder_finalise): " - (vee_expunge): As we expunge folders, re-sync their content by - rerunning the query. - - * providers/vee/camel-vee-store.c (vee_get_folder): Pass flags to - folder new. - -2001-02-18 Not Zed - - * providers/vee/Makefile.am (noinst_HEADERS): Added - camel-vee-private.h. - - * providers/vee/camel-vee-private.h: New file to add locking stuff - for vee folders. - - * providers/vee/camel-vee-folder.c (camel_vee_folder_new): Add - locking around unmatched setup. - (camel_vee_folder_init): Setup lock. - (camel_vee_folder_finalise): Free locks. - (folder_changed): Add locking. - (unmatched_finalise): " - (message_changed): " - (vee_folder_build): " - -2001-02-17 Not Zed - - * providers/vee/camel-vee-folder.c (vee_folder_add): Check uid - doesn't exist before adding it. - -2001-02-16 Not Zed - - * providers/vee/camel-vee-folder.c (camel_vee_folder_new): Create - a new virtual virtual folder UNMATCHED, to store all messages that - dont match other vfolders. - (unmatched_folder_changed): When a vfolder issues a changed event, - use its info to update the unmatched folder info. - (unmatched_finalise): When a vfolder is finalised, remove any uids - it has as if we had a removed event for it. - -2001-02-16 Jeffrey Stedfast - - * camel-filter-driver.c (camel_filter_driver_finalise): Thaw the - defaultfolder. - (camel_filter_driver_set_default_folder): Thaw the defaultfolder - we're about to replace, and freeze the new defaultfolder. - -2001-02-15 Jeffrey Stedfast - - * providers/vee/camel-vee-folder.c (camel_vee_folder_new): Emit - the folder_created signal here. - - * providers/local/camel-local-folder.c - (camel_local_folder_construct): Emit the folder_created signal. - - * providers/local/camel-local-store.c (delete_folder): On error, - free the 'name' string so we don't leak. Also emit the - folder_deleted signal. - - * providers/imap/camel-imap-store.c (subscribe_folder): Emit the - folder_created signal. - (unsubscribe_folder): Emit the folder_deleted signal. - - * camel-store.c (camel_store_class_init): Added folder_created and - folder_deleted signal defs. - -2001-02-15 Dan Winship - - * camel-folder-thread.c (container_parent_child): Deal with - out-of-order References headers so they don't cause messages to - disappear in threaded view. - - * providers/imap/camel-imap-folder.c (fetch_medium): IMAP4 - (pre-rev1) doesn't allow BODY.PEEK[], so use RFC822.PEEK instead - in that case. - -2001-02-14 Christopher James Lahey - - * camel-mime-filter-charset.c (complete, filter), - camel-mime-utils.c (rfc2047_decode_word, rfc2047_encode_word): - Changed this code to match the glibc iconv signature. - -2001-02-14 Dan Winship - - * camel-store.c (camel_store_create_folder): New method to create - a folder when you don't know its full name. - - * providers/imap/camel-imap-store.c (create_folder): Implement. - (create_folder): Oops, and fix bug involving namespaces - -2001-02-12 Not Zed - - * camel-mime-part.c (init_header_name_table): Add address headers - to list that we dont fold when writing. The are properly - formatted as we build them. - (write_to_stream): DOH, lookup the header name in the formatted - hash table, not the value, that would never have worked. - - * camel-internet-address.c - (camel_internet_address_encode_address): Changed to take a - parameter saying how much we've printed so far. We now fold the - header as we format it. We dont fold addresses, even if they are - too long, we simply put them on another line by themselves: this - should make the result more parsable by mailers that can't handle - split up addresses (which are legal). - (internet_encode): Fix for changes to above. - -2001-02-12 Jeffrey Stedfast - - * providers/local/camel-local-provider.c: mbox, mh, and maildir - camel-url's need absolute paths. - - * camel-provider.h (CAMEL_URL_PATH_IS_ABSOLUTE): New flaggy flag. - -2001-02-08 Dan Winship - - * camel-store.c: Rewrite a bunch. Replace the existing folder - cache stuff with much simpler code that still handles all the - existing cases. Now the folder hash table is always created by the - base class, using hash and compare functions provided by the class - implementation. (If they are set to NULL, CamelStore won't cache - folders.) lookup_folder, cache_folder, and uncache_folder are no - longer class methods, and get_name is gone completely. - - (camel_store_get_inbox): Renamed from - camel_store_get_default_folder, since that wasn't being used, and - this is what we actually need. - (camel_store_get_root_folder): Removed, since it's not needed for - anything given get_folder_info. - - * camel-remote-store.c: - * providers/local/camel-local-store.c: - * providers/local/camel-mbox-store.c: - * providers/local/camel-mh-store.c: - * providers/local/camel-maildir-store.c: - * providers/nntp/camel-nntp-store.c: - * providers/pop3/camel-pop3-store.c: - * providers/vee/camel-vee-store.c: Minor updates for CamelStore - changes - - * providers/imap/camel-imap-store.c (camel_imap_store_class_init): - Update for CamelStore changes. - (hash_folder_name, compare_folder_name): treat INBOX - case-insensitively, otherwise use g_str_hash and g_str_equal. - - * camel-service.c (camel_service_construct): Remove - camel_service_new and create camel_service_construct (as a class - method) in its place. - - * camel-session.c (camel_session_get_service): Use - camel_object_new and camel_service_construct to replace - camel_service_new. - - * providers/local/camel-local-store.c (construct): Append a '/' to - the URL path if it doesn't end with one - -2001-01-31 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c: Oops, include the camel-tcp-stream-ssl - header instead of the raw one. - -2001-02-07 Not Zed - - * camel-operation.c (camel_operation_start): Changed to push the - operation into a status stack. - (camel_operation_progress): Changed to only accept % complete. - (camel_operation_reset): Free status stack as well. - - * providers/pop3/camel-pop3-folder.c (pop3_get_message): Get the - octect count from the return line, and pass it to - get_additional_data(). - (pop3_refresh_info): Added status stuff. - - * providers/pop3/camel-pop3-store.c - (camel_pop3_command_get_additional_data): Added a total bytes - expected argument for progress reporting & fixed callers. - (camel_pop3_command_get_additional_data): Added progress - reporting. - - * providers/local/camel-mbox-summary.c (mbox_summary_sync_full): - (mbox_summary_sync_quick): - (summary_rebuild): Added progress reporting stuff. - -2001-02-07 Jeffrey Stedfast - - * camel-search-private.c (CAMEL_SEARCH_COMPARE): Macro for making - comparisons easy. - (camel_ustrcasecmp): Use CAMEL_SEARCH_COMPARE and check for - end-of-string before the utf-8 error check. - (camel_ustrncasecmp): Same. - (camel_search_header_match): Strip leading spaces before doing - anything else. Also use vlen and mlen so as to not need to do 500 - strlen()'s. - (camel_ustrcasecmp): Don't get_utf8() for the 2 strings in the - comparison part of the loop because of short-circuit expression - evaluation. (blame JPR if this is the wrong term!) - (camel_ustrncasecmp): Same. - -2001-02-06 Jeffrey Stedfast - - * camel-search-private.c (utf8_get): Rewrote using unicode_get_utf8(). - (camel_ustrcasecmp): Use unicode_char_t - (camel_ustrncasecmp): Same. - -2001-02-06 Christopher James Lahey - - * camel-mime-filter-charset.c (complete, filter), - camel-mime-utils.c (rfc2047_decode_word, rfc2047_encode_word): - Made these pass char ** as the second parameter to iconv. - -2001-02-06 Not Zed - - * camel-session.c: Removed all the camel_cancel stuff. - - * camel-stream-fs.c (stream_read): Change to use camel_operation. - (stream_write): " - - * camel-remote-store.c (socket_connect): Change to use - camel_operation rather than camel_cancel stuff. - Removed gal include, WTF is that doing there anyway? - - * Makefile.am (libcamel_la_SOURCES): - (libcamelinclude_HEADERS): Added camel-operation.[ch], stuff to - handle notification and cancellation. - - * camel-search-private.c: Removed unwanted header. It was never - put in for a reason. Stop fixing irrelevant warnings. - - (camel_ustrstrcase): Our own strstrcase impl for utf8 strings. - (camel_ustrcasecmp): Ditto for strcasecmp. - (camel_ustrncasecmp): And strncasecmp. - (utf8_get): Simpler interface to utf8 string processing. - (camel_search_header_match): Use the new things. - -2001-02-05 Not Zed - - * camel-folder.c (get_summary): Removed some old variables/a small - memleak. - (free_summary): Removed old variables. - - * camel-mime-utils.c (header_raw_check_mailing_list): New utility - function to get the mailing list (if any) that a set of headers - came from. - -2001-02-05 Christopher James Lahey - - * camel-stream-fs.c: Added a missing #include. - - * camel-search-private.c: Added a missing #include. - -2001-02-05 Jeffrey Stedfast - - * camel-remote-store.c (remote_query_auth_types): Oops. Change - this too. - - * providers/smtp/camel-smtp-transport.c (query_auth_types): Updated. - - * providers/nntp/camel-nntp-store.c (nntp_store_query_auth_types): - Updated. - - * providers/pop3/camel-pop3-store.c (query_auth_types): Updated. - - * providers/imap/camel-imap-store.c (query_auth_types): Updated. - - * camel-service.c (camel_service_query_auth_types): Now takes a - boolean value to specify whether or not to connect when - constructing a supported authtype list. - -2001-02-05 Not Zed - - * camel-stream-filter.c (do_write): Revert jeff's earlier change, - the change below is the more-correct fix. All his was doing was - ignoring the return code & looping actually :) - - * camel-stream-fs.c (stream_write): Since we are non-blocking on - the outgoing fd, keep looping if writing out large blocks, so we - can keep checking for cancel, etc. - -2001-02-02 Not Zed - - * camel-folder-thread.c (camel_folder_thread_messages_new): When - we drop a fake node, dont skip checking the next in the list. - (camel_folder_thread_messages_new): Add an assertion check just to - make sure we dont get any pseudo nodes, and spit a warning if we - do. - -2001-02-04 Jeffrey Stedfast - - * camel-stream-filter.c (do_write): Make do_write loop until the - entire buffer is written. - -2001-02-02 Not Zed - - * camel-stream-fs.c: Add missing header for cancel check stuff. - - * camel-session.c (camel_cancel_cancel): Fix a wrong cast. - - * camel-mime-part.c (init_header_name_table): Setup a new table - header_formatted_table, that lists headers that we dont want to - fold (they've already been folded). - (write_to_stream): Check for already formatted headers, and dont - try and fold them. This is a fix for bug #1097. - -2001-02-01 Not Zed - - * camel-mime-utils.c (header_fold): If we are folding, drop the - space at the end of the line. - -2001-01-30 Not Zed - - * camel-remote-store.c (timeout_cb): Remvoe the stream locking - here. I think this was leading to a deadlock when a keepalive is - being sent, in imap. - -2001-01-29 Not Zed - - * providers/imap/camel-imap-command.c - (imap_command_strdup_vprintf): Include the terminating NUL in the - calculated string length. This hit memcheck. - -2001-01-25 Not Zed - - * tests/folder/test3.c: Changed the subject search to handle case - sensitive when it is mixed case. - - * Makefile.am (libcamel_la_SOURCES): Added camel-ssearch-private.c - (noinst_HEADERS): Added camel-search-private.h - - * camel-folder-search.c (check_header): New function to do the - work of the various header checks. - (search_header_matches): - (search_header_starts_with): - (search_header_ends_with): - (search_header_contains): Use check_header to do the work. - (build_match_regex): Removed. - - * camel-search-private.c (header_soundex): New - function to match words to phrases using soundex algorithm. - - * camel-filter-search.c (soundexcmp): Removed. - (check_match): Moved to search-private.h - -2001-01-24 Not Zed - - * camel-search-private.c (camel_search_build_match_regex): Added - extra flags, so the same function can be used for - start/end/whole/partial matches. - (camel_search_header_match): Convenience function to check a - single header against all sorts of different matches. - - * providers/imap/camel-imap-search.c (imap_body_contains): Fix for - e_sexp api changes. - - * camel-folder-search.c: Fix for e_sexp api changes. - (search_header_contains): Free args/quit on unknown header. - (search_header_matches): " - (search_header_starts_with): " - (search_header_ends_with): " - (match_message): Add an exception argument. - (search_body_contains): Free args/quit on fatal error. - (message_body_contains): Removed (moved to - camel-search-private.c), fixed callers. - - * camel-filter-search.c: Fix for e_sexp api changes. - (build_match_regex, message_body_contains): Moved into - camel-filter-private.c Fixed callers. - (check_header): moved guts to camel-search-private, and - changed to use regex's for everything. Just calls that with the - right args. - (check_header): GEts the header, decodes it, and checks for - failure, and whatnot. - (check_match): Removed. - (header_soundex): Changed significantly. Now it soundexes each - word in the header separately, and compares it to the first - argument. - - * tests/folder/test9.c (main): Fix for api changes. - (main): Added tests to see that invalid match and action - rules are properly detected. - - * camel-filter-driver.c (camel_filter_driver_filter_mbox): Remove - the 'finished message' bit. - (camel_filter_driver_filter_message): Remove an accidentally - checked in debug. - (camel_filter_driver_filter_message): Fix for e-sexp api changes. - -2001-01-23 Dan Winship - - * providers/imap/camel-imap-wrapper.c: Add a lock around the - delayed loading, so two threads won't try to do it at the same - time. - -2001-01-22 Dan Winship - - * providers/vee/camel-vee-folder.c (camel_vee_folder_new): Set the - CamelFolder::name to just the base part of the vfolder name (the - non-query part) - -2001-01-23 Not Zed - - * camel-filter-search.c (camel_filter_search_match): Perform error - checking on parsing/execution. - - * camel-folder-search.c (camel_folder_search_execute_expression): - Perform error handling on search expression. - (CamelFolderSearchPrivate): Add a camelexception for error - returns. - (camel_folder_search_execute_expression): Setup exception pointer. - (search_match_all): Quit on error. - - * providers/imap/camel-imap-summary.c (message_info_load): Removed - some debug 'warnings', as they should now be displayed at the - toplevel loader, and just made the code match similar code - elsewhere. - - * providers/local/camel-mbox-summary.c (message_info_load): Error - handling. - (message_info_save): more error handling. - - * camel-folder-summary.c (message_info_load): Add error handling - and sanity checking. - (camel_folder_summary_load): Add error checks. - (perform_content_info_load): Error + sanity checks. - (content_info_load): error + sanity checks. - - * camel-filter-driver.c (close_folder): avoid /0 by updating after - we've done the sync. - (close_folders): Setup the first progress report to start it off. - (camel_filter_driver_filter_message): Fix a fixme, check errors in - e_sexp parsing, etc. - -2001-01-22 Christopher James Lahey - - * providers/imap/camel-imap-folder.c (camel_imap_folder_selected): - Initialize the value of the variable exists here. - -2001-01-22 Not Zed - - * .cvsignore */*/.cvsignore: Added profiling temp - files. - - * camel-folder-thread.c (camel_folder_thread_messages_new): When - removing phantom nodes, check for the end node too. - - * camel-filter-driver.[ch]: Changed status vars to be - CAMEL_FILTER_STATUS_ etc. - -2001-01-21 Jeffrey Stedfast - - * camel-mime-utils.c (header_param_list_format_append): Make the - output a little prettier. Okay, so I'm anal... - -2001-01-21 Not Zed - - * camel-filter-driver.h: Added an exception to - CamelFilterGetFolderFunc. - - * camel-filter-driver.c (camel_filter_driver_filter_message): - Remove source parameter, as it is determined elsewhere now. - (camel_filter_driver_filter_folder): Same here. - (camel_filter_driver_filter_mbox): And here. - (do_move): If we cannot open a folder, quit, rather than ignoring - it. - (do_copy): Here too. - (open_folder): Pass an exception into get_folder callback. - (camel_filter_driver_filter_folder): Report that we're syncing, - when we are. - (camel_filter_driver_filter_mbox): And here too. - (close_folder): And here. - -2001-01-19 Jeffrey Stedfast - - * camel-filter-driver.c (camel_filter_driver_filter_message): Set - the deleted bit *before* copying to the default folder, this way - if they are importing mail and have a rule to delete it, it - doesn't get copied to the default folder un-deleted. - -2001-01-19 Dan Winship - - * providers/imap/camel-imap-store.c - (get_subscribed_folders_by_hand): If LISTing a subscribed folder - doesn't return a LIST response, just ignore that folder. Yay - RFC2060. - (subscribe_folder): add a missing UNLOCK - -2001-01-19 Kjartan Maraas - - * providers/smtp/camel-smtp-provider.c: Mark strings for translation. - -2001-01-19 Not Zed - - * camel-filter-driver.c (report_status): Add a percentage complete - indicator to the status thing. - (camel_filter_driver_filter_mbox): Add percentage complete to - reporting. - (camel_filter_driver_filter_folder): Same. - -2001-01-18 Dan Winship - - * camel-store.c (camel_folder_info_build): More tweaking... skip - separator characters after the namespace character. (Gets rid of - the shell folder registration warning some people have had with - IMAP) - - * providers/imap/camel-imap-store.c (imap_connect): I'm sure there - was some clever reason I was storing the flags of the folder in - the hash table rather than just "1", but I don't remember what it - was now. Anyway, since we only ever test NULL/non-NULL, store 1, - since flags is sometimes 0. - - * providers/imap/camel-imap-folder.c (imap_update_summary): Oops. - Somewhere in one of the reorgs, the code to add new messages to - the CamelFolderChangeInfo structure got removed. Fix that. - -2001-01-17 Jeffrey Stedfast - - * providers/imap/camel-imap-summary.c (message_info_load): Add - some g_warnings() to help debug later if I ever get the segfaults - I was getting earlier. Can't seem to reproduce them after my - previous "fix". - - * camel-folder-summary.c (camel_folder_summary_load): Undid my - change here, NotZed said it was wrong and that if it gets a NULL - mi then it should abort and not continue. - -2001-01-17 Jeffrey Stedfast - - * camel-folder-summary.c (camel_folder_summary_load): Make sure - that the message-info is non-null before we go accessing inner - parts of it and/or adding it to the summary array. I may not have - handled the error correctly, but it does seem to work - correctly. If NotZed could double-check this it'd be great. - - * providers/smtp/camel-smtp-transport.c (get_smtp_error_string): - New smtp error-code to string mapping function. - (smtp_connect): Use the new error->string function for reporting - useful errors. - (smtp_helo): Same. Also use a case-insensitive strstr for 8BITMIME - as it seems Exchange sends back lowercase for that one single SMTP - extension. Everything else is uppercase. I'm seeing a lack of love - for that extension by Microsoft dudes... - (smtp_mail): Use get_smtp_error_string. - (smtp_rcpt): Same. - (smtp_data): Same. - (smtp_quit): Same. - (smtp_rset): Same. - -2001-01-16 Jeffrey Stedfast - - * camel-folder-summary.c (camel_folder_summary_array): Add an int - i so this code will compile. Should I be worried about how well - this code will work? ;-) - -2001-01-17 Not Zed - - * camel-folder.c (free_summary): Call - camel_folder_summary_array_free() to do the work. - (get_summary): Use camel_folder_summary_array() to get the array - atomically. These fixes allow folder/test8 to work again, and fix - a sort of race where the summary size can change while we were - making a copy of it. - - * camel-folder-summary.c (camel_folder_summary_array): Get the - summary array atomically, so it can't contain empty records. - (camel_folder_summary_array_free): And free it. - - * tests/lib/camel-test.c (die): If we are verbose & in threads, - then goto sleep so we can debug. - - * tests/folder/test8.c (worker): Add a missing pull() for - comnparing content. - - * camel-filter-search.c: Fix the symbol table, so match-all is an - immediate function, as it should be. - - * tests/folder/test9.c (main): New test, tests some filtering - things. - - * tests/message/test3.c (main): Dont use a boundary string with - spaces in it. Folding can corrupt it. Maybe the folding isn't - working entirely right, but anyway. - - * camel-session.c: Debug out the debug. - - * camel-filter-driver.c (camel_filter_driver_filter_folder): Plug - a messageinfo leak. - -2001-01-16 Dan Winship - - Delayed loading of IMAP message parts. - - * camel-types.h: typedef CamelMessageInfo and - CamelMessageContentInfo here - - * camel-folder-summary.h: Add a "size" field to - CamelMessageContentInfo. - - * camel-folder-summary.c (camel_folder_summary_content_info_new, - camel_folder_summary_content_info_free): Renamed and made - non-static for providers that construct their own content info. - (content_info_load, content_info_save): load/save size - - * camel-data-wrapper.c (camel_data_wrapper_is_offline): New - function to return if a data wrapper's contents are "offline". (So - that, for example, we don't make thumbnails of images that haven't - been loaded off the IMAP server yet.) Defaults to FALSE. - - * providers/imap/camel-imap-folder.c (camel_imap_folder_selected): - Fix a bug in re-selecting a folder when messages have been - expunged from it by another client in the meantime. - (imap_get_message): Rewrite. If the message is larger than a - certain size, just create a skeleton message containing - CamelImapWrappers that will read parts as needed. This way, large - attachments only need to be downloaded if the user looks at them, - and multipart/alternative alternatives that aren't used will never - be downloaded at all. - (imap_update_summary): Rewrite this a bunch too to make the - parsing more robust. - - * providers/imap/camel-imap-summary.c - (CAMEL_IMAP_SUMMARY_VERSION): bump. - (camel_imap_summary_new): Set build_content to TRUE. - (content_info_load, content_info_save): Only save/load the content - for messages that have it. (The content info gets created as a - side effect of imap_get_message.) - - * providers/imap/camel-imap-utils.c (imap_parse_body): New routine - (and helpers) to parse an IMAP 'body' FETCH response and fill in a - CamelMessageContentInfo from it. - - * providers/imap/Makefile.am (libcamelimap_la_SOURCES, - libcamelimap_la_HEADERS): add camel-imap-wrapper. - -2001-01-16 Dan Winship - - * camel-tcp-stream-raw.c (stream_getsockopt, stream_setsockopt): - * camel-stream-fs.c (stream_read, stream_write): - * camel-remote-store.c (socket_connect): fcntl(fd, F_GETFL) - returns the flags as the return value, not via a passed in - pointer. And F_SETFL looks for an int, not a long, and you have to - pass it what it's expecting because it's a va_arg parameter. (Yes, - the man page lies on Linux. But check the UNIX98 spec or the glibc - source.) Also, fix another bug in socket_connect: if we manage to - connect right away, unset O_NONBLOCK so it doesn't mess us up - later. - - Fixes a bunch of problems with non-blocking I/O being done in the - allegedly-blocking case and then returning EWOULDBLOCK. - -2001-01-16 Chris Toshok - - * providers/Makefile.am (NNTP_DIR): set to nntp if ENABLE_NNTP - (SUBDIRS): use $(NNTP_DIR) - -2001-01-16 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_rcpt): Don't check - errno as it's not being set. Fixes bug #1150. - -2001-01-16 Jeffrey Stedfast - - Ugh, this design is ugly like my butt. - - * camel-session.c (camel_session_query_cert_authenticator): New - function which will be useful when we integrate SSL. - - * camel-tcp-stream-ssl.c (ssl_auth_cert): Callback to authenticate - a certificate. - (ssl_bad_cert): Callback that gets the reason the certificate is - bad and then calls camel's cert-authenticator callback to notify - the user and to allow the user to override the check. - (stream_connect): Set the URL we expect to connect with and setup - the auth_cert and bad_cert callbacks. - (camel_tcp_stream_ssl_new): Now takes a CamelSession and a - expected_host argument that it will use for certificate - authentication. - (camel_tcp_stream_ssl_finalize): Unref the session and free the - expected_host. - -2001-01-16 Not Zed - - * camel-filter-search.c (header_exists): Changed to support - multiple args (or'd together). - (header_contains): Cleaned up to match the search code. Why did - fejj change it? I'll never know. - (header_matches): - (header_starts_with): - (header_ends_with): Big cleanup of fejj's "i'm the cut & paste - king" code. Also properly handle or'ing of additional args to - match what the folder-search code should do. - (check_match): New function which does the annoying matching - stuff (for header matches). - (check_header): Similarly, handles or'ing of the matches together. - (header_contains): - (header_matches): - (header_starts_with): - (header_ends_with): Call check_header to do the actual work. - (header_soundex): And here too. - (match_all): Yeah like match-all isn't passed expression results, - its passed expression terms. Fix this so match-all works like it - should, by executing the contained expression. - (message_body_contains): Copied directly from - camel-folder-search.c, a more robust/faster/simpler body search - code. - (mime_part_matches): Removed entirely. - (handle_multipart): Removed entirely. - (build_match_regex): Copied from camel-folder-search. Builds a - set of simple strings into a regex pattern that matches any of - them (for faster & simpler matching). Expanded to accept regex - patterns itself, so it can merge them together. - (body_contains): Use build match/match message to match using a - built regex. - (body_regex): Likewise, this time we tell it we're building a - regex though. - (header_full_regex): Use build_match_regex to take the drudgery - out of it, and expand it to handle multiple regex's at once. - (get_full_header): slightly cleaner (well i dunno, the sprintf - stuff just got to me). - (header_regex): Cleaned up to use build_match_Regex too, and to - properly check types. - (filter_message_search): Just allocate 'fms' on the stack. - - * camel-filter-driver.c (camel_filter_driver_finalise): - (camel_filter_driver_init): - (camel_filter_driver_class_init): - (camel_filter_driver_get_type): Changed from gtk object to camel - object. - (camel_filter_driver_add_rule): New function to add a rule to be - processed in sexp form. - (camel_filter_driver_init): Init the rules list. - (camel_filter_driver_finalise): Clear the rules/rules list. - (camel_filter_driver_filter_message): Scan rules list directly - rather than creating on the fly. - - * Makefile.am (libcamelinclude_HEADERS): Added camel-filter-driver.h - (libcamel_la_SOURCES): Added camel-filter-driver.c, code taken - from filter-driver, which can drive, uh, filters based on sexp's. - (libcamelinclude_HEADERS): - (libcamel_la_SOURCES): Added camel-filter-search.[ch] - - * camel-folder-summary.c (camel_folder_summary_decode_string): - Chganged len back to be unsigned. And do a simple range check on - the string value to try and detect corrupted summary files. - - * providers/imap/camel-imap-command.c (imap_read_untagged): Handle - cancelled stream reads with an appropriate exception. - - * providers/imap/camel-imap-private.h: Fix the include-once - macro. Doh, confliced with camel-private.h. - - * providers/imap/camel-imap-store.c (imap_store_refresh_folders): - A copy of camel_remote_store_refresh_folders. We avoid locking - each folder when we call it though. This should be removed when i - can work out how to remove the folder lock from this function - easily. - - * camel-stream-fs.c (stream_write): Fix n' argument of select. - (stream_read): Likewise. - - * camel-remote-store.c (socket_connect): Bump the connect timeout - upto 4 minutes. - (socket_connect): Oops, fix the 'n' argument of select. - - * camel-session.c (camel_cancel_cancel): If we are given no - cancellation node, then do it for all active ones. - -2001-01-15 Jeffrey Stedfast - - * camel-stream-fs.c (stream_close): If the close() is successful, - set the fd to -1. - - * camel-tcp-stream-raw.c: Removed the disconnect() method. - (stream_close): If the close() is successful, set the sockfd to - -1. - - * camel-tcp-stream-ssl.c: Removed the disconnect() method. - (stream_close): If the close() is successful, set the sockfd to - NULL. - - * camel-tcp-stream.c (camel_tcp_stream_disconnect): Removed, - easier to just use the close() method as it did the same thing - anyway. - -2001-01-15 Jeffrey Stedfast - - * camel-tcp-stream-raw.c (stream_getsockopt): Updated to be able - to get the CAMEL_SOCKOPT_NONBLOCKING socket opt. - (stream_setsockopt): Updated to be able to set the - CAMEL_SOCKOPT_NONBLOCKING socket opt. - -2001-01-15 Peter Williams - - * providers/imap/camel-imap-folder.c (camel_imap_folder_new): Lock - around the imap_rescan, which needs it. - -2001-01-15 Not Zed - - * camel-remote-store.c (socket_connect): A cancellable connection - routine. - (remote_send_string): Return cancelled exception if we were. - (remote_send_stream): " - (remote_recv_line): " - - * camel-stream-fs.c (stream_read): First cut at cancellation - stuff. Its looking a bit ugly. - -2001-01-15 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (stream_connect): Uses an SSL socket now - although there's still a few things missing (like certificate - handling and such). - - * camel.c (camel_ssl_init): A replacement function for - camel_init() that also initializes SSL. - -2001-01-14 Jeffrey Stedfast - - * camel-tcp-stream-ssl.c (stream_getsockopt): Implemented. - (stream_setsockopt): Implemented. - - * camel-tcp-stream-raw.c (stream_getsockopt): Implemented. - (stream_setsockopt): Implemented. - - * camel-tcp-stream.c (camel_tcp_stream_getsockopt): New method. - (camel_tcp_stream_setsockopt): Another new method. I think you get - the idea of what these are for so I won't explain them. - -2001-01-14 Jeffrey Stedfast - - * camel-tcp-stream-ssl.[c,h]: New CamelTcpStream class that - implements nspr sockets and eventually will use nss for - SSL/TLS. Currently doesn't do any SSL/TLS but it should still - work. It's functionally equivalent to CamelTcpStreamRaw at the - moment only it uses nspr i/o. - - * camel-tcp-stream-raw.[c,h]: New CamelTcpStream class that - implements native sockets. Should be usable but may have some bugs - yet. - -2001-01-13 Jeffrey Stedfast - - * camel-tcp-stream.[c,h]: New abstract class for TCP streams. The - next step is to write child classes (CamelTcpStreamBSD and - CamelTcpStreamSSL). The BSD stream will use normal BSD sockets - while SSL will use Mozilla's NSPR and NSS libraries to do Secure - Socket Layers which wille ventually replace CamelStreamSSL which I - just commit'd. Oh well. - -2001-01-13 Jeffrey Stedfast - - * camel-stream-ssl.[c,h]: New stream for handling SSL/TLS - connections. - -2001-01-12 Not Zed - - * camel-folder-thread.c (camel_folder_thread_messages_new): - Perform a final pass, removing any pseudo nodes we added earlier. - Quick patch to test the idea. - (camel_folder_thread_messages_new): Added casts to rmeove some - warnings for the analites out there. - -2001-01-11 Dan Winship - - * providers/imap/camel-imap-folder.c (camel_imap_folder_selected): - Fix a bug in previous commit: don't check for deleted messages if - there are no known messages in the folder (because it would end up - sending "FETCH 0 ..."). - (imap_copy_message_to): Fix this up: sync flags to the server - before copying so that they end up correct in the remote folder. - And poke the destination folder after doing the copy so it notices - the new message right away. - (imap_move_message_to): Call imap_copy_message_to for most of the - work rather than duplicating the code (since it's much more - complicated now). - -2001-01-11 Dan Winship - - * providers/imap/camel-imap-folder.c (camel_imap_folder_selected): - New function to check for added/deleted messages when re-selecting - a folder. - (imap_refresh_info, imap_rescan, imap_update_summary): Various - locking tweaks that turn out to be irrelevant since command_lock - is recursive, but whatever. - - * providers/imap/camel-imap-command.c (camel_imap_command): When - selecting a new folder, call camel_imap_folder_selected on it. - - * camel-folder.c (camel_folder_copy_message_to): Fix a locking - problem. (One branch of an if statement was returning with the - lock still locked.) Also remove the deprecation comments, to match - move_message_to. - -2001-01-10 Jeffrey Stedfast - - * providers/local/camel-local-provider.c: Changed the descriptions - for mh, mbox, and maildir to be more "user-friendly". - -2001-01-10 Dan Winship - - * providers/imap/camel-imap-types.h: New header to prevent - recursive #include problems - - * providers/imap/*.h: Replace some #includes with #include - "camel-imap-types.h", remove typedefs that were moved to - camel-imap-types.h - - * providers/imap/*.c: Add #includes to make up for #includes - removed from .h files - - * providers/imap/Makefile.am (libcamelimapinclude_HEADERS): Add - camel-imap-types.h - -2001-01-10 Dan Winship - - * camel-store.c (camel_store_sync): New class function, parallel - to camel_folder_sync. (The default implementation just calls - camel_folder_sync on each cached folder.) - - * providers/imap/camel-imap-store.c (get_folder_info): Call - camel_store_sync before doing anything else so that the IMAP - server and Camel are working from the same data. Don't ask the - server for the unread message count of the current folder, since - UW will return often-incorrect cached data, and we can calculate - it without talking to the server anyway. - -2001-01-09 Dan Winship - - Mostly IMAP changes. Use the NAMESPACE extension (where - available). Deal with servers that don't return LIST flags in - response to LSUB (like UW) to get rid of the "not a selectable - folder" error messages in the UI. Take advantage of the \Marked - and \Unmarked flags to try to speed up the folder scan by not - doing STATUS on unmarked folders. Some further tweaks on the shape - of the resulting folder tree in various situations... - - * camel-store.h: Remove the (read) message_count, since nothing - uses it, and we can speed up IMAP a bit this way. - - * camel-store.c (camel_folder_info_build): Redo this a bit to make - it more useful for IMAP since that's the only thing that uses it. - - * camel-remote-store.c (camel_remote_store_connected): Public - function to check if the store is connected, and try to connect it - if it's not. - (remote_send_string, remote_send_stream, remote_recv_line): Use - that. - - * providers/imap/camel-imap-store.c (camel_imap_store_finalize): - fix up for changes. - (camel_imap_store_init): Initialize subscribed_folders to NULL - rather than an empty hash table. - (imap_connect): Get the list of subscribed folders here. If the - server doesn't claim that any of them are either Marked or - Unmarked, then assume that it doesn't do that for LSUB and - remember that for later. If the server supports the NAMESPACE - extension and the user didn't specify a namespace, use the - server-provided one. - (imap_disconnect): Free the list of subscribed folders, and the - namespace. - (get_folder): check camel_remote_store_connected - (get_folder_info): check camel_remote_store_connected. Add a bunch - of new cleverness. If we learned that the server doesn't do LSUB - usefully, do a bunch of LISTs by hand. Then, if we're getting - unread counts, only do it for folders that weren't listed as - Unmarked. Also, deal with namespaces that end with the separator - character, and update for changes to camel_folder_info_build. - (folder_subscribed): Add a g_return_val_if_fail. - (subscribe_folder, unsubscribe_folder): check - camel_remote_store_connected. - - * providers/nntp/camel-nntp-store.c (build_folder_info, - build_folder_info_from_grouplist, nntp_store_get_folder_info): - Don't fill in message_count since it doesn't exist any more. - -2001-01-09 Dan Winship - - Kill off a long-hated Camel kludge: "empty" URLs and - query_auth_types_generic. - - * camel-url.c: Remove "empty" from CamelURL. - (camel_url_new): No longer set it. - (camel_url_to_string): Treat "" as equivalent to NULL for - authmech. (Unrelated change, but it simplifies some stuff with the - new config dialog.) - - * camel-service.c (camel_service_new): Remove url->empty check: if - the URL isn't valid, we don't create the service. - (camel_service_query_auth_types): No longer need to switch between - generic and connected variants. - - * providers/smtp/camel-smtp-transport.c (query_auth_types): - * providers/pop3/camel-pop3-store.c (query_auth_types): - * providers/nntp/camel-nntp-store.c (nntp_store_query_auth_types): - * providers/imap/camel-imap-store.c (query_auth_types): - * camel-remote-store.c (remote_query_auth_types): Remove generic - version, rename connected version. - -2001-01-06 Not Zed - - * providers/vee/camel-vee-folder.c (vee_folder_build_folder): Dont - try and unref a messageinfo that wasn't there, and use the right - free function too. Modified patch from Iain. - (vee_move_message_to): New method, call the real folders' - move_message_to method. - -2001-01-04 JP Rosevear - - * tests/lib/Makefile.am: fix includes for compilation - - * tests/message/Makefile.am: Build test3 again - - * tests/message/test2.c: Kill warnings with header includes - - * tests/message/test3.c: ditto - - * tests/lib/streams.c: ditto - - * tests/lib/camel-test.c: ditto - - * tests/lib/messages.c: ditto - - * tests/lib/folders.c: ditto - -2001-01-04 Dan Winship - - * providers/imap/camel-imap-folder.c (imap_rescan): Fix two - problems in figuring out server-expunged messages. - -2001-01-04 Not Zed - - * camel-folder.c (thaw): If we have a lot of messages changed, - promote it to a folder changed event. - -2000-01-03 Jeffrey Stedfast - - * camel-folder-search.c (search_header_matches): Implemented. - (search_header_exists): Implemented. - (search_header_starts_with): Implemented. - (search_header_ends_with): Implemented. - -2001-01-03 Christopher James Lahey - - * providers/imap/camel-imap-folder.c (camel_imap_folder_new): - Initialize the exists variable so that we don't do random things - if the imap server misbehaves. - -2000-12-29 Not Zed - - * camel-folder.c (camel_folder_move_message_to): REmove warning, - this isn't really deprecated, sigh. - - * camel-mime-utils.c (header_fold): Comment out some debug. - -2001-01-02 Christopher James Lahey - - * providers/maildir/, providers/mbox/, providers/mh/: Removed - these directories since they're unused. - -2001-01-02 Dan Winship - - IMAP randomness. - - * providers/imap/camel-imap-stream.[ch]: Remove. To be replaced. - - * providers/imap/Makefile.am (libcamelimapinclude_HEADERS): Remove - camel-imap-stream.h - - * providers/imap/camel-imap-utils.c (imap_parse_flag_list): Take a - char ** instead of char *, to return the position at the end of - parsing like the string parsing functions. - (imap_parse_string_generic): New function to parse a string, - nstring, or astring. - (imap_parse_nstring, imap_parse_astring): Now macros - (imap_parse_string): Added - - * providers/imap/camel-imap-folder.h: Remove the "exists" field - from CamelImapFolder. - - * providers/imap/camel-imap-folder.c: Remove unused include of - camel-imap-stream.h. - (camel_imap_folder_init): Remove no-longer-relevant summary - initialization. - (camel_imap_folder_new): Update for imap_parse_flag_list change, - exists removal, and imap_rescan. - (imap_rescan): New function that does most of the work of the old - imap_refresh_info, but taking "exists" as an argument instead of - getting it from the folder. Also calls camel_imap_folder_changed - to do the summary updating and signalling, rather than duplicating - that code. - (imap_refresh_info): Just call imap_rescan (using the size of the - folder summary as "exists"). - (imap_update_summary): Update for imap_parse_flag_list change - (camel_imap_folder_changed): Update for "exists" change. - -2001-01-02 Dan Winship - - * camel-mime-utils.c (header_content_type_simple): New function to - return just foo/bar with no parameters. - - * camel-data-wrapper.c (get_mime_type): Use - header_content_type_simple rather than header_content_type_format. - -2000-12-28 Dan Winship - - * gmime-content-field.[ch]: Remove this. It was only a thin - wrapper around struct _header_content_type anyway, and didn't - match the naming scheme of anything else. - - * Makefile.am: Remove gmime-content-field.[ch] - - * camel.h: Remove gmime-content-field.h - - * camel-types.h: Add CamelContentType as a typedef for struct - _header_content_type (especially for use outside of camel). - - * camel-multipart.c: - * camel-mime-part.c: - * camel-mime-message.c: - * camel-folder-summary.c: - * camel-folder-search.c: - * camel-data-wrapper.[ch]: Use CamelContentType and - header_content_type_* functions rather than the GMime stuff. - - * camel-mime-part-utils.c: - * camel-medium.c: Remove unused gmime-content-field.h include. - -2000-12-27 Dan Winship - - * providers/pop3/camel-pop3-store.c (connect_to_server): Fix the - APOP check to not crash on servers that don't return any - information on the +OK greeting line. - -2000-12-24 Not Zed - - * providers/imap/camel-imap-search.c (imap_body_contains): Lock - the command channel while searching. - (imap_body_contains): If performing a whole uid search, then add - references to our own summary items, dont look it up in the - folder. This way they can't vanish unexpectedly. - - * providers/imap/camel-imap-folder.h (CamelImapFolder): Added a - private field. - (CamelImapFolder): Removed summary again from here. - - * providers/imap/camel-imap-private.h: Added lock for imap - searches. - - * Merge from camel-mt-branch. - - * providers/imap/camel-imap-folder.c (imap_update_summary): Merge - fix, use the folder->summary. - (imap_get_message_flags, imap_set_message_flags, - imap_get_message_user_flag, imap_set_message_user_flag): Removed - again. - (camel_imap_folder_init): Setup private data/lock. - (imap_finalize): Free private data/search lock. - (imap_search_free): Lock the search_lock. - (imap_search_by_expression): Lock the search lock when using the - search object. Also copy/ref hte summary, rather than getting it - directly. - (imap_refresh_info): Free any info lookups. Use folder->summary - not imap_folder->summary. And lock around commands. - (camel_imap_folder_changed): Use folder->summary again. - (camel_imap_folder_changed): Make sure we unref the summary lookup. - -2000-12-22 Dan Winship - - * providers/imap/camel-imap-store.c (get_folder_info): When - getting the top-level folder list, include INBOX even if it's not - subscribed. Don't show subscribed folders outside of the given - namespace. Do a better job of pruning the namespace from the - returned folder tree. - -2000-12-21 Dan Winship - - * providers/imap/camel-imap-search.c: New CamelFolderSearch - subclass that just reimplements body_contains (using the IMAP - SEARCH command). All other kinds of searching are done against the - local summary. - - * providers/imap/camel-imap-folder.c (imap_search_by_expression): - Use a CamelImapSearch to do searching. - - * providers/imap/camel-imap-utils.c (imap_translate_sexp, etc): No - longer needed. - - * camel-folder-search.h: Add missing CAMEL_FOLDER_SEARCH_TYPE - #define - -2000-12-21 Dan Winship - - * camel-stream-buffer.c (camel_stream_buffer_gets): Update the - doc comment: since it always NUL-terminates the buffer, it reads - at most @max-1 bytes, not @max. - - * camel-remote-store.c (remote_recv_line): Fix the "did - camel_stream_buffer_gets fill the whole buffer" check. Fixes a bug - when reading lines longer than 1024 characters (eg, IMAP SEARCH - responses in very large folders). - -2000-12-19 Dan Winship - - * providers/imap/camel-imap-folder.c (imap_refresh_info): Oops. - Don't do "FETCH 1:0" when the folder is empty. - (imap_protocol_get_summary_specifier): Request RFC822.SIZE too. - (imap_update_summary): Parse RFC822.SIZE and add it to the - summary. - -2000-12-18 Dan Winship - - * providers/imap/camel-imap-summary.c: Add "guint32 server_flags" - to CamelImapMessageInfo to keep track of the last known message - flag state on the server. - (message_info_save, message_info_load): Save/load the - server_flags. - - * providers/imap/camel-imap-folder.c: Make this use - CamelFolderChangeInfo and emit folder_changed notifications as it - gets them rather than only on refresh_info. - (imap_refresh_info): Notice flags that get cleared on the server - as well as flags that get set. - (imap_update_summary): Remove a comment that never actually - applied to the committed code. - -2000-12-15 Dan Winship - - * providers/imap/camel-imap-command.c (camel_imap_command): Change - the semantics of fmt: Now %S (capital S) means an IMAP "string", - (which can be sent as either a quoted string or a literal). If - the server supports LITERAL+, these will be sent as extended - literals (which don't require any special escaping). Otherwise - they'll be sent as quoted strings (and it now properly deals with - " or \ in the string). - (imap_command_strdup_vprintf): Utility routine that does the real - work for the functionality mentioned above. - - * providers/imap/camel-imap-utils.c (imap_quote_string): Turns a - string into a proper IMAP "quoted string". - - * providers/imap/camel-imap-store.c: - * providers/imap/camel-imap-folder.c: Use %S instead of "%s" where - appropriate. - -2000-12-22 Not Zed - - * camel-folder-summary.c (GLOBAL_INFO_UNLOCK): Doh, cut and paste - victim again, call unlock instead of lock! - (summary_assign_uid): Unlock around trying to get a new uid, if we - have a clash. - -2000-12-21 Not Zed - - * tests/folder/Makefile.am (TESTS): reenabled the tests here. - - * providers/nntp/camel-nntp-newsrc.c (CamelNNTPNewsrc): Add a - lock. Made completely mt-safe. Sigh, this is all so i can - support snooping of the set_flags stuff inside camel-nntp-folder, - since i've removed the global folder lock from all of the other - folder summary operations. - (camel_nntp_newsrc_read_for_server): Setup lock. - (camel_nntp_newsrc_get_highest_article_read): Lock internal access. - (camel_nntp_newsrc_get_num_articles_read): - (camel_nntp_newsrc_mark_article_read): - (camel_nntp_newsrc_mark_range_read): - (camel_nntp_newsrc_article_is_read): - (camel_nntp_newsrc_group_is_subscribed): - (camel_nntp_newsrc_unsubscribe_group): - (camel_nntp_newsrc_subscribe_group): - (camel_nntp_newsrc_get_subscribed_group_names): - (camel_nntp_newsrc_get_all_group_names): " - (camel_nntp_newsrc_write_to_file): Lock internal accesses. - (camel_nntp_newsrc_write): Lock around diry stuff. - - * providers/local/camel-maildir-summary.c (maildir_summary_check): - Lock around our internal poking of the summary hashtable/array. - (maildir_summary_sync): And the same here too. - - * camel-folder-summary.c: Moved the summaryprivate data into - camel-private.h. Only needed for the locks really. - (camel_folder_summary_init): Setup locks. - (camel_folder_summary_set_filename): Lock. - (camel_folder_summary_index): lock - (camel_folder_summary_uid): Lock - (camel_folder_summary_next_uid): " - (camel_folder_summary_set_uid): " - (camel_folder_summary_load): Lock around whole load. Hrm, - probably not required. - (camel_folder_summary_save): Lock around whole save, this is - reqwuired, unless we ref/copy the whole list first, and i couldn't - be bothreed. - (camel_folder_summary_add): lock - (summary_assign_uid): Lock around internal accesses. - (camel_folder_summary_info_new_from_parser): Lock around filtr stuff. - (camel_folder_summary_info_ref): Add locking. Could probably use - its own lock? - (camel_folder_summary_touch): Add locking, likewise. - (camel_folder_summary_clear): Lock. If the preiovus two are - changed, then so this will need mroe locking. - (camel_folder_summary_info_free): Lock around refcounting. - (camel_folder_summary_remove): Locking. - (camel_folder_summary_remove_uid): Lock ref, unlock, unref. Also - fixed a bug that would have made this never work, freeing the key, - which isn't allocated. - (camel_folder_summary_remove_index): lock, ref, unlock unref also. - (camel_message_info_ref): Lock using a separate global lock, since - we have no context here. - (camel_message_info_free): Here too. - (content_info_alloc): Use an alocation lock here. avoids races - with setting up content_info_chunks, etc. - (camel_folder_summary_info_new): And here too. - (camel_folder_summary_load): Changed to use a differnet lock for - loading/saving. - (camel_folder_summary_init): Doh, i do need a reflock afterall, - set one up. - (camel_folder_summary_finalize): Free it. - (camel_folder_summary_index): Add a reflock. - (camel_folder_summary_uid): And here too. - (camel_folder_summary_info_free): Use reflock instead of - summary_lock. - (camel_folder_summary_info_ref): Likewise. - (camel_folder_summary_remove_uid): Add reflocking. - (camel_folder_summary_remove_index): And here too. - - * providers/vee/camel-vee-folder.c (camel_vee_folder_new): Setup a - summary object. - (vee_folder_build): Build each item into the real summary object. - (vee_folder_add, vee_folder_add_uid, vee_folder_add_change): New - functions to add a single record to the vfolder summary. - (vee_folder_build_folder): Use a real summary. - (vee_get_uids): Removed, use default impl. - (vee_free_message_info): " - (vee_get_message_info): " - (vee_get_summary): " - (vee_get_unread_message_count): " - (vee_get_message_count): " - (vee_sync): Make vee-folder-sync sync all subordinate folders. - Well i dont think this is right, but enough peopl ehave aksed for - it. - (vee_expunge): Same for expunge. - (vee_set_message_flags): Call parent class, then mirror flags to - subfolder. - (vee_get_message_user_flag): Removed, we just use the default - impl, and our flags should always match. - (vee_set_message_user_flag): Snoop the set and set on subfolder. - (vee_get_message_flags): Removed, jsut use parent impl, assume our - copy matches the real ones. - (get_real_message): Removed. We sort ofneed to keep the - summaryitem refed while we use it, so this doesn't make as much - sense as it did once. - (camel_vee_folder_finalise): Unhook listening events as we unref - folders. - (camel_vee_folder_new): Set the summary messageinfo data size - properly. - (vfolder_remove_match): Fixed for summary change. - (folder_changed): ditto. Also stopped changed items from being - re-searched and possibly removed. Might have to resort to the old - whole-search idea again. - (message_changed): Similarly. Might be easier just not to bother - with a whole search. - - * providers/vee/camel-vee-folder.h: Removes summary - hashtable/array, and use a real summary object. Sigh, more work. - - * providers/nntp/camel-nntp-folder.c (nntp_folder_sync): Move - summary to folder object. - (nntp_folder_get_message_count): Removed, use default impl. - (nntp_folder_set_message_flags): Call parent impl to do the work, - but snoop for newsrc. - (nntp_folder_get_uids): Removed, use default impl. - (nntp_folder_get_summary): " - (nntp_folder_get_message_info): " - (nntp_folder_free_message_info): " - (camel_nntp_folder_new): moved summary to folder class - - * providers/imap/camel-imap-folder.c (camel_imap_folder_init): - Move summary to folder object. - (camel_imap_folder_new): " - (imap_finalize): No longer unref the summary (or infact, do - anything else either). - (imap_refresh_info): move summary to folder object. - (imap_sync): " - (imap_get_message_count): Removed, use default impl. - (imap_get_unread_message_count): " - (imap_get_uids): " - (imap_get_summary): " - (imap_free_summary): " - (imap_get_message_info): " - (imap_free_message_info): " - (imap_get_message_flags): " - (imap_set_message_flags): " - (imap_get_message_user_flag): ", this changes functionality, but - only by providing non-permanent flags. - (imap_set_message_user_flag): " - (imap_update_summary): move summary to folder object, and use - camel_folder_summary_info_new_from_header, instead of calling the - virtual function directly. - - * providers/local/camel-maildir-folder.c (maildir_append_message): - move summary to folder object, again. - (maildir_get_message): " - - * providers/local/camel-mh-folder.c (mh_append_message): move - summary to folder object. - (mh_get_message): " - - * providers/local/camel-mbox-folder.c (mbox_append_message): Move - summary to folder object - (mbox_get_message): " - (mbox_set_message_user_flag): We need our own copy of this, sigh, - so we can track if the xev needs a rewrite (probably, its only a - guide anyway). - (mbox_set_message_user_tag): Same same with this one. - (camel_mbox_folder_class_init): Link in these new virtual functions. - - * providers/local/camel-local-folder.h (CamelLocalFolder): removed - summary. - - * providers/local/camel-local-folder.c (local_get_message_count): - (local_get_unread_message_count): - (local_get_uids): - (local_get_summary): - (local_free_summary): - (local_get_message_info): - (local_free_message_info): - (local_get_message_flags): - (local_set_message_flags): - (local_get_message_user_flag): - (local_set_message_user_flag): - (local_get_message_user_tag): - (local_set_message_user_tag): Removed, all now use default - implementation. - (camel_local_folder_class_init): Removed overrides. - (local_init): Clear folder->summary. - (local_finalize): move summary to folder. - (camel_local_folder_construct): " - (local_sync): " - - * camel-folder.c (free_summary): Provide a real impl. - (get_summary): " - (free_uids): " - (get_uids): " - (free_message_info): " - (get_message_info): " - (set_message_user_tag): " - (get_message_user_tag): " - (set_message_user_flag): " - (get_message_user_flag): " Sigh, the last so far. - (get_message_flags): Sigh, 1 more afterall. - (get_unread_message_count): And and this. - (get_message_count): and this! - (set_message_flags): Sigh, and this. - (camel_folder_finalize): Unref the summary if we have it. - (camel_folder_free_uids): Remove locking. - (camel_folder_get_message_flags): Remove locks, since the summary - is now mt-safe. - (camel_folder_set_message_flags): " - (camel_folder_get_message_user_flag): " - (camel_folder_set_message_user_flag): " - (camel_folder_get_message_user_tag): " - (camel_folder_set_message_user_tag): " - (camel_folder_get_message_info): " - (camel_folder_free_message_info): " - (camel_folder_get_uids): " - (camel_folder_free_summary): " - (camel_folder_get_unread_message_count): " - (get_unread_message_count): Check we got info, no big deal, but - the summary might change while we're counting, and upset the count - slightly. - (camel_folder_get_message_count): Remove locks. - - * camel-folder.h (struct _CamelFolder): Added CamelFolderSummary - to the base folder object. Sigh, this is going to be a lot of - work ... - - * camel-service.c (camel_service_init, finalise): changed - connect_lock to be recursive e_mutex. - - * camel-remote-store.c (camel_remote_store_init, finalise): Changed - stream_lock to recursive e_mutex. - - * camel-private.h (RemoteStorePrivate, ServicePrivate): Use - recursive mutexes for connect_lock & stream_lock. Ick. Because - of the imap code. - - * providers/imap/camel-imap-private.h: Change the command_lock to - be an EMutex. - - * providers/imap/camel-imap-store.c (connect_to_server): Removed - the command_lock stuff. If we are just connected again, it should - be safe to assume we have exclusive access at this point without - it (and yes, removes a deadlock). - (imap_create): Remove a lock that wasn't even supposed to be - there. - (camel_imap_store_finalize, init): g_mutex->e_mutex(E_MUTEX_REC). - Use a recursive mutex since the imap code is multiply recursivly - calling some functions (sigh, it would be nice to fix this). - -2000-12-20 Not Zed - - * camel-folder.c (folder_changed): Change the locks to inside the - if. Stops a deadloc,k and we dont need a lock to read a value. - (message_changed): Likewise. - - * camel.c (camel_init): Blah, comment out g_thread_init, leave it - to the caller, since it can only ever be done once. - - * camel-folder-thread.c (camel_folder_thread_messages_new): Ref - and save the folder in the thread return. Also get the summary - once, and access that for the messageinfo's. Added bonus that now - threads should come out in a similar order. We need to do this so - that the messageinfo's dont get unref'd under us, and using the - summary directly simplifies memory management. - (camel_folder_thread_messages_destroy): Free the summary/unref the - folder. - - * camel-folder-thread.h: Add a folder to CamelFolderThread struct. - -2000-12-19 Not Zed - - * providers/imap/camel-imap-utils.c (imap_translate_sexp): Unref - using e_sexp_unref, since it is no longer an object. - - * tests/lib/camel-test.c: Added a global lock, and made it - thread-aware. - - * camel-exception.c: Add a global lock. Not sure its really - needed here, but it doesn't really hurt. - (camel_exception_clear): Lock around access. - (camel_exception_set): Same. - (camel_exception_setv): " - (camel_exception_xfer): " - - * providers/local/Makefile.am (noinst_HEADERS): Added, for - camel-local-private.h - - * camel-folder.c (camel_folder_search_by_expression): Removed - locking here, now upto the implementing class to lock. - (camel_folder_search_free): Removed the folder lock here too, for - consistency really, and the locking probably wasn't needed. - - * providers/local/camel-local-folder.c (local_get_summary): - Changed to copy/ref the summary items. - (local_free_summary): Unref the summary items/free the array. - (local_get_unread_message_count): Free info lookups. - (local_search_by_expression): Perform more fine-grained locking, - and dont lock the whole folder while searching, just the search - object. Dum de dum, it *would* be possible to not even have to - lock the search, by using our own copy of the search object each - time. Could be investigated. - (local_init): Init priaate data/lock. - (local_finalize): Free private data/lock. - (local_search_free): Also lock around the search object, because - it accesses global data inside. - - * README.mt: Some info about the mt code development. - - * camel-folder-search.c (match_message): Put in a warning, this - plain deadlocks so far, but i'm going to bed now. - (camel_folder_search_finalize): Use e_sexp_unref() since its no - longer an object. - - * camel-session.c (camel_session_init): Init private data/lock. - (camel_session_finalise): Free private data/lock. - (camel_session_register_provider): Lock hash insert. - (service_cache_remove): Lock. - (camel_session_list_providers): " - (camel_session_get_service): Lock the whole function. - - * camel-session.h (struct _CamelSession): Added private data. - - * providers/imap/camel-imap-store.c (camel_imap_store_init): Setup - private data. - (camel_imap_store_finalize): Free private data. - (connect_to_server): Lock around command calls. I dont think its - needed, but it shouldn't hurt either. - (imap_connect): Lock around command calls. Again, I don think it - is needed, but wont hurt. - (imap_disconnect): ditto for this one. - (imap_create): Lock around command. - (get_folder): " - (get_folder_info): " - (subscribe_folder): " - (unsubscribe_folder): " - (imap_keepalive): " - - * providers/imap/camel-imap-folder.c (camel_imap_folder_new): Lock - around calling a command. - (imap_refresh_info): Likewise. - (imap_sync): " - (imap_append_message): " - (imap_copy_message_to): " - (imap_move_message_to): " - (imap_get_message): " - (imap_update_summary): " - (imap_search_by_expression): ", also minor logic cleanup. - (imap_get_summary): Copy/ref the summary items. - (imap_free_summary): And free it now too. - - * providers/imap/camel-imap-auth.c (imap_try_kerberos_v4_auth): - Lock the command stream for the command session. - - * providers/imap/camel-imap-private.h: Private (locking info) - stuff for imap provider. - (CAMEL_IMAP_STORE_UNLOCK): Fix to call unlock, rather than lock! - - * camel-service.c (camel_service_query_auth_types): Lock also for - the connection here, incase the service needs to connect. - - * camel-remote-store.c (camel_remote_store_init): Init private - data/lock. - (camel_remote_store_finalise): Readded, free private data/lock. - (remote_send_stream): Changed to return the number of bytes - written, like a good little stream function should. - (camel_remote_store_send_string): Lock for stream access. - (camel_remote_store_send_stream): Same here. - (camel_remote_store_recv_line): And here. - (camel_remote_store_refresh_folders): Lock the store for cache - access. - (timeout_cb): Lock for stream access. - -2000-12-18 Not Zed - - * camel-service.c (camel_service_init): Init private data. - (camel_service_finalise): Free private data. - (camel_service_connect): Lock around connection access. - (camel_service_disconnect): " - - * camel-service.h (struct _CamelService): Added private field. - - * camel-store.c (camel_store_init): Init private data/lock. - (camel_store_finalize): Free private data/lock. - (camel_store_get_folder): Lock internal calls. - (camel_store_delete_folder): " - (camel_store_rename_folder): " - (camel_store_get_root_folder): " - (camel_store_get_default_folder): " - (camel_store_get_folder_info): " - (camel_store_folder_subscribed): " - (camel_store_subscribe_folder): " - (camel_store_unsubscribe_folder): " - (lookup_folder): Lock accesses to the folder cache. - (cache_folder): " - (uncache_folder): And here too. - - * camel-store.h (struct _CamelStore): Added a private field. - - * Makefile.am (noinst_HEADERS): Add camel-private.h. There is a - comment in that header as to why it ins't installed. - - * camel-private.h: New header for private data, that subclasses - can get to. - - * tests/lib/camel-test.c (camel_test_init): If we do have threads - enabled already, dont call g_thread_init(). - - * tests/lib/folders.c (test_folder_counts): Add free of info. - (test_folder_message): And here too. - - * providers/local/camel-maildir-summary.c (remove_summary): Free - info. - (maildir_summary_check): Free info lookups. - - * providers/local/camel-mh-summary.c (message_info_new): Removed, - didn't add value. - (remove_summary): free info after being used. - (mh_summary_check): Free info lookups. - (mh_summary_sync): and here too. - - * providers/local/camel-mbox-summary.c (summary_update): Free info - lookups. - (mbox_summary_sync_full): Likewise. - (mbox_summary_sync_quick): And here. - (mbox_summary_sync): ... and here. - - * providers/local/camel-maildir-folder.c (maildir_get_message): - Free messageinfo lookups. - - * providers/local/camel-mh-folder.c (mh_get_message): Free - messageinfo lookups. - - * providers/local/camel-mbox-folder.c (mbox_get_message): Free - messageinfo lookups. - - * providers/local/camel-local-summary.c - (message_info_new_from_message): Removed, since it wasn't doing - anything useful. - (message_info_new_from_parser): Same. And some other dead code. - - * providers/local/camel-local-folder.c (local_get_message_info): - deconstify. - (local_free_message_info):new func to free info. - (local_get_uids): - (local_get_message_flags): - (local_set_message_flags): - (local_get_message_user_flag): - (local_set_message_user_flag): - (local_get_message_user_tag): - (local_set_message_user_tag): Free all info lookups. - (local_expunge): Dont call camel_folder_* functions, to avoid a deadlock. - - * providers/nntp/camel-nntp-folder.c - (nntp_folder_get_message_info): deconstify. - (nntp_folder_free_message_info): Free summary item. - (nntp_folder_get_message_flags): Free summary lookup. - (nntp_folder_set_message_flags): and here. - (nntp_folder_get_uids): And here. - - * providers/imap/camel-imap-auth.c: Make base64_*_simple optional - with the HAVE_KRB4 flag. - - * providers/imap/camel-imap-folder.c (imap_free_message_info): - Added a free of the message info. - (imap_refresh_info): - (imap_sync): - (imap_refresh_info): - (imap_get_unread_message_count): - (imap_get_uids): - (imap_get_message_flags): - (imap_set_message_flags): Free any summary lookups. - (imap_get_message_flags): Get the message info directly from the - summary, not via the folder interface. - (imap_move_message_to): Dont call folder functions directly - (delete_message), as it will deadlock since we already have the - lock. - - * providers/vee/camel-vee-folder.c (vee_free_message_info): Free/unref - the messageinfo. - (vee_get_message_info): First ref the internal copy, then return it. - (folder_changed): Free all got message info's. - (message_changed): And here. - (get_real_message): And here. - (vee_folder_build): and here. - (vee_folder_build_folder): ... and here. - - * camel-folder-summary.c (camel_folder_summary_info_new): - Initialise the messageinfo refcount to 1. - (camel_folder_summary_info_free): Down the refcount till we need - to free. - (camel_folder_summary_info_ref): New function to up the refcount. - (camel_message_info_dup_to): Sewt the refcount of the dest to 1. - (camel_message_info_new): Set refcount to 1. - (camel_message_info_new_from_header): Dont allocate the mi - ourselves. - (camel_message_info_free): Handle refcounting. - (camel_message_info_ref): New function. - (camel_folder_summary_index): Ref the messageinfo before returning - it. - (camel_folder_summary_uid): Likewise. - (camel_folder_summary_save): Access the messageinfo array - directly, rather than through accessors (saves ref/unref). - (camel_folder_summary_clear): Likewise. - (camel_folder_summary_remove_index): Likewise. - (main): Free lookups. - - * camel-folder-summary.h (CamelMessageInfo): Added a refcount - value. - - * camel-folder.c (camel_folder_free_message_info): New function to - 'free' a message info. - (camel_folder_get_message_info): Deconstify return. - (camel_folder_lock): New (internal) function to thread-lock the - folder. - (camel_folder_unlock): Likewise for unlocking. - (freeze): - (thaw): Lock around access to folder->frozen/changed_frozen. - (folder_changed): Likewise. - (message_changed): Likewise. - (camel_folder_init): Init private data, locks and moved frozen - info. - (camel_folder_finalize): Free new private data, locks and moved - frozen info. - (copy_message_to): Free the messageinfo after we've used it. - (move_message_to): And here too. - (camel_folder_sync): Lock around virtual method invocation. Just - locking around any virtual method that is known to need it. This - is the first cut at locking. - (camel_folder_refresh_info): " - (camel_folder_expunge): " - (camel_folder_get_message_count): " - (camel_folder_get_unread_message_count): " - (camel_folder_append_message): " - (camel_folder_set_message_flags): " - (camel_folder_get_message_flags): " - (camel_folder_get_message_user_flag): " - (camel_folder_set_message_user_flag): " - (camel_folder_get_message_user_tag): " - (camel_folder_set_message_user_tag): " - (camel_folder_get_message): " - (camel_folder_get_uids): " - (camel_folder_free_uids): " - (camel_folder_get_summary): " - (camel_folder_search_by_expression): " - (camel_folder_free_summary): " - (camel_folder_search_free): " - (camel_folder_move_message_to): " - (camel_folder_copy_message_to): " - (copy_message_to): Dont call any of our own folder functions - directly, otherwise we will deadlock. - (move_message_to): Likewise. - - * camel-folder.h (CamelFolder): Added free_message_info() function - & deconstify get_message_info()'s return. - (CamelFolder): Add a private field (for locks). - (struct _CamelFolder): Moved changed_changed/frozen into private - data, since it really is private and now needs locked access. - -2000-12-15 Jeffrey Stedfast - - * camel-mime-utils.c (header_fold): When checking to see if we - need to fold the header, when we come accross a \n, make sure to - start at p + 1 the next time through the loop or else we get into - an infinite loop. - -2000-12-13 Dan Winship - - * Namespace cleanup: change a bunch of IS_CAMEL_* macros to - CAMEL_IS_* - -2000-12-13 Chris Toshok - - * providers/imap/camel-imap-auth.c: add #include for - freebsd. - -2000-12-12 Christopher James Lahey - - * camel-folder-summary.c, camel-folder-summary.h: Added #ifndef - NO_WARNINGS around a #warning. Added (void) to the prototype and - declaration of camel_message_info_new. - - * camel-mime-message.h: Added an include for - camel-mime-filter-bestenc.h. Added a prototype for - camel_mime_message_set_best_encoding. Reformatted prototypes to - line up. - - * camel-mime-parser.c: Added #if d(!)0 around the states string - lookup table since it's only used in debugging output. - - * camel-seekable-substream.c (stream_flush): Added a cast. - - * providers/imap/camel-imap-auth.c: Added #include . - - * providers/imap/camel-imap-folder.c (imap_refresh_info): Made uid - and flags const to fix warnings here. - - * providers/imap/camel-imap-store.c (get_folder_info): Made p - const to fix warnings here. - -2000-12-12 Dan Winship - - * tests/lib/Makefile.am: Add missing .h file. (From campd.) - -2000-12-11 Not Zed - - * providers/smtp/camel-smtp-transport.c (smtp_data): Remove use of - linewrap filter. Headers are now wrapped. encode_8bit already - enforces a 998 octet line limit. - (smtp_data): Also fixed a memleak, we always have to unref our own - copy of the filters. We also dont need to remove them manually, - so dont bother. The type's an int too ... - - * camel-internet-address.c (internet_unformat): When scanning past - quotes, remove them also. - (camel_internet_address_format_address): If the name contains "'s, - or ','s then strip and quotes and wrap the whole lot in one set of - quotes. - - * Makefile.am (noinst_HEADERS): We dont want to install - camel-charset-map-private.h, ever. There are probably other - similar files ..? - - * camel-mime-part.c (write_to_stream): Fold header lines - appropriately as we're writing them out. - - * camel-mime-utils.c (header_fold): Add a new argument, headerlen, - tells it how long the associated header token is. - (header_fold): Also,k check to see if we need to fold first, using - a better algorithm, and also accept already-folded lines, and - re-process accordingly. - (rfc2047_decode_word): Add a little buffer space to iconv output - for shifting overheads? - (rfc2047_decode_word): finish the iconv with a null call, to flush - shift state, etc. - (rfc2047_encode_word): Attempt to break up long words into - appropriately sized, independent, chunks. See rfc2047, section 2. - (header_decode_mailbox): Dont add in extra spaces into the output - if we are decoding adjacent encoded words. We can only guess this - case, as some broken mailers put encoded words inside quoted - words. - (header_encode_phrase): Dont merge words if they are going to end - up too long. Also change back ot only merge consecutive words of - the same type. e.g. 'foo. blah fum.' -> "foo." blah "fum." or - 'iam an. idiot' -> iam "an." idiot - - * camel-medium.c (camel_medium_set_header): Hrm, we actually want - to call set_header, not add_header here, probably explains some - duplicate X-Evolution headers i was trying to track down. Also - changed the api to handle a NULL value == remove the header. - - * providers/local/camel-maildir-summary.c - (maildir_summary_decode_x_evolution): Always return error, we dont - use x-evolution for maildir. - (maildir_summary_encode_x_evolution): Always return a NULL string, - likewise. - (maildir_summary_add): Hook in here, since the _new function - doesn't have access to any flags from the caller. If we have - flags, then update the filename again. Not ideal, but should - work. - -2000-12-08 JP Rosevear - - * tests/message/Makefile.am: Remove test3 from build until the files - show up - -2000-12-09 Not Zed - - * camel-mime-message.c (camel_mime_message_set_date): Change the - sign of the default date offset when none is supplied. - (camel_mime_message_set_date): Also do dst if its dst (forward 1 - hour). Fixes #928 + some. - -2000-12-06 Not Zed - - * tests/lib/camel-test.h (check): Change line no format so that - emacs can detect it. - -2000-12-06 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_refresh_info): We want - to bitwise-or the server and cached flags here so that we keep the - flags that we have set locally and set any additional flags that a - parallel connection may have set. - -2000-12-05 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_data): If the data - wrapper fails to be written to the stream, unref it and the - filters before returning. - -2000-12-05 Dan Winship - - * providers/imap/camel-imap-folder.c (imap_get_message): use - BODY.PEEK[] rather than RFC822, so the message doesn't get marked - as \Seen. - (imap_refresh_info): Fix a really really really dumb bug. - -2000-12-05 Dan Winship - - * providers/imap/camel-imap-folder.c (imap_set_message_flags): Fix - the check for "flags aren't actually changing". - - * providers/local/camel-local-folder.c (local_set_message_flags, - local_set_message_user_flag, local_set_message_user_tag): Don't - emit message_changed unless the flags actually changed. - - * providers/nntp/camel-nntp-folder.c - (nntp_folder_set_message_flags): Don't emit message_changed unless - the flags actually changed. Fix the check for marked as seen. - -2000-12-05 Not Zed - - * camel-seekable-substream.c (stream_flush): stream_flush does - make sense for a substream afterall (if you have a stream_write). - (stream_write): Implement this. - (stream_seek): Change the STREAM_END behaviour to be more sane. - if bounded go from the end of the bound, if unbounded, go from the - end of the parent stream. - - * camel-stream-mem.c (stream_read): Dont return error if reading - past the end of data, just return 0. - - * camel-stream-fs.c (camel_stream_fs_init): Initialise the stream - to be unbound. - (stream_seek): Fix the logic when seeking from the end of an - unbounded stream. - (camel_stream_fs_new_with_fd): If the fd is invalid (-1), then - return NULL immediately. - (stream_seek): Range check a SEEK_END so it fits within - bound_start. - -2000-12-01 Not Zed - - * tests/lib/folders.c (test_folder_basic): New test to perform - basic store operations on folders (taken from folders/test1). - (test_folder_message_ops): Tkane the guts out of folders/test2. - -2000-12-04 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_connect): i18n-ize - exception strings. - (get_name): And here. - (_send_to): Here too. - (smtp_helo): And here and there... - (smtp_mail): And around the square... - (smtp_rcpt): Saying catch me if you can... - (smtp_data): And here three. - (smtp_rset): And here. - (smtp_quit): And finally here. - -2000-12-01 Jeffrey Stedfast - - * camel-folder-search.h: Added system_flag to CamelFolderSearchClass - - * camel-folder-summary.c (camel_system_flag_get): Convenience - function to return whether or not a flag is set using a string as - the flag name. - (camel_system_flag): Return the integer value of the flag string. - - * camel-folder-search.c (search_system_flag): New ESExp callback - for allowing vfoldering on CamelMessageInfo flags. - -2000-12-01 Dan Winship - - * camel-service.c (camel_service_disconnect): Don't - g_return_if_fail if the service is already disconnected. Just - return. - - * providers/pop3/camel-pop3-store.c (pop3_try_authenticate): - Return FALSE (don't try again) if we get CAMEL_POP3_FAIL. - (pop3_connect): If we don't succeed, disconnect. - -2000-11-30 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c - (parse_list_response_as_folder_info): Fix a possible bug where - 'name' could be uninitialized. - - * camel-folder-summary.c (camel_message_info_new): New convenience - function, doesn't do much but it sure makes code cleaner to read. - (camel_message_info_new_from_header): This one makes my life heaven. - -2000-11-30 Jeffrey Stedfast - - * providers/imap/camel-imap-summary.c (camel_imap_summary_new): - Handle the case where the summary failed to load - clear the - summary and then set the dirty bit so that it is sure to save - later. Is this the right fix? - -2000-11-30 Dan Winship - - * camel-exception.c (camel_exception_setv): Remove unused - variable. - -2000-11-30 Not Zed - - * providers/local/camel-mbox-folder.c (mbox_get_message): Remove - assertion that content is there, when it no longer can be. - - * camel-folder-summary.h: Removed pos/bodypos/endpos from - camelmeessagecontentinfo. - (CamelMessageFlags): Added an attachments flag. - - * providers/local/camel-local-summary.h: Added load virtual - function. - - * tests/lib/folders.c (test_message_info): Accessors. - (test_folder_message): " - - * camel-folder-thread.c (get_root_subject): Fix accessors. - (dump_tree_rec): " - - * camel-folder-search.c (camel_folder_search_execute_expression): - Accessors for messageinfo. - (search_match_all): " - (search_header_contains): " - (search_header_contains): " - (search_body_contains): " - (camel_folder_search_execute_expression): Use mepool_strdup. - - * providers/local/camel-mbox-summary.c (summary_update): Accessors - for messageinfo. - (mbox_summary_sync_full): " - - * providers/local/camel-mh-summary.c (remove_summary): Accessors - for messageinfo. - (mh_summary_check): " - (mh_summary_sync_message): " - (mh_summary_sync): " - - * providers/local/camel-mh-folder.c (mh_append_message): Use - accessor for uid. - - * providers/local/camel-local-summary.c - (local_summary_decode_x_evolution): Use accessor to uid. - (local_summary_encode_x_evolution): Likewise. - (message_info_new): And here. - (camel_local_summary_load): Call virtual load function. - (local_summary_load): Default load function, load summary. - (camel_local_summary_load): Check file exists before trying to - load. - (camel_local_summary_construct): Turn off building content info! - (CAMEL_LOCAL_SUMMARY_VERSION): Bump, since we dont build content - info anymore. - (camel_local_summary_load): After a successful load/check, do a - save too so we dont have to go through it again randomly. - - * providers/nntp/camel-nntp-utils.c (get_XOVER_headers): Use - accessors for messageinfo. - - * providers/nntp/camel-nntp-folder.c (nntp_folder_get_uids): Use - accessors for uid. - - * providers/imap/camel-imap-folder.c (imap_refresh_info): Use - accessor for uid. - (imap_sync): Likewise. - (imap_get_uids): Likewise. - (imap_update_summary): And here. - - * providers/vee/camel-vee-folder.c (vfolder_remove_match): Use - accessor for uid. - (vfolder_add_match): Handle estrv stuff. - (vfolder_change_match): Accessor for uid. - (get_real_message): " - (vee_get_uids): " - (vee_folder_build): " + estrv. - (vee_folder_build_folder): " - - * providers/local/camel-maildir-folder.c (maildir_append_message): - Use acccessors for uid's. - (maildir_get_message): Here too. - - * providers/local/camel-maildir-summary.c - (camel_maildir_summary_init): Setup the string count for us. - (message_info_new): Access the string array directly. - (message_info_free): No need to free string if using array. - (camel_maildir_summary_info_to_name): Use accessor to get to uid. - (remove_summary): And here. - (maildir_summary_check): Likewise. - (maildir_summary_sync): And here. - (maildir_summary_load): Load up a cache of uid->filename mappings - before loading the actual summary file. This saves us having to - waste the diskspace storing the filenames in the summary itself, - and also helps us sync the summary better on load. - (message_info_load): If we have the load_map setup, and the uid - exists, then set the filename cache from it, and update the flags - from the name, incase our summary mismatches it. - - * camel-folder-summary.c (camel_folder_summary_init): Setup string - count for compressed info record. An optional compile mode which - stores all strings for a given messageinfo into a packed array, - which should save 36-50 bytes/record. - (camel_folder_summary_info_new): Init the string array. - (message_info_new): Set the string array items, as required. - (message_info_load): And here too. - (message_info_save): Use accessors to get to strings. - (message_info_free): Free strings as one. - (camel_message_info_dup_to): Handle packed array case. - (camel_folder_summary_add): Use accessors. And pack the strv - before storing it. - (summary_assign_uid): New function to assign a unique uid to a - message, if it doesn't have one. - (camel_folder_summary_add): Call assign_uid instead of doing it - ourselves. - (camel_folder_summary_info_new_from_parser): " - (camel_folder_summary_info_new_from_message): " - (camel_folder_summary_encode_string): constify. - (camel_folder_summary_encode_token): " - (summary_build_content_info_message): Fix accessors to messageinfo. - (CAMEL_FOLDER_SUMMARY_VERSION): Bumped, for removal of - contentinfo->pos data. - (camel_folder_summary_info_new_from_parser): Calculate the size - based on the parser position, not the removed contentinfo stuff. - (camel_folder_summary_info_new_from_message): Remove size stuff. - (camel_folder_summary_offset_content): Removed, no longer means anything. - (content_info_new): - (content_info_load): - (content_info_save): - (summary_build_content_info): Remove stuff for contentinfo->pos*. - (summary_build_content_info): Take a msginfo argument, set - attachments flag if we find any attachments. - (summary_build_content_info_message): set attachments flag if we - find any attachments. - (camel_folder_summary_info_new_from_parser): Always scan the - content info, even if we dont save it. - (camel_folder_summary_info_new_from_message): And here too. - (summary_build_content_info): Only create the contentinfo stuff if - we have it turned on, otherwise just parse and discard. - (summary_build_content_info_message): Likewise. - -2000-11-29 Jeffrey Stedfast - - * camel-store.c (camel_store_get_folder): Updated the gtk-doc - comment. - -2000-11-29 Dan Winship - - * camel-mime-utils.c: - * camel-mime-filter-charset.c: Use iconv instead of unicode_iconv. - - * providers/imap/camel-imap-command.c (imap_read_untagged): Fix - some off-by-one-ness. - - * camel-stream-buffer.c (stream_read): Fix another bug found in - previously-unused code here. - -2000-11-29 Ettore Perazzoli - - * tests/lib/Makefile.am (INCLUDES): `$(top_srcdir)' for builddir - != srcdir compilation. - -2000-11-29 Not Zed - - * tests/message/test2.c (main): Add a missed unref. - - * camel-stream-mem.c (camel_stream_mem_set_buffer): We must set - ourselves as the owner of the byte-array. - Weird, someone has modified this file (its been reindented), but i - can't see any changelogs ... - - * tests/lib/messages.c (content_finalise): Fix memleak in tester, - free byte array when our content object is deleted. - - * camel-folder-search.c (camel_folder_search_finalize): Yeah - great, so the sexp is a gtk object, not a camel object. Isn't - that going to be fun to fix? - - * camel-session.c (camel_session_finalise): Free the storage path. - - * providers/local/camel-local-store.c (camel_local_store_init): If - store->folders is setup, free it first, then overwrite. Hmm, - this seems a bit crappy to me. - - * camel-store.c (camel_store_init): Dont setup store->folders if - its already setup. - - * camel-exception.c (camel_exception_setv): Removed a memleak. no - need to strdup after a strdup_printf!!! - - * camel-address.c (camel_address_finalize): Free the address - ptrarray, once finished. - - * providers/local/camel-local-folder.c (local_finalize): Make sure - we dont leave the folder locked on close. - (local_finalize): Free summary/search. - - * providers/local/camel-mh-summary.c (mh_summary_next_uid_string): - Small memleak, always free name after using it. - - * camel-mime-part.c (set_content_object): Free txt after setting - the header. - - * providers/local/camel-maildir-summary.c (maildir_summary_check): - Fix a memleak, close the dir after scanning new. - (message_info_free): Added so we can free the filename cached in - the messageinfo. - (camel_maildir_summary_finalise): Free the hostname. - - * tests/folder/test[12].c (main): Clear out camel-test before - starting. - - * providers/local/camel-mbox-summary.c (mbox_summary_sync_quick): - Because encode_x_evolution folds the line (sigh, because - encode_param does, unlike every other function in - camel-mime-utils), unfold the encoded result before comparing. - (mbox_summary_sync_quick): Another small memleak, free xevnew once - finished with it. - - * camel-mime-utils.c (header_decode_quoted_string): Removed a - redundant check for c=0. - (header_unfold): New function to un-fold headers. - - * providers/local/camel-local-summary.c - (local_summary_encode_x_evolution): some problems with encoding - tags, using the wrong output strings. - (local_summary_encode_x_evolution): We dont need to append a ; - either, param_list_format_append() will do it for us. - -2000-11-28 JP Rosevear - - * camel-lock.c: No longer hard code the enabled lock types - -2000-11-28 Dan Winship - - * camel-remote-store.c (remote_recv_line): Don't set exception to - g_strerror (errno) when nread == 0, because it won't have been - set. - - * providers/pop3/camel-pop3-folder.c (pop3_finalize): Don't try to - free things if they haven't been set yet. - -2000-11-28 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_connect): Clear the - exception if EHLO fails before trying HELO in the cases where the - SMTP provider doesn't announce its ESMTPness. - -2000-11-28 Not Zed - - * providers/local/camel-maildir-summary.c - (camel_maildir_summary_init): Set the info size's properly, oops! - - * tests/lib/folders.[ch]: Folder testing helpers. - - * tests/folder/test2.c: Test basic message ops on folders. - - * tests/folder/test1.c (main): Test basic folder ops on (local) - stores. - - * providers/local/camel-local-provider.c - (camel_provider_module_init): Removed some debug. - - * providers/local/camel-maildir-folder.c - (camel_maildir_folder_class_init): fix parent class. - - * providers/local/camel-mh-folder.c (camel_mh_folder_class_init): - Fix parent class (damn cut & paste). - - * providers/local/camel-maildir-store.c (get_folder): Call parent - impl. - (camel_maildir_store_class_init): Fix parent class setup. - (delete_folder): Check the folder exists before trying to delete - it. - (delete_folder): Try and make the delete operation atomic/rollback - failures. e.g. if one directory isn't empty, then create the - other empty ones back. Also clear the tmp directory fully first. - - * providers/local/camel-mbox-store.c (get_folder): Call parent - impl. - (camel_mbox_store_class_init): parent class is camel_local_store, - not camel_folder, oops. - (delete_folder): Return an error if it doesn't exist, rather than - covering it up. - - * providers/local/camel-mh-store.c (get_folder): Call parent impl. - (camel_mh_store_class_init): fix parent class setup. - (delete_folder): Error if it doesn't exist now. - - * camel-folder.c (camel_folder_move_message_to): - (camel_folder_copy_message_to): Added warnings as these functions - are going to be removed later. - - * camel-store.c (camel_store_get_root_folder): Fix for an early - api change. We want CAMEL_STORE_FOLDER_CREATE, not TRUE, since - its a flag. - (camel_store_get_default_folder): And here too. - - * providers/local/camel-local-store.c (xrename): Handle renaming - folders differently to renaming files. - (get_default_folder_name): local stores dont have a default - folder, so make it so. Or at least, it doesn't seem to make sense - to have one. - (get_root_folder_name): Same for root. - (get_folder): Added parent implementation, that makes sure the - service path exists, if we are creating a new folder (but doesn't - create the folder). - -2000-11-27 Not Zed - - * providers/local/camel-local-store.c (xrename): Fixed races. Use - link/unlink, rather than rename, to properly detect overwriting - another file. And allow some files to be missing. - -2000-11-28 Radek Doulik - - * providers/local/camel-local-summary.c - (local_summary_decode_x_evolution): add scan = scan->next; to - avoid infinite loop - -2000-11-27 Dan Winship - - * providers/imap/camel-imap-command.c (imap_read_untagged): Make - this gratuitously more complicated. No wait, I mean, fix bugs. Now - fully handles NULs in the data stream (which "can't happen" but - do) and also handles responses containing multiple literals. Also - does less copying than the original code. - - * camel-stream-buffer.c (stream_read): Fix a bug that could make - it lose sync and/or overrun buffers. - -2000-11-27 JP Rosevear - - * providers/local/.cvsignore: shush - -2000-11-27 Not Zed - - * providers/Makefile.am: Removed mh, mbox, added local, to the default. - -2000-11-24 Not Zed - - * tests/data/getaddr.pl: little util to scan mailboxes for any and - every address they contain. - - * tests/message/test2.c (main): Added a bunch of stuff to test - decoding/reencoding/etc of internationalised addresses. - - * tests/message/lib/address-data.h: Copy of some unicode/other - testing data. **Beware** of editing this file in emacs, it'll - probably try and convert all the characters to something - unusable. - - * tests/lib/camel-test.c (camel_test_break): Add a debugger hook - point. - - * camel-mime-utils.c (quoted_encode): Check for space and convert - to _ separately. - (header_decode_mailbox): Fixed the 'check comments for realname' - code, problem was the domain getting code was skipping all - whitespace/comments before we could get a look-in. This is - approximate but fairly robust. - (header_decode_text): Dont use the c-type isspace func here, we - want a specific whitespace only. - (header_decode_text): If we have decoded words next to each other, - do not insert whitespaces between them, which is what rfc2047 requires. - (header_decode_text): Make c unsigned too. - - * tests/README: Added at least some explanation of all this stuff. - - * tests/lib/camel-test.h (check_msg): Added a non-gcc version of - the fail command, we dont get the expression that failed, but no - matter. Should be (more) portable now. - (check, check_msg): Put the file/lineno in the default message. - - * Makefile.am (SUBDIRS): Add tests. - - * camel-mime-filter-basic.c (filter): Well, I'll add the extra - bytes here too, lathough not strictly needed, might save a - re-malloc when we get to complete(). - - * camel-mime-filter-charset.c (filter): Make sure we have room if - we only convert very short data. - (complete): and here too. - - * tests/Makefile.am: Initial test harness & tests. Requires gcc - for this. - - * camel-internet-address.c (d): Turn off debug. - - * camel-charset-map.c (camel_charset_step): Oops, & masks for set - intersection, not | them. Dunno how this got even close to - working. - -2000-11-23 Not Zed - - * camel-mime-filter-basic.c (filter): For base64 encoding, the - output size for 0, 1, or 2 bytes of input can exceed input*2, so - make sure we account for that as well. - (complete): And here. - (complete): Similarly for qp encoding, if we have a trailing - space, we need some extra bytes (not needed for 'filter()', as any - such bytes are stored in state/save). - - * camel-mime-utils.c (quoted_decode_step): Removed fixme not required. - (quoted_encode_close): Dont append a trailing afterall. Otherwise - a pass through the encode/decode will grow the message each time. - -2000-11-22 Radek Doulik - - * camel-mime-utils.c (header_msgid_generate): check for return - values - -2000-11-21 Dan Winship - - * camel-lock.c: - * camel-movemail.c: add #ifdef HAVE_ALLOCA_H - -2000-11-21 Not Zed - - * providers/local/camel-mh-summary.c (mh_summary_sync_message): - Shite, -1 on error, >=0 on success. So i've just been truncating - all the messages I touched, good one zed. - (mh_summary_sync_message): Sigh, and write to the right damn fd as - well. - (mh_summary_sync_message): Argh, and we need to compare the length - of the old xev -1 to the new xev, to check if we can optimise it. - - * camel-folder.c (camel_folder_change_info_new): Init the pool. - (camel_folder_change_info_add_source): Allocate string in the - pool. - (camel_folder_change_info_add_source_list): - (camel_folder_change_info_add_update): No longer free the key, as - it cannot be yet. - (change_info_add_uid): Add a new arg, copy, telling it whether to - copy the uid argument or not, and copy using mempool_strdup. - (change_info_cat): Tell add_uid to copy the string. - (camel_folder_change_info_add_update): Call add_uid directly. - (change_info_remove): Call add_uid directly, with no copy, and - dont free the key. - (change_info_free_update): No longer required since we dont malloc - the keys. - (camel_folder_change_info_add_uid): Fix for add_uid change. - (camel_folder_change_info_remove_uid): - (camel_folder_change_info_change_uid): - (change_info_clear): No longer needed, just set the size to 0 on - the array directly. - (camel_folder_change_info_clear): Empty the arrays directly, and - flush the mempool too, and also clear uid_source, incase anyone - was silly enough to call us in the wrong order. - (camel_folder_change_info_free): Dont bother clearing the array's - contents, just free the pool and throw away all the indexes. - - * camel-folder.h: Added a mempool to CamelFolderChangeInfo to - store the uid's we get. - - * camel-folder-search.c (search_match_all): If we are only - matching a single info, just use that/do the search. - (camel_folder_search_match_expression): New function. Matches a - single message info against an expression. - (camel_folder_search_init): Init a hash table used to map the - returned gptrarrays' to mempools. - (camel_folder_search_execute_expression): Store all of the string - data in a mempool, slightly faster, less wasted space (usually),. - (camel_folder_search_free_result): Check for the mempool that - stores the data for the list, and free that if we have it, - otherwise assume we need to use g_free() (which should only happen - if the list is empty at the moment). - : commented out the debugging prints. Got sick of 'executing - header search' crap. - - * providers/vee/camel-vee-folder.c (camel_vee_folder_init): Init - changes. - (camel_vee_folder_finalise): Free changes. - (vfolder_add_match): Simple helper to add a new matching info - record. - (camel_vee_folder_add_folder): Only trigger a changed event if we - have changes. - (vfolder_change_match): New function, changes our local vfolder - info to match the source. - (vfolder_add_match): Add a new info to the vfolder list. - (vfolder_remove_match): Remove a no-longer matching info from the - vfolder summary. - (message_changed): check if the message still matches, and - remove/etc as required. - (camel_vee_folder_finalise, init): init/free search object. - (vee_folder_build_folder): Build the changes to the folder into - the changes data, as we go. - (folder_changed): If the folder gave us an explicit list of - changes, then process each one separately (unless there's a lot - added/changed). - - * providers/vee/camel-vee-folder.h: Added a changes field to the - folder. - - * Makefile.am (libcamel_la_SOURCES): Added - camel-folder-thread.[ch]. - - * camel-folder-thread.c: message-threading algorithm, taken from - evolutions' mail component, as it is generally more useful than - just for evolution itself. Changed to use e-memchunks as well to - speed it up a little and use less mem. - -2000-11-20 Jeffrey Stedfast - - * camel-remote-store.c (remote_recv_line): Fixed to return the - correct bytecount in all cases which is the real fix to - imap_parse_nstring. - - * providers/imap/camel-imap-command.c (imap_read_untagged): Again, - don't use strlen for the post-data, use 'n'. - - * providers/imap/camel-imap-utils.c (imap_parse_nstring): Undo my - previous temp-fix. - -2000-11-20 Not Zed - - * providers/nntp/camel-nntp-utils.c (get_XOVER_headers): Fixes for - the summary messageid changes. Hash the messageid and store it. - (get_XOVER_headers): Use camel_folder_summary_info_new() to create - the summary item before adding it. - - * camel-folder-summary.h (CamelMessageInfo): Changed the - messgae-id to be an 8 byte md5 hash, and the references list to be - an array of these. - - * providers/local/camel-mh-summary.c (mh_summary_sync_message): - New function, sync out the message info stuff. Only updates the - X-Ev header if it can get away with it, otherwise writes out a - whole new message. - (mh_summary_sync): Added more functionality. All summary info is - now written to the X-Ev header, etc, and new messages re-written - if required during the sync process. - - * providers/local/camel-local-folder.c - (local_set_message_user_flag): Set the XEVCHANGE flag. - (local_set_message_user_tag): And here too. - - * providers/local/camel-local-summary.h: New flag - CAMEL_MESSAGE_FOLDER_XEVCHANGE to indicate the XEV header has - probably changed size and needs to be rewritten in whole. - - * camel-folder-summary.c (next_uid_string): Want this static, not - const. - (message_info_new): Store the references and message-id values as - 64 bit, binary hashes. - (message_info_load): fix for message-id/references changes. - (message_info_save): Likewise. - (camel_message_info_dup_to): And here. - (camel_message_info_free): And here too. No longer free - message_id, and simple free for references array. - (CAMEL_FOLDER_SUMMARY_VERSION): Bumped file revision. - (camel_folder_summary_init): Init memchunk allocators to empty. - (camel_folder_summary_finalize): Free memchunk allocators if - there. - (message_info_new): Use the chunk allocator to allocate message - info's. - (camel_folder_summary_info_new): New helper to allocate the - message info, and setup the memchunk if required. - (content_info_alloc): Likewise for content info's. - (message_info_load): Use summary_info_new_empty. - (content_info_new): Use content_info_alloc. - (content_info_load): " - (content_info_free): Free the content info as a memchunk. - (message_info_free): Free everything directly and the base as a - memchunk, rather than calling camel_message_info_free(), which - assumes a malloc'd array. - - * providers/local/camel-local-summary.c: Include ctype.h, kill a - warning. - (local_summary_decode_x_evolution): If we get a NULL message info, - then dont try and set anything, just check for validity. - (camel_local_summary_write_headers): New function to write a set - of headers to an fd. - (camel_local_summary_check): Added some statistic generation - stuff for memory profiling. - - * providers/local/camel-mbox-summary.c (header_write): Changed to - use stdoi functions to write out the header to a buffered stream, - instead of using writev, which is apparently slow (and writing - each line separately is slow anyway). - (mbox_summary_sync_full): New implementation. Does things - differently, doesn't use or require the content info stuff. - (summary_rebuild): Dont return an error if we start scanning at - the end of file. - (mbox_summary_sync_full): If we are not writing out new headers, - make sure we copy the From line as we go, and update frompos - appropriately. - (mbox_summary_sync_full): Always copy the From line from the - existing one, rather than trying to make one up ourselves. - (mbox_summary_sync): If we can get by with a quick-sync, then try - it, if that fails, then try a full sync anyway. - (mbox_summary_sync_quick): Quick sync. Only update system flags, - etc. - (mbox_summary_sync_full): Use the proper local summary encode_xev - function. - (header_evolution_decode): Removed, no longer needed. - (header_evolution_encode): Same. - (copy_block): No longer needed, removed. - (header_write): Removed, replaced with - camel_local_summary_write_headers. - (mbox_summary_sync_full): Fixed for header_write change. - - * camel-mime-parser.c (folder_scan_step): Implement the new - optional parser state HSCAN_PRE_FROM, that returns the (currently - unfiltered) input data. - (folder_scan_drop_step): Do the right thing for the PRE_FROM - state. - (camel_mime_parser_scan_from): Update the doco. - (camel_mime_parser_scan_pre_from): Ok, make this behaviour - optional, it simplifies a lot of loops that dont otherwise need to - know about it. - (folder_scan_step): Made the PRE_FROM state optional. - (struct _header_scan_state): Made the bool vars 1 bit. - (folder_pull_part): Free the from_line buffer if it is there. - (folder_scan_skip_line): Added a new arg, can save the skpped data - to a byte_array, as we go. - (folder_scan_step): Fixed calls to skip_line approrpiately. Now - we save the from line as we parse it. - (camel_mime_parser_read): New function to read from the mime - parser buffer directly. Useful if you use the parser to read the - first/some headers, then need to scan the rest of the data, - without needing to use a seek(), or allocate your own buffers. - - * camel-mime-parser.h (struct _header_state): Added a new parser state, - pre-from which returns any data found before a from line during - parsing (all other data can be retrieved by the caller except - this). - -2000-11-17 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c (imap_parse_nstring): When - extracting a literal string, capture up until the end of the last - line - this we we don't lose any data if the byte count is off. - - * providers/imap/camel-imap-command.c (imap_read_untagged): Use - the byte-read count to decrement the number of bytes left to read - rather than using strlen. Not only does this protect against a DoS - (embedded NUL chars in the literal string would make strlen - inaccurate) but it also improves performace a little. - - * camel-remote-store.c (remote_recv_line): *Sigh* Return the - number of bytes read on success rather than 0. Also don't use - camel_stream_buffer_read_line since we can't get an accurate octet - count. - -2000-11-17 Not Zed - - * providers/local/camel-local-summary.c (local_summary_add): Clear - the NOXEV/FLAGGED bits, since we do have an xev header. um m, - maybe this is right, this assumes a write is following. Maybe - this should be done in folder::append() instead ... - - * camel-stream-buffer.c (camel_stream_buffer_gets): We should - always terminate the string. No need to check outptr is in range, - its already been checked. - - * providers/local/camel-mbox-summary.c (mbox_summary_sync): When - we update the summary, do it from mbox_summary->folder_size, not - the content info endpos (which isn't any good anymore anyway). - - * providers/local/camel-mbox-folder.c (mbox_append_message): Set - the frompos from the current folder size, since summary_add wont - have initialised it to anything useful. - -2000-11-16 Not Zed - - * providers/local/camel-local-summary.c - (local_summary_encode_x_evolution): Check the uid string is all - digits before trying to write a 'standard' x-ev header. - - * providers/local/camel-maildir-summary.c - (camel_maildir_summary_info_to_name): Convert an info into a - maildir name:info filename. - (camel_maildir_summary_name_to_info): Convert a name:info filename - into an info, and tell us if it didn't match it. - (message_info_new): When creating a new filename, gets its info - from the flags field. Likewise if creating from an existing file, - extract the flags. - (maildir_summary_sync): Remove a small memleak. Also, if our - flags and that requires a filename change, perform that here. - (message_info_new): Get the received date from the filename. - Also, dont overwirte the uid if we have one. - (maildir_summary_check): Sort the summary in received order before - completion. - (maildir_summary_next_uid_string): Test the name for collusions - before we give it out. Retry, and if that fails, well, I guess we - collide :( - - * providers/local/camel-mbox-folder.c (mbox_lock): Implement mbox - locking. - (mbox_unlock): And unlocking. - (mbox_append_message): Lock the folder for write before doing - anything. - (mbox_get_message): Lock the folder for read before doing - anything. - - * providers/local/camel-local-folder.c (camel_local_folder_lock): - Implement something here. We handle the recursive ability but - pass the locking to the folder itself. - (camel_local_folder_unlock): Likewise for unlocking. - (local_lock): Default - do nothing, return success. - (local_unlock): Same. - (local_sync): Changed slightly for locking api changes, and also, - only lock around the sync process itself. - - * camel-lock.c: New file - utility functions for locking using - different strategies and/or for locking folders safely. - - * Makefile.am (libcamel_la_SOURCES): Adde camel-lock.[ch] - -2000-11-15 Radek Doulik - - * camel-mime-utils.c: mime_guess_type_from_file_name moved back to - composer as it introduced unwanted VFS dependency - removed #include - -2000-11-15 Not Zed - - * providers/Makefile.am: Removed local again, not quite ready. - -2000-11-14 Not Zed - - * camel-folder-summary.c (message_info_new_from_message): Use - message_info_new to create the summary from headers, instead of - getting directly from the message. - (format_recipients): No longer required. - - * providers/Makefile.am (SUBDIRS): Added local. - -2000-11-11 Not Zed - - * camel-mime-parser.c (folder_push_part): Make sure 'atleast' is - at least 1, always. This is possibly a temporary fix for a - bad failure mode on bad multipart messages. - (folder_scan_content): Go until inend, not inend+1. Changed the - continuation and retry logic to be simpler and more robust. If we - can't find a marker within - the atleast we need, just set it to 1, and try again, rather than - just going to the next smaller limit (boundary check checks the - length anyway). - (header_append): streamline the empty line case. And strip - trailing \r's if there are any (\n's already stripped). - (folder_scan_header): Reordered and cleaned up a lot. Check for - continuation only once, and compress lwsp then. Assume the header - buffer already has end of line's stripped, and simplify some things: - Only check for end of headers once and easier. - Dont check to remove end of line character - Dont bother testing inptr-start if we get a boundary match - it is - always zero. - (folder_scan_header): Removed the unused part variable, and a few - pointless assignments. - (folder_scan_header): Change the end limit to be 1 higher, to make - sure we get all content. - (folder_scan_content): And here too. - (folder_scan_header): Killed a warning. - (folder_push_part): Removed a bad comment. Actually - boundarylenfinal can be zero for a new message not in a - multipart. So we fix that here. - -2000-11-09 Not Zed - - * camel-mime-utils.c (header_decode_param_list): Renamed from - header_param_list_decode. - (header_param_list_decode): New external function to decode a - parameter list. - (header_param_list_format_append): Made public. - (header_param_list_format): Another new public helper function for - formatting just a param list. - - * camel-folder-summary.c (next_uid_string): Default implementation - is the same as before. - (camel_folder_summary_class_init): And set it up. - - * camel-folder-summary.h: Make next_uid_string a virtual function. - - * camel-folder.c (camel_folder_change_info_changed): New function - to return true if the changeset contains any changes. - -2000-11-14 Jeffrey Stedfast - - * camel-stream.c (camel_stream_printf): Don't cast an int to a - ssize_t. - -2000-11-10 Dan Winship - - * providers/mbox/camel-mbox-summary.c - (camel_mbox_summary_build_from): put a space before a single-digit - day of the month since it seems some mailers are fantastically - picky about this. (bugs.gnome.org #27232) - -2000-11-10 Radek Doulik - - * camel-mime-utils.c (header_msgid_generate): fix ids ending with '.' - -2000-11-09 Dan Winship - - * providers/imap/camel-imap-auth.c (imap_try_kerberos_v4_auth): - Fix error handling. (Only send a "*" to bail out of authentication - if the server hasn't already bailed on us.) - -2000-11-08 Radek Doulik - - * camel-mime-utils.c (mime_guess_type_from_file_name): new - function, moved from composer - -2000-11-08 Not Zed - - * camel-mime-message.c (find_best_encoding): Keep track of the - caller bestenc flags that make sense. - - * camel-mime-filter-bestenc.c (filter): Added code to detect when - we have "^From " lines in the sequence of text. - (camel_mime_filter_bestenc_get_best_encoding): Added a new flag - CAMEL_BESTENC_NO_FROM: if set, it will not allow any lines - matching "^From " to appear in the output - currently forcing - base64 encoding to achieve this. - - * camel-mime-parser.c (folder_scan_step): Call - camel_mime-filter_complete() once we're done, rather than - filter_filter(). - (folder_scan_content): Some fixes for state changing; so that when - we do find another boundary it is properly flagged. Since we - strip the last \n off all data, we must take that into account - too. Sigh. Fixes a rather nasty set of bugs where multipart - messages could start including following messages as parts, etc. - (struct _header_scan_stack): Added new parameter, - boundarylenfinal, which holds the length of the final boundary, if - it is different (e.g. for From lines, whihc aren't) - (folder_scan_step): Setup teh boundarylenfinal value when creating - a new boundary. - (folder_scan_content): Hmm, if we hit the end-of-buffer sentinal, - reset the scanner back to leave 'atleast' chars in the buffer - still, dump that content, and retry again. Stops us losing a - check for a boundary on some data we haven't really looked at yet! - (folder_scan_content): Use boundarylenfinal to calculate - 'atleast'. - (folder_scan_header): And here too. - (folder_boundary_check): Use the atleast value directly, dont - truncate it. Use the boundarylen/boundarylenfinal values directly - too. - (struct _header_scan_stack): Add an atleast parameter to cache the - atleast info. - (folder_push_part): Determine/set 'atleast', every time we add a - new part. - (folder_scan_header): Get the cached atleast info from the current - part. - (folder_scan_content): And here too. - (folder_scan_header): Fix a problem where a part starting with - " text" would be interpreted as a followon header wrongly. - - * camel-mime-filter-charset.c (complete): Add some assertions to - find a bug. - -2000-11-07 Ettore Perazzoli - - * camel-service.c (get_name): Strdup the "???" string you return, - so that the expected semantics for `::get_name()' is respected. - -2000-11-07 Dan Winship - - * camel-stream-filter.c (d): Kill debugging, as it causes lots of - evolution-mail spewage. - -2000-11-07 Not Zed - - * camel-mime-filter-bestenc.c (complete): Implement a complete() - function, now we need one. - (filter): Upgraded to match rfrc2045 properly. Checks also for - length of line and valid CRLF sequences. - (camel_mime_filter_bestenc_get_best_encoding): Do the work of - working out what is the best encoding given what we found about - the stream. - - * camel-mime-part.c (camel_mime_part_encoding_to_string): Use a - lookup table to get the encoding naem, and add the binary type. - (camel_mime_part_encoding_from_string): Likewise for the reverse. - - * camel-mime-part.h: Added the binary encoding type, see rfc2045. - - * camel-mime-utils.c (header_param_list_format_append): Dont put a - space before ;'s in parameter lists, makes them more - readable/consistent. - - * camel-mime-message.c (multipart_has_8bit_parts): Cleaned up the - old stuff, well removed it. - (camel_mime_message_set_best_encoding): Added another argument - that lets you select what you want to set the best of. i.e. for - smtp transport we only need 7 bit, and dont need to optimise the - charset (although of course, we should always). - (find_best_encoding): Implement this feature, if we are not - getting the best charset, use the one we have. - (best_encoding): Set the charset on the part appropriately. Sigh, - the interfaces for this are nonexistant. - (find_best_encoding): Tell the bestenc filter that lf should be - treated as crlf for the purposes of determining encodings. - -2000-11-06 Not Zed - - * camel-charset-map.c (camel_charset_init): Init function for an - iterative charset determinator. - (camel_charset_step): Iterate another buffer. - (camel_charset_mask): Removed, since it couldn't have worked. - (camel_charset_best): Use the iterative interface to do the work. - (camel_charset_best_name): Get the best name for a charset so far. - - * camel-mime-filter-bestenc.c: New class, a stream - filter that can be used to memory-efficiently determine the best - encoding and/or charset to use for a given stream of bytes. - - * Makefile.am (libcamelinclude_HEADERS): Added stream-null*. - (libcamel_la_SOURCES): Added bestenc* - - * camel-stream-null.c: New class, a null-stream, that always - succeeds, and never has any contents. - - * camel-stream.c: Minor pointless changes. Was going to do - something else but changed my mind. Added trivial default - implementations for all callbacks. - - * camel-mime-message.h: Cleaned up some old cruft. - - * camel-folder-summary.c (camel_folder_summary_format_address): - address_list_format() no longer encodes, so we dont need to decode - it. - - * camel-address.c (camel_address_unformat): New function, attempts - to reverse the formatting process on display addresses. - (camel_address_length): New function to get the number of - addresses, without having to peek the structure. - - * camel-mime-message.c (camel_mime_message_set_from): Fix a typo. - (camel_mime_message_finalize): Only unref from/reply_to if we have - it. - (camel_mime_message_set_recipients): New function - set the - recipients as a CamelInternetAddress. This function effectively - deprecates the older recipient setting functions. - (camel_mime_message_add_recipient): What the hell, i'll bite the - bullet. Terminate this function. The old api was ambiguious and - inefficient and didn't work right anyway. - (camel_mime_message_remove_recipient_address): And this one. - (camel_mime_message_remove_recipient_name): And this one too. - (camel_mime_message_set_recipients): If we set an empty header, - then remove it from the header list. Allow a null receipient - object to clear a header. - (camel_mime_message_set_from): Likewise, if setting an empty from - address. - (camel_mime_message_encode_8bit_parts): Eeek!! - camel_stream_mem_new_with_byte_array owns the byte_array we give - it, so make sure we dont free any of it! - (camel_mime_message_encode_8bit_parts): Infact, i'll just rewrite - the whole lot, its a bit of a mess. Should really rename it and - make it a little more useful too, lets see ... - (best_encoding): This has a string interface? Oh boy. - (camel_mime_message_foreach_part): New experimental function to - iterate over all message parts. Might not remain. - (camel_mime_message_has_8bit_parts): New implementation using - foreach_part. Fixed a couple of problems. - (find_best_encoding): New function, that finds the best encoding - for a given part (will probably be moved to camel-mime-part), and - also the best charset to use if it is a text part. Since one - affects the other it is a two pass process, but uses streams and - not memory to achieve this. - (camel_mime_message_set_best_encoding): Uses the function above to - configure an entire message for the best encoding possible given - transport constraints. - (camel_mime_message_encode_8bit_parts): Reimplemented to use the - function above to perform the work. - - * camel-internet-address.c - (camel_internet_address_format_address): Dont put <> around a lone - address with no real name. - (camel_internet_address_encode_address): Similarly. - (internet_decode): Actually return the count of decoded addresses. - (internet_unformat): Implement the unformatting routine. - -2000-11-05 Not Zed - - * providers/smtp/camel-smtp-transport.c (_send_to): Changed to get - the internetaddress directly, rather than having to parse it - itself. - - * camel-address.c (camel_address_format): Added a new function - which will format address, suitable for display. - (camel_address_cat): Concatentate 1 camel address onto another. - It is upto the caller to ensure the addresses are of compatible - types. - (camel_address_new_clone): New function to create a new address by - copying an existing one of the same type. - (camel_address_copy): New helper function to copy an address. - - * camel-mime-message.h (struct _CamelMimeMessage): Removed cached - copy of date string. - (struct _CamelMimeMessage): Added date_received info. - - * camel-mime-message.c (camel_mime_message_get_date_string): - Removed. Nothing uses it anyway, and it is redundant. - (camel_mime_message_finalize): No more date_str. - (camel_mime_message_init): No more date_str, initialise - date_received* - (write_to_stream): Change the check for a date header. - (process_header): No longer track the date_str. - (camel_mime_message_get_received_date): Removed. totally invalid - anyway. - (camel_mime_message_get_sent_date): Removed. Redundant. The only - 'date' is the sent date, the received date is just made up. - (camel_mime_message_get_date): Args changed to be more consistent - with utility functions. - (camel_mime_message_get_date): Dont set the date when we're asked - for it (if its not set by the time its written, it'll be set - then). - (camel_mime_message_get_date_received): Actually do 'the right - thing' here, if we have a received header, use that to determine - the received date. And return the data in the same format as - get_date. - (camel_mime_message_set_from): Changed the api to better match - what we should be doing. Pass a camelinternetaddress, etc. - (camel_mime_message_set_reply_to): Cahnged similarly to take an - internetaddress. - (camel_mime_message_get_reply_to): Likewise. - (camel_mime_message_finalize): Unref the from/reply_to objects. - (format_address): Removed, no longer needed. - (process_header): Changed to store the from/reply_to as - internetaddress's. - (write_to_stream): Set the from header directly to empty, if we - dont have one. Maybe we should just abort, and/or create one - based on the current user. - - * camel-mime-utils.c (header_address_list_format): Renamed to - header_address_list_encode, which is what it is actually doing. - (header_address_list_format_append): Similarly. - (encoding_map[]): Removed, no longer used. - (header_address_list_encode_append): Take another arg, do we - encode the address (for internet), or not (for display - utf8 - only). - (header_address_list_format): Re-added this function, but now it - generates a display version only. Surprise surprise, that is all - anythign needs to generate anyway. Sigh. - - * camel-internet-address.c (camel_internet_address_get): Return - false if we get an invalid index only. - (camel_internet_address_encode_address): Helper function to encode - a single address for mailing. - (internet_encode): Use the above function to format it. - (camel_internet_address_format_address): Format a single address - for display. - (internet_format): Implement the display version. - (camel_internet_address_class_init): Init the internet_format - virtual function. - (internet_cat): Implement virtual function to concatenate - addresses. - - * camel-folder-summary.c - (camel_folder_summary_info_new_from_header): new function, only - build the summary info, dont add it. - (camel_folder_summary_info_new_from_parser): Likewise, for new - info from parser. - (camel_folder_summary_add_from_parser): Cahnged to call function - above to build info. - (camel_folder_summary_add_from_header): Changed to call function - above, to build info. - (camel_folder_summary_info_free): New function to free the summary - message info. - (camel_folder_summary_clear): Changed to clal above to free info. - (camel_folder_summary_remove): Likewise. - (camel_folder_summary_add): Cleaned up the clashing uid - re-assignment logic a little bit. - (camel_folder_summary_decode_uint32): Fixed a typo, 01 != -1. - (camel_folder_summary_decode_time_t): Return -1 on error. - (camel_folder_summary_encode_off_t): New function to encode an - off_t type. - (camel_folder_summary_decode_off_t): And likewise for the reverse. - (CAMEL_FOLDER_SUMMARY_VERSION): Bumped the summary version, since - we're now encoding time/off_t's right. - (summary_header_save): Use time_t encoder to save the timestamp. - (summary_header_load): Likewise for decoding the timestamp. - (content_info_load): Decode off_t types directly, now we can. - (content_info_save): And likewise for encoding. - (camel_folder_summary_add_from_message): New function, create a - summary item from an existing message and add it. - (camel_folder_summary_info_new_from_message): New function, create - a summary item from an existing message. - (summary_build_content_info_message): New function to do the dirty - work of building the conent info/indexing, from a message source. - (format_recipients): Format an internetaddress suitable for the - summary. - (message_info_new_from_message): Build a new summary item from a - mime message. - (content_info_new_from_message): Build a new conent info from a - mime part. - (camel_folder_summary_class_init): Init the new class functions. - (message_info_new_from_message): Fixed for message api change. - - Added documentation to the functions. - -2000-11-03 Radek Doulik - - * camel-mime-utils.c (header_msgid_generate): new function, - generates simple message/content id - -2000-11-04 Not Zed - - * camel-mime-part-utils.c - (camel_mime_part_construct_content_from_parser): Set the - preface/postface from the parser into the multipart object. - - * camel-multipart.c (camel_multipart_set_postface): Function to - set the postface text on a multipart. - (camel_multipart_set_preface): Similarly for preface text. - - * camel-mime-parser.c (folder_scan_content): If we scan until a - boundary, then we do not include the \n that starts the boundary - line in the content. - (struct _header_scan_stack): Added a ByteArray to store the - multipart pre/post-text as we're scanning. - (folder_pull_part): Free pre/posttext if they are allocated. - (folder_scan_step): Build into the pre/posttext arrays as we - encounter data. - (camel_mime_parser_preface): REturn the multipart preface text, if - there is any scanned. - (camel_mime_parser_postface): Likewise for postface text. - (byte_array_to_string): helper function for above. - - * providers/mbox/camel-mbox-folder.c (mbox_append_message): Change - the from line to be "\nFrom ..." always, so no need to - check/append a \n to messages. - (mbox_append_message): Open the output stream with append mode - [assuming this is more efficient than seeking to the end] - And dont prepend \n on the From line if its the first in the - mbox. - (mbox_append_message): Pass the offset of the real start of the - "From " line when we perform the update (which may != 'seek') - - * camel-mime-filter-charset.c (complete): Removed the terminating - NUL 'fix'. - - * camel-stream-filter.c (do_read): Added some debug. - (do_flush): And here. - (do_write): And here too. - (do_write): ARGH!!! ARGH! Ok, so the filter stream was writing a - different number of bytes than the requester was asking it to - write (because of filtering, of course!). So instead of returning - the true number of written bytes, we'll return what they asked us - to write - unless there is an error in which case we return -1. - - * camel-mime-utils.c (base64_encode_close): Sigh, forgot to make - it unsigned. I think this is actually a gcc bug as (48 >> 2) - somehow ended up negative, when it obviously should not, even if - the data load was signed. - -2000-11-03 Jeffrey Stedfast - - * camel-url.c: Undo my incorrect fix - I misunderstood danw - - sorry! - -2000-11-03 Dan Winship - - * providers/pop3/camel-pop3-store.c (camel_pop3_store_expunge): - Unbreak this. - -2000-11-03 Jeffrey Stedfast - - * camel-url.c (camel_url_to_string): If show_pass, then base64 the - password before writing it to the output string. - (camel_url_new): Assume password has been base64 encoded and - decode accordingly. - -2000-11-03 Dan Winship - - * camel-provider.h: Add an "url_flags" field to CamelProvider. - Move the CAMEL_SERVICE_URL_* defines here and remove the SERVICE_ - part of the name. - - * camel-service.h: Remove CAMEL_SERVICE_URL_* flags and - service->url_flags field. - - * camel-service.c (check_url, get_path): Get URL flags from - service->provider, update for changed flag names. - - * providers/*/camel-*-provider.c: Add URL flags to provider - structures. - - * providers/*/camel-*-{store,transport}.c, camel-remote-store.c: - Remove service->url_flags initialization. - -2000-11-02 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (get_folder_info): Quote - foldernames when sending to the IMAP server because the folder - name might contain spaces. - -2000-11-02 Not Zed - - * Merged in camel-incremental-branch. - -2000-11-01 Dan Winship - - * providers/imap/camel-imap-store.c (get_folder_info): Remove old - subbed folders from hash table after freeing them. - - * providers/imap/camel-imap-folder.c (imap_get_full_name): Deal - correctly with namespace == "" - -2000-11-01 Gediminas Paulauskas - - * camel-charset-map.c, camel-charset-map-private.h: synced all charsets - with ones found in libunicode. Just include more "iso/*.h" and rebuild - ...private.h with this. - -2000-10-31 Dan Winship - - * camel-service.c (service_disconnect): Add a new argument, clean, - that says whether or not to try to disconnect cleanly. - - * camel-remote-store.c (remote_send_string, remote_send_stream, - remote_recv_line): disconnect uncleanly on failure to prevent - infinite loops when providers would normally send commands from - disconnect(). Remove some unneeded CamelException goo. - - * providers/smtp/camel-smtp-transport.c (smtp_disconnect): - * providers/pop3/camel-pop3-store.c (pop3_disconnect): - * providers/nntp/camel-nntp-store.c (nntp_store_disconnect): - * providers/imap/camel-imap-store.c (imap_disconnect): Don't send - QUIT/LOGOUT if !clean. - -2000-10-30 Dan Winship - - * providers/imap/camel-imap-auth.c: New file with code for IMAP - authentication mechanisms. (Currently just krb4, and without - integrity/privacy protection). - - * providers/imap/Makefile.am: Add camel-imap-auth.[ch] and krb4 - CFLAGS/LDFLAGS - - * providers/imap/camel-imap-store.c (connect_to_server): Split out - from imap_connect. Just does the basic connect and CAPABILITY - check. Redo the CAPABILITY code more robustly. - (query_auth_types_connected): Do this right rather than punting to - query_auth_types_generic. Check for KERBEROS_V4 if compiled with - krb4 support. - (query_auth_types_generic): Mention KERBEROS_V4 if compiled with - krb4 support. - (imap_connect): Use connect_to_server(). - - * camel-mime-utils.c (base64_encode_step, base64_encode_close): - Take an additional argument, "break_lines", saying whether or not - to add '\n's to the output. - - * camel-multipart.c (set_boundary): - * camel-mime-filter-basic.c (filter, complete): Update for base64 - api change. - -2000-10-30 Peter Williams - - * providers/imap/camel-imap-store.c (unsubscribe_folder): Correct - parameters to g_hash_table_lookup_extended. - -2000-10-29 Dan Winship - - Improved IMAP namespace handling: leave the namespace in the - folder names rather than constantly prepending it and stripping it - off. Also some subscription fixes. - - * camel-store.c (camel_folder_info_build): Fix for the case where - @top isn't in @folders. - - * providers/imap/camel-imap-folder.c (camel_imap_folder_new): Add - a "short_name" argument rather than figuring it out ourselves. - (imap_get_full_name): Implementation of CamelFolder::get_full_name - that strips off namespace so the user doesn't have to see it. - (imap_append_message, imap_copy_message_to, imap_move_message_to): - Use folder->full_name rather than calling - camel_imap_store_get_folder_path. - - * providers/imap/camel-imap-utils.c (imap_parse_list_response): - Update this: make @flags a bitmask and @sep a char rather than a - string. Make all of the out arguments optional. Handle literals in - the server response. - - * providers/imap/camel-imap-store.c (imap_connect): Do a better - job of getting the correct dir_sep for the namespace we're using. - Construct a base_url here that will be used by get_folder_info. - (camel_imap_store_folder_path): Removed - (imap_folder_exists): Add an argument to return the short name of - the folder (parsed out of the LIST response). Update for - imap_parse_list_response change. - (get_folder): Update for the various other changes. - (get_folder_info): Update for the various other changes. Be more - consistent about the returned layout: put everything underneath - the "namespace" directory, including INBOX, even if it doesn't - belong there. Don't destroy the list of subscribed folders until - we've actually gotten the new list. - (folder_subscribed, subscribe_folder, unsubscribe_folder): Use - folder_name directly rather than camel_imap_store_folder_Path. - - * providers/imap/camel-imap-command.c (camel_imap_command): Update - for folder name changes. - -2000-10-29 Dan Winship - - * camel.h: Remove md5-utils.h include since it's not part of Camel - any more. - - * camel-charset-map.c: Kill some warnings. - - * providers/nntp/camel-nntp-grouplist.c - (camel_nntp_get_grouplist_from_file, camel_nntp_grouplist_save): - Clean up warnings about time_t casts. - - * providers/smtp/camel-smtp-transport.c: Remove unused md5-utils.h - include. - - * providers/pop3/camel-pop3-store.c: Undefine the "_" macro - defined by krb4's des.h when compiling with krb support. - Fix md5-utils.h include. - -2000-10-27 Dan Winship - - * camel-mime-utils.c (header_param_list_format_append): Only quote - Content-type parameters when the quoting is mandatory, and deal - with embedded quotes/backslashes when quoting. - -2000-10-27 JPR - - * providers/pop3/Makefile.am: Tidy up build - - * providers/smtp/Makefile.am: ditto - - * Makefile.am: Move md5-utils.[hc] to e-util because the - addressbook is going to use md5 hashes for pilot syncing. - Maybe the calendar conduits as well because this is a good idea - Chris had. - -2000-10-26 Kjartan Maraas - - * camel-exceptions-list.def: Add newline to kill warnings. - -2000-10-25 Dan Winship - - * providers/imap/camel-imap-store.c (get_folder_info): Fix folder - listing code infinite loop. - - * camel-store.h: Add a "parent" field to CamelFolderInfo. - - * camel-store.c (camel_folder_info_build): Deal with "parent" - (camel_store_folder_subscribed, camel_store_subscribe_folder, - camel_store_unsubscribe_folder): Add g_return_if_fails checking - that the folder supports subscriptions. - - * providers/imap/camel-imap-store.c (folder_subscribed, - subscribe_folder, unsubscribe_folder): Remove "+ 1"s since the - mail subscribe UI won't prepend / to the folder names now. - (get_folder_info): Clear the "parent" field of the folderinfos - when removing an empty top level. - - * providers/nntp/camel-nntp-store.c (nntp_store_folder_subscribed, - nntp_store_subscribe_folder, nntp_store_unsubscribe_folder): - Remove "+ 1"s since the mail subscribe UI won't prepend / to the - folder names now. - -2000-10-24 Chris Toshok - - * providers/imap/camel-imap-store.h: add subscribed_folders. - - * providers/imap/camel-imap-store.c (camel_imap_store_class_init): - fill in vtable entries for subscription functions. - (camel_imap_store_finalize): new function, so we can free up our - subscribed_folders hashtable. - (camel_imap_store_init): set CAMEL_STORE_SUBSCRIPTIONS in the - CamelStore flags, and create our subscribed_folders hashtable. - (camel_imap_store_get_type): camel_imap_store_finalize is our - finalize function. - (get_folder_info): if we're looking at subscribed_only, clear out - the subscribed_folders hashtable, use LSUB instead of LIST, and - insert folder paths (prepended by their namespace if there is one) - into subscribed_folders. INBOX subscription support needs work, - since we always show it, regardless of it's subscribed state. - (folder_subscribed): new function. just look up the folder_path - in the hashtable. - (subscribe_folder): new function. use the imap SUBSCRIBE command, - and if successful add it to the hashtable. - (unsubscribe_folder): new function. use the imap UNSUBSCRIBE - command, and if successful remove it from the hashtable. - -2000-10-24 Dan Winship - - * providers/imap/camel-imap-store.c (get_folder_info): Fill in the - message_count and unread_message_count flags (if !fast). - -2000-10-23 Dan Winship - - * camel-object.h: #include gnome-i18n.h (and gnome-defs.h since - the former depends on it.) - - * *: Add lots of _() and N_(). - -2000-10-23 Chris Toshok - - * providers/nntp/Makefile.am (libcamelnntpinclude_HEADERS): add - camel-nntp-types.h. - -2000-10-23 Dan Winship - - * providers/imap/camel-imap-command.c (imap_read_untagged): Fix a - "how could this have been working before" memory overrun bug - found by Vlad. - - * camel-op-queue.[ch], camel-thread-proxy.[ch]: These should have - gone away a long time ago. - -2000-10-20 Chris Toshok - - * providers/Makefile.am (SUBDIRS): re-enable the nntp provider. - -2000-10-20 Chris Toshok - - * providers/nntp/camel-nntp-store.c (build_folder_info): add - function to build a tree from the nntp group names (using '.' as a - heirarchy separator.) #ifdefed INFO_AS_TREE only. - (build_folder_info_from_grouplist): if INFO_AS_TREE is selected, - call build_folder_info instead of appending a new CamelFolderInfo - to our list. - (ensure_news_dir_exists): use e_mkdir_hier instead of failing if a - parent directory (~/evolution/news generally) isn't there. - -2000-10-19 Chris Toshok - - * camel-folder-search.c: #include before - -2000-10-19 Dan Winship - - * providers/imap/camel-imap-utils.c (imap_parse_list_response): - Fix a bug with "INBOX" (or anything else with NIL hierarchy - separator) as the namespace. - - * providers/imap/camel-imap-folder.c (imap_refresh_info): Emit - message_changed and folder_changed as appropriate. - -2000-10-19 Dan Winship - - * camel-folder.c (camel_folder_refresh_info): Update comment here - so refresh_info isn't just for reconnects any more. Make the - default implementation a no-op rather than an error. - - * providers/nntp/camel-nntp-folder.c: Move refresh_info impl into - camel_nntp_folder_new, since it would have leaked memory and not - done anything useful if it was called later. - - * providers/mbox/camel-mbox-folder.c: Remove no-longer-necessary - refresh_info impl. - - * providers/imap/camel-imap-folder.c (camel_imap_folder_changed): - Update imap_folder->exists, but don't actually load the new - messages. This is a temporary workaround to deal with the IMAP - provider stealing the message list focus at annoying times. - (imap_copy_message_to, imap_move_message_to): Emit a - folder_changed by hand, for now. - -2000-10-19 Ettore Perazzoli - - * providers/imap/Makefile.am (libcamelimapinclude_HEADERS): Add - `camel-imap-stream.h'. - - * Makefile.am (libcamelinclude_HEADERS): Add `camel-charset-map.h' - and `camel-charset-map-private.h'. - -2000-10-18 Jeffrey Stedfast - - * camel-mime-part.c (camel_mime_part_set_description): The correct - fix this time - the description should be encoded here and not in - the camel-medium layer. - -2000-10-30 Not Zed - - * camel-folder.c (camel_folder_change_info_add_update): Fixed the - changeset logic, which was completely wrong. - -2000-10-27 Not Zed - - * camel-mime-utils.c (quoted_encode_step): Removed is_blank() stuff. - (header_decode_init): When we set the 'space' bit, dont clear all - the others. - (quoted_encode): Put back the safemask. Yes we totally need it, - see rfc 2047 section 5, parts (1) and (3). - (CHARS_PSPECIAL): Remove '=' and '_' from the list of allowed - characters (this is an allowed list, not a not-allowed list, like - the ESPECIAL). - (camel_mime_special_table): Updated for fixes to definitions. - (CHARS_ESPECIAL): Added '_' to list of characters that should be - encoded. - -2000-10-26 Not Zed - - * providers/mbox/camel-mbox-summary.c (camel_mbox_summary_update): - Use the new camel_folder_change_info_* stuff to build the update - diff, rather than doing it ourselves. - - * camel-folder.c (camel_folder_change_info_add_source): Add a - 'source' list, used to create change lists. - (camel_folder_change_info_add_source_list): Add a list of uid's, - convenience function. - (camel_folder_change_info_add_update): Add a uid to the list of - uid's in the new updated list. - (camel_folder_change_info_add_update_list): Add a bunch of uid's - at once for the same purpose. - (camel_folder_change_info_build_diff): Take the source list, the - update list, and find the differences, building on the added or - removed list as appropriate. - -2000-10-20 Not Zed - - * providers/mbox/camel-mbox-summary.c (removed_uids): REnamed from - add_uid. - (camel_mbox_summary_update): Oops, fix the reversed logic for - determining the uid changesets. - - * camel-folder.c (message_changed): Oops, we want to change the - uid, not add it. - -2000-10-19 Not Zed - - * providers/mh/camel-mh-summary.c (camel_mh_summary_sync): Added a - change list argument, and add expunged uid's to it. - - * providers/mh/camel-mh-folder.c (mh_init): Setup the change list. - (mh_finalize): And free it. - (mh_sync): Track changes, and send a folder_changed signal as - appropriate. - (mh_expunge): Likewise. - (mh_append_message): Add the new uid to the change list and - trigger a folder_changed event. - - * providers/mbox/camel-mbox-folder.c (camel_mbox_folder_new): - Setup a mbox list of changes structure. - (mbox_finalize): And free it. - (mbox_expunge): Include the change list with the folder_changed - event, and clear it off. - (mbox_sync): And the same for when we are just syncing the folder. - (mbox_append_message): And do the same here, after we've updated - the folder. - - * providers/mbox/camel-mbox-summary.c - (camel_mbox_summary_build_from): Use gmtime_r to get the time - thread-safely. - (camel_mbox_summary_sync): Added a changeinfo argument. Add any - removed or changed messages to the changelists as appropriate. - (camel_mbox_summary_update): Added a changeinfo argument. - Genereate a list of added/removed uid's based on the difference - before and after rebuilding the summary. - - * camel-folder.c (camel_folder_change_info_new): - (camel_folder_change_info_add_uid): - (change_info_add_uid): - (camel_folder_change_info_remove_uid): - (camel_folder_change_info_change_uid): - (change_info_clear): - (camel_folder_change_info_clear): - (camel_folder_change_info_free): - (change_info_cat): - (camel_folder_change_info_cat): Bunch of utility functions for - working with change info lists. - (camel_folder_init): Init the change info list. - (camel_folder_finalize): And free it. - (thaw): Changed to pass through a list of changes, or to get the - changed message uids from the camelfolderchangeinfo struct, and - reset it. - (folder_changed): Add the changed lists to the frozen change list - if we are frozen. - (message_changed): Add the message to the changed list if we are - in the frozen state. - - * camel-folder.h (CamelFolderChangeInfo): New structure to hold - information for the folder_changed event. - -2000-10-18 Ettore Perazzoli - - * camel-mime-filter-charset.c (complete): Put a zero at the start - of the outbuf. - -2000-10-18 Not Zed - - * camel-mime-part.c (add_header): No, we must not encode the - headers here. These interfaces ARE raw interfaces as they are - defined in camel_medium. Also removed a bogus/meaningless FIXME. - (set_header): Likewise here, we must not. - (process_header): Removed another bogus comment. - - * camel-object.c (shared_is_of_type): Comment out the spitting of - a big warning when we're trying to determine types from code. - - * providers/mbox/camel-mbox-summary.c - (message_info_new_from_parser): Only call ibex funcitons if we - have an index. - - * providers/mh/camel-mh-summary.c (camel_mh_summary_add): Only - call ibex functions if we have an index. - (remove_summary): Likewise. - (camel_mh_summary_check): Likewise. - - * providers/nntp/camel-nntp-store.c (nntp_store_get_folder): - get_folder -> flags argument. - - * providers/vee/camel-vee-store.c (vee_get_folder): create->flags. - - * providers/pop3/camel-pop3-store.c (get_folder): Changed create - -> flags. - - * providers/imap/camel-imap-store.c (get_folder): Added flags - argument. - - * providers/mh/camel-mh-folder.c (camel_mh_folder_new): Added - flags argument, and fixed code appropriately. - - * providers/mh/camel-mh-store.c (get_folder): Added flags argument. - - * camel-folder-search.c (message_body_contains): Perform a regex - match on the contents of messages. This wont quite work yet as - message contents are encoded when written to a stream. - (build_match_regex): Converts a number of strings into a regex - matching pattern, escaping special chars. - (match_message): match a single message from a folder, by uid. - Slow. - (search_body_contains): Changed to support matching where no index - is supplied. Matches are performed by retrieving message - contents, etc. - () WTF? camel should not be including any widget headers. - - * providers/mbox/camel-mbox-folder.c (camel_mbox_folder_new): - Added flags argument. - (mbox_refresh_info): Changed into a NOP, the refresh info code - moved into the new function. - (camel_mbox_folder_new): If we have an index requested, build one, - otherwise, remove an old one, or just dont do anything. - - * providers/mbox/camel-mbox-store.c (get_folder): Changed create - to flags, changed code to suit. - - * camel-store.c (camel_store_get_folder): Changed create to flags. - (get_folder_internal): And here. - (get_folder): And here too. - - * camel-store.h (camel_store_get_folder): Change the create - argument to be a flags argument. - -2000-10-17 Dan Winship - - * providers/imap/camel-imap-folder.c (imap_refresh_info): Remove - cached info at the end of the summary when the folder shrinks - between sessions. Also remove an untrue comment. - (camel_imap_folder_new): Move the summary creation to after the - folder selection again, since it depends on the uidvalidity - having been set. - - * providers/imap/camel-imap-store.c (get_folder): Fix up - summary_file to not include the namespace twice. - -2000-10-17 Jeffrey Stedfast - - * camel-mime-part.c (set_header): Encode the header value. - (add_header): Same. - -2000-10-17 Not Zed - - * camel-mime-filter.c: Added some malloc check debugging stuff. - - * camel-mime-parser.c - (struct _header_scan_state): Removed top_part, top_start, and - pending. I can't even remember why they were there, and they're - not used anymore. - - * camel-mime-filter-basic.c (filter): Forgot to up the space here - too. - -2000-10-14 Not Zed - - * camel-mime-filter-basic.c (complete): Ok, so we hit a fixme, 3x - just wasn't enough for some sequences. - -2000-10-16 Jeffrey Stedfast - - * providers/imap/camel-imap-command.c - (imap_read_response): Don't imap_next_word(respbuf + 2), instead - use imap_next_word(respbuf) or else we'll skip over the second - token. - -2000-10-16 Jeffrey Stedfast - - * providers/imap/camel-imap-command.c - (camel_imap_response_extract): Don't free 'resp' as it doesn't - point to the beginning of the allocated data, instead free - response->untagged->pdata[i]. Also, if '*resp' is equal to a space - character, then set resp = imap_next_word (resp) rather than - expecting resp++ to work (there's a list broken IMAP daemons that - like to put extra spaces between tokens). - (imap_read_response): Don't expect 'respbuf+2' to be where the - untagged number response to start (see above fix for an - explanation). - -2000-10-16 Chris Toshok - - * camel-service.c (get_path): when using the construct (flags & - CAMEL_SERVICE_URL_NEED_*) make sure to do ((flags & - CAMEL_SERVICE_URL_NEED_*) == CAMEL_SERVICE_URL_NEED_*) - (check_url): same. - -2000-10-16 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (imap_disconnect): Only send - the LOGOUT command if the store is connected. - (imap_connect): Set the 'connected' state to TRUE when we - successfully connect. - (get_folder_info): if (!topfi), 'topfi' was allocated but then - 'fi' was set. I think Dan meant to set topfi since fi is an - uninitialized value at this point. - - * providers/imap/camel-imap-command.c (imap_read_response): Check - for the untagged BYE response and set the 'connected' state to - FALSE if we receive the BYE response. Return NULL if we get a BYE - response. - -2000-10-16 Dan Winship - - * providers/imap/camel-imap-store.c (get_folder_info): Deal with - the possibility of not getting a LIST response back for the top - level. - -2000-10-12 Dan Winship - - * providers/imap/camel-imap-summary.c: Simple subclass of - CamelFolderSummary that also keeps a UIDVALIDITY value (and - doesn't, for the moment, build content info). - - * providers/imap/camel-imap-folder.c: - (various): Use a CamelImapSummary to store/fetch summary info. - (camel_imap_folder_new): Take a path to a file to use for the - summary. Set the folder's permanent_flags correctly according to - the server response. Read in the summary (checking the - UIDVALIDITY) and update it if it's out of date. - (imap_refresh_info): Just fetch UIDs and flags. If the UIDs all - match, update the flags as needed and be done with it. Otherwise, - delete messages that have been expunged from the server and fetch - full summary info for any new messages. - (imap_sync): Save the summary to disk. - (imap_update_summary): Renamed from imap_get_summary_internal. Can - now be told to get summary for only a subset of messages. Use - camel-mime-utils functions rather than rolling our own header - parsing. - (imap_get_message_info_internal): Merged into imap_update_summary. - (imap_set_message_flags): Don't marked the message FOLDER_FLAGGED - if we're not actually changing the value of any of the flags. - (camel_imap_folder_changed): Deal with EXISTS rather than RECENT. - - * providers/imap/camel-imap-store.c (imap_connect): Call - camel_session_get_storage_path and save the value. - (get_folder): Create a local directory to store summary - information and pass a summary file name to camel_imap_folder_new. - Don't call camel_folder_refresh_info from here any more since - camel_imap_folder_new does it again. - - * providers/imap/camel-imap-command.c (camel_imap_command): Add a - special case to this to make it possible to get the repsonses from - a SELECT and still have store->current_folder be updated - correctly. - (imap_read_response): parse EXISTS rather than RECENT - - * camel-session.c (camel_session_get_storage_path): Use - e_mkdir_hier. - - * camel-folder-summary.c (camel_folder_summary_remove_index): New - function. - - * camel-mime-utils.c (header_raw_append_parse): fix this. - (camel-mime-parser.c doesn't use this code because of the MEMPOOL - optimization, so nothing was ever actually calling it before.) - -2000-10-11 Not Zed - - * camel-mime-part.h (struct _CamelMimePart): Removed - temp_message_buffer, and content_input_stream fields which seem to - have come from nowhere, and are unused. - - * camel-mime-utils.c: Added a note about touching this file. - Nobody is to touch it without asking me first. That goes for you - too Jeff. - (header_decode_text): In what way is this broken? - -2000-10-10 Not Zed - - * providers/imap/camel-imap-folder.c (imap_get_summary_internal): - Fix camel_summary_* function rename - (imap_get_message_info_internal): Likewise. - - * camel-mime-parser.c (camel_mime_parser_finalise): Fixed a spelling mistake. - - * camel-folder-summary.c (camel_summary_format_address): Uh, why - do we encode and then decode here ... sigh. This is not the way - to fix this. - (camel_folder_summary_format_address): Renamed to a proper name, - this was only supposed to be a private function. - (camel_folder_summary_format_string): Likewise. Oh i see why it - was made public, code reuse by cut & paste. Joy. - -2000-10-11 Chris Toshok - - * providers/nntp/camel-nntp-store.c (nntp_store_unsubscribe_folder): remove the leading '/'. - (nntp_store_subscribe_folder): same. - (nntp_store_folder_subscribed): same. - -2000-10-11 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_move_message_to): Quote - the mailbox name as it may contain spaces. - (imap_copy_message_to): Same. - -2000-10-10 Chris Toshok - - * providers/nntp/camel-nntp-store.c - (build_folder_info_from_grouplist): fill in message_count and - unread_message_count properly. - - * providers/nntp/camel-nntp-newsrc.h: reformat. - - * providers/nntp/camel-nntp-grouplist.c - (camel_nntp_get_grouplist_from_file): remove spew. - - * providers/nntp/camel-nntp-newsrc.c - (camel_nntp_newsrc_group_get_num_articles_read): new function. - (camel_nntp_newsrc_group_get_highest_article_read): robustification. - -2000-10-10 Joe Shaw - - * providers/imap/camel-imap-store.c - (parse_list_response_as_folder_info): Check before dereferencing the - sep pointer. - -2000-10-10 Jacob "Ulysses" Berkman - - * camel-*.c: teach camel about "its" vs. "it's" - -2000-10-09 Chris Toshok - - * providers/nntp/camel-nntp-store.c (finalize): write out the - newsrc. - (nntp_store_get_name): if @brief, just return host. - - * providers/nntp/camel-nntp-newsrc.c: robustification and bug - fixes. - -2000-10-06 Jeffrey Stedfast - - * camel-folder-summary.c (camel_summary_format_address): Decode - the resulting string. - -2000-10-06 Chris Toshok - - * providers/nntp/camel-nntp-grouplist.c: new file. - - * providers/nntp/camel-nntp-grouplist.h: new file. - - * providers/nntp/camel-nntp-types.h: new file. - -2000-10-06 Jeffrey Stedfast - - * camel-mime-utils.c (quoted_encode): Fix so that we don't encode - every single char in the word. Also, do we need a safemask? I - don't see why we would. - (header_encode_string): Don't strip off the last char!! - -2000-10-06 Chris Toshok - - * providers/nntp/Makefile.am (libcamelnntpinclude_HEADERS): add - camel-nntp-grouplist.h - (libcamelnntp_la_SOURCES): add camel-nntp-grouplist.c - - * providers/nntp/camel-nntp-provider.c: add our own hash functions - for nntp urls. - - * providers/nntp/camel-nntp-newsrc.c - (camel_nntp_newsrc_group_is_subscribed): new function. - (camel_nntp_newsrc_subscribe_group): new function. - (camel_nntp_newsrc_unsubscribe_group): new function. - - * providers/nntp/camel-nntp-newsrc.h: add prototypes for - _group_is_subscribed, _subscribe_group, and _unsubscribe_group. - - * providers/nntp/camel-nntp-store.c - (build_folder_info_from_grouplist): new function. - (nntp_store_get_folder_info): add subscribed_only_parameter. if - it's FALSE, load the grouplist and call - build_folder_info_from_grouplist. - (nntp_store_folder_subscribed): implement. - (nntp_store_subscribe_folder): implement. - (nntp_store_unsubscribe_folder): implement. - (camel_nntp_store_init): add CAMEL_STORE_SUBSCRIPTIONS to the - store's flags. - - * providers/mh/camel-mh-store.c (get_folder_info): add - subscribed_only parameter. - - * providers/mbox/camel-mbox-store.c (get_folder_info): add - subscribed_only parameter. - - * providers/imap/camel-imap-store.c (get_folder_info): add - subscribed_only parameter. - - * camel-store.c (camel_store_supports_subscriptions): new function. - (camel_store_folder_subscribed): new function. - (camel_store_subscribe_folder): new function. - (camel_store_unsubscribe_folder): new function. - - * camel-store.h: add prototypes and virtual functions for the - subscribe implementation. also, add a subscribed_only argument to - camel_store_get_folder_info. - -2000-10-05 Jeffrey Stedfast - - * camel-mime-utils.c (header_address_list_format_append): Encode - the name part of the address and don't quote the name. - (header_decode_text): Rewrote from scratch, the old code was badly - broken. - -2000-10-05 Jeffrey Stedfast - - * camel-mime-message.c (camel_mime_message_set_reply_to): Use the - camel_address_encode function again. - (camel_mime_message_set_from): Same. - -2000-10-05 Jeffrey Stedfast - - * camel-mime-utils.c (quoted_encode_step): Modified to not encode - space chars in the middle of a line. - (isblank): New macro if we're not on a system with the GNU isblank - extension. - - * camel-mime-message.c (camel_mime_message_set_from): Reversed my - changes, don't header_encode_phrase - it generates broken headers. - (camel_mime_message_set_reply_to): Same. - -2000-10-04 Chris Toshok - - * providers/nntp/camel-nntp-utils.c (camel_nntp_get_headers): - revert to old method (only use XOVER if OVER is supported.) - - * providers/nntp/camel-nntp-store.c - (camel_nntp_store_get_overview_fmt): handle the case where the - OVER extension isn't listed but LIST OVERVIEW.FMT works (again, - INN 2.2). enable the OVER extension in this case. - -2000-10-04 Chris Toshok - - * providers/nntp/camel-nntp-utils.c (get_XOVER_headers): return a - gboolean so we can tell if this command worked. we can't key off - the OVER extension being present because at least one server (INN - 2.2) doesn't report the OVER extension but implements the XOVER - command. This could of course just be because I'm a loser for - thinking they were related in the first place. - (camel_nntp_get_headers): always try XOVER first, and if it fails - revert to the slow method. - -2000-10-04 Dan Winship - - * providers/mbox/camel-mbox-store.c (get_folder): Fix a case where - a variable was free'd and then possibly used in an error message. - -2000-10-04 Chris Toshok - - * providers/nntp/camel-nntp-provider.c - (camel_provider_module_init): news: -> nntp:. - -2000-10-04 Chris Toshok - - * providers/nntp/camel-nntp-store.c (nntp_store_get_folder_info): - use "nntp:" instead of "news:" since "news:" urls aren't supposed - to have host/user/port info in them. also, if there's a user - defined in the url, put it in the urls for our folders. - -2000-10-04 Chris Toshok - - * providers/nntp/camel-nntp-auth.c (camel_nntp_auth_authenticate): - borrow some code from the imap provider to query the user for - their password, and pass the user/passwd to nntp. be extra - paranoid and zero out the password before freeing it. - - * providers/nntp/camel-nntp-store.c (camel_nntp_store_init): add - ALLOW_USER/ALLOW_PASSWORD/ALLOW_AUTH to the url flags. - (nntp_store_query_auth_types_generic): return our list of - auth_types. - (nntp_store_query_auth_types_connected): broken, return same as in - query_auth_types_generic. - -2000-10-04 Dan Winship - - * providers/imap/camel-imap-store.c (imap_connect): IMAP4 - (pre-rev1) doesn't support the 'LIST "" ""' idiom, so don't use - it. Just assume the dir_sep is '/'. Shrug. - -2000-10-04 Jeffrey Stedfast - - * camel-mime-message.c (camel_mime_message_set_reply_to): Use - header_encode_phrase instead. - (camel_mime_message_set_from): Same. - -2000-10-04 Not Zed - - * camel-mime-utils.c (header_content_type_is): Handle the case - where ct != NULL, but type and subtype are, and also match that - against text/plain. - - * camel-folder-summary.c: Bump summary file version. - (message_info_save): Save the size from the messageinfo. - (message_info_load): Load the size from the summary file. - (message_info_load): Fixed up the time_t saving/loading. There - was a reason the warning was left there ... obviously nobody could - read the comment "/* warnings, leave them here */", why do i even - bother. - (camel_folder_summary_decode_time_t): Decode a time_t value from - the summary file. - (camel_folder_summary_encode_time_t): Encode a time_t value to the - summary file. - -2000-10-03 Jeffrey Stedfast - - * providers/imap/camel-imap-command.c (camel_imap_command): Quote - the mailbox name when sending a SELECT request otherwise mailboxes - with spaces in their names will cause problems. - - * camel-mime-message.c (camel_mime_message_set_reply_to): encode - before setting. - (camel_mime_message_set_from): Same. - -2000-10-03 Dan Winship - - * providers/imap/camel-imap-command.c: New file containing - camel_imap_command and friends. Major camel_imap_command rewrite - to remove duplicated code, make the parsing of literals be - more safe/correct, deal with RECENT/EXPUNGE responses more - consistently, and make it possible to implement the AUTHENTICATE - command. - - * providers/imap/camel-imap-utils.c (imap_parse_nstring): New - function, to parse an IMAP "nstring". - - * providers/imap/camel-imap-store.c: Move command stuff to - camel-imap-command.c. Update for camel_imap_command changes. - - * providers/imap/camel-imap-folder.c: Update for - camel_imap_command changes. - (imap_append_message): CRLF filter the message before sending it. - - * providers/imap/Makefile.am: Add camel-imap-command.[ch], remove - camel-imap-stream.[ch] for now. - -2000-10-02 Jeffrey Stedfast - - * camel-mime-message.c (camel_mime_message_has_8bit_parts): New - convenience function to determine if there are any 8bit mime parts - in a mime message. - (camel_mime_message_encode_8bit_parts): New convenience function - to recursively reencode all 8bit mime parts to either - quoted-printable or base64 depending on which would be the best - encoding for that part. - - * providers/smtp/camel-smtp-transport.c (smtp_data): If the mime - message contains 8bit parts and the server doesn't support 8bit - transfers, reencode those parts before proceding with the send. - (smtp_mail): If the mime message contains 8bit parts and the - server supports the 8BITMIME extension to SMTP, notify the server - that we'll be sending it 8bit mime parts. - (_send_to): Find out if the message contains 8bit parts. - -2000-10-02 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (_send_to): Use the - CamelInternetAddress parser. - (smtp_get_email_addr_from_text): deprecated. - -2000-10-02 Dan Winship - - * camel-provider.h: Remove default_ports. - - * camel-remote-store.c (remote_connect): Get default_port from - CamelRemoteStore rather than CamelProvider. - - * providers/{imap,nntp,pop3}/camel-*-store.c: Initialize - CamelRemoteStore::default_port - - * providers/*/camel-*-provider.c: Remove default_ports. - -2000-10-02 Dan Winship - - * camel-folder.[ch]: Remove - camel_folder_{get,free}_subfolder_info, as we want to be able to - scan the whole subfolder tree without having to open any folders, - so this needs to be in CamelStore. Remove can_hold_folders and - can_hold_messages flags; things that don't hold messages are no - longer considered CamelFolders. - - * camel-folder-summary.[ch]: Remove CamelFolderInfo stuff. - - * camel-store.[ch]: Add camel_store_{get,free}_folder_info, as - well as camel_store_free_folder_info_full and ..._nop for default - implementations, and camel_folder_info_free and - camel_folder_info_build as convenience functions. Turn - CamelFolderInfo into a tree structure and also add an "url" - member. - - * providers/*/camel-*-folder.c: Remove subfolder_info and can_hold - stuff. - * providers/*/camel-*-store.c: Add folder_info stuff. - - * providers/imap/camel-imap-folder.c (imap_summary_free): Free the - summary elements with camel_message_info_free, not - camel_folder_info_free. Oops. - - * providers/imap/camel-imap-utils.c: const poison - -2000-09-28 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c: Fixed some memory leaks. - (camel_smtp_transport_init): Initialize supports_8bit to FALSE. - (smtp_helo): If server supports 8bit, set supports_8bit to TRUE. - - * camel-transport.h (struct _CamelTransport): Added variable - gboolean supports_8bit (we'll need this eventually? - see bugzilla - bug #53) - - * providers/smtp/camel-smtp-transport.c - (smtp_get_email_addr_from_text): Ugh, no wonder people were - getting illegal seek warnings *sigh*. I guess I can only blame - myself for this one though :-( - -2000-09-28 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (_send_to): Don't send the - recipient data through smtp_get_email_addr_from_text - this is a - complete waste. In fact, we don't want to have to use that - function ever. - - * camel-internet-address.c, camel-address.c: Added some gtk-doc - comments. - -2000-09-28 Jeffrey Stedfast - - * camel-mime-utils.c (header_encode_string): Make sure to add the - space char after an encoded word when the encoding is iso-8859-1. - -2000-09-28 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_message): When - getting a literal string response, don't include the \r\n after - the closing } (as in: "... {798}\r\n...") - - * providers/imap/camel-imap-stream.c (stream_read): Same. - -2000-09-28 Not Zed - - * camel-mime-utils.c (header_fold): New function to fold headers. - -2000-09-27 Not Zed - - * camel-mime-parser.c (folder_scan_header): If we had an empty - header, then it must be end of the headers too. - (folder_scan_init): No we dont need to init the outbuf with a nul - terminator. - - * camel-folder-summary.c (camel_folder_summary_set_uid): New - function to reset the uid to a higher value. - - * providers/mbox/camel-mbox-summary.c (camel_mbox_summary_sync): - "something failed (yo!)" what sort of crap is this? Fixed all the - indenting again, what wanker keeps running stuff through indent? - (message_info_new): Check the uid we loaded off the disk, if it - existed already, assign a new one. If it didn't then make sure - the nextuid is higher. - - * camel-charset-map.c: New file, used to build a large unicode - decoding mapping table, and use it to determine what is the - lowest charset a given word can be encoded with. Uses tables from - libunicode's source. - - * camel-internet-address.c (internet_encode): Use - header_phrase_encode to properly encode the fullname, as required. - refixed indenting. Who keeps doing that? - (camel_internet_address_find_address): Changed fatal return/warnings - into assertions. - - * camel-mime-utils.c (header_raw_append_parse): Check : explicitly - (removed from is_fieldname() macro). - (camel_mime_special_table): Changed to short, so we can represent - more bit types. - (quoted_encode): Take a mask of the safe chars for this encoding. - (header_address_decode): Removed a #warning that makes no sense - anymore. - (header_decode_date): Fixed the 'broken date' parser code, if it - ever decoded it it just threw away the result. - (header_encode_string): Use better charset matching for encoding - strings as well. - -2000-08-31 Not Zed - - * providers/mh/camel-mh-summary.c (camel_mh_summary_sync): Save - the index if we do a sync. - (camel_mh_summary_check): Save the index here too. Probably. - -2000-09-27 Dan Winship - - * providers/imap/camel-imap-store.c (camel_imap_command_extended): - Return untagged data in a GPtrArray rather than a string, since it - saves processing time and is much easier to deal with for several - commands. Update for camel_imap_folder_changed change. - (camel_imap_fetch_command): Update for camel_imap_folder_changed - change. - (imap_connect, imap_folder_exists): Update for - camel_imap_command_extended change. - - * providers/imap/camel-imap-folder.c - (imap_get_message_count_internal, - imap_get_subfolder_info_internal, imap_search_by_expression): - Update for camel_imap_command_extended change. - - (imap_get_summary_internal, imap_get_message_info_internal): Use - camel_imap_fetch_command here now to get around the - camel_imap_command_extended change. - - (camel_imap_folder_changed): turn expunged into a GArray of ints - rather than a GPtrArray of strings representing ints. - -2000-09-26 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c - (imap_get_message_count_internal): Quote the folder name as it may - contain spaces. - (imap_get_subfolder_info_internal): Same. - - * providers/imap/camel-imap-utils.c (imap_parse_list_response): Do - proper unquoting for folder names. - (func_get_current_date): Implemented. - - * providers/imap/camel-imap-store.c - (imap_folder_exists): Quote the folder name as it may have spaces. - (imap_create): Same. - (check_current_folder): Same. - -2000-09-22 Dan Winship - - * providers/imap/camel-imap-folder.c - (imap_get_subfolder_info_internal): The root folder's name is "", - not the namespace. - (camel_imap_folder_new): constify folder_name. - - * providers/imap/camel-imap-store.c (get_folder): Create the - folder with folder_name, not folder_path. - (camel_imap_command_preliminary): Don't free cmdid here. - -2000-09-21 Dan Winship - - * providers/imap/camel-imap-utils.c (imap_create_flag_list): New - function to convert Camel flags to an IMAP flag_list. - (imap_parse_flag_list): Contrariwise. - - * providers/imap/camel-imap-store.c (camel_imap_command_*): Make - the @ret arg actually optional, as (mostly) documented. - (various): Don't pass "&result" to camel_imap_command_* if we're - just going to immediately free it. Don't record status if we're - not going to look at it. - - * providers/imap/camel-imap-folder.c: Likewise. - (imap_summary_free): Use camel_folder_info_free. - (imap_sync): Use imap_create_flag_list. Clear - CAMEL_MESSAGE_FOLDER_FLAGGED after syncing so we don't keep - re-syncing. - (imap_append_message): Use imap_create_flag_list. Don't leak the - memstream if the append fails. - (imap_move_message_to): Use camel_folder_delete_message rather - than doing it by hand. - (imap_get_summary_internal, imap_get_message_info_internal): Use - imap_parse_flag_list and header_raw_clear. - (camel_imap_folder_changed): Use camel_message_info_free. - -2000-09-21 Dan Winship - - * providers/imap/camel-imap-store.c (get_folder_name): INBOX is - case-insensitive. - (get_root_folder_name): Make the root folder "" rather than "/". - (get_folder): Update for root folder name change. - (camel_imap_store_get_toplevel_dir): Removed. (Unused, unneeded.) - (camel_imap_store_folder_path): New function to turn a Camel - folder name into the corresponding namespaced IMAP path. - (imap_folder_exists): Make this take a store and a path rather - than a folder. - (imap_create): Likewise - (get_folder): Update for camel_imap_store_folder_path and other - changes. - (check_current_folder): Likewise. - - * providers/imap/camel-imap-folder.c: Change a bunch of CamelStore - variables to CamelImapStore (and add a few more) to prevent excess - gratuitous casting. Use camel_imap_store_folder_path where - appropriate. - (camel_imap_folder_new): Update for root folder name change. - -2000-09-19 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_data): Use the - linewrap filter to achieve full RFC0821 compliance. - - * camel-mime-filter-linewrap.[c,h]: New mime-filter to word-wrap. - -2000-09-19 Jeffrey Stedfast - - * camel-internet-address.c (internet_encode): When encoding the - internet address, quote the name as the name may have commas or - any other token which may later confuse our address parser. - -2000-09-19 Dan Winship - - * providers/imap/camel-imap-folder.c - (imap_get_subfolder_info_internal): Fix the case where INBOX - isn't returned in the folder listing. - -2000-09-19 Dan Winship - - * camel-folder.c: (init): Removed - (camel_folder_init, camel_folder_construct): New object init - function and public object constructor to replace the old init - method in a more Gtk-like fashion. - - (get_parent_folder, camel_folder_get_parent_folder): Removed. No - CamelFolder subclass was ever setting the parent_folder member, no - code has ever needed to look at it, and fixing it would actually - be pretty hard. - - (get_subfolder_info, camel_folder_get_subfolder_info): Renamed - from ..._names. Deals in CamelFolderInfo now. - (free_subfolder_info, camel_folder_free_subfolder_info): Likewise. - - (get_subfolder, camel_folder_get_subfolder): Removed. - CamelFolderInfo contains the subfolder's full name, so this is - unnecessary now, and removing it lets us get rid of the - CamelFolder separator member, which is needed for the default - implementation of this function, but not otherwise needed for most - providers. - - Also, lots of code style fixes. - - * providers/*: Update CamelFolder subclasses for changes, although - none of them fill in the message counts in the CamelFolderInfo - yet. - -2000-09-18 Christopher James Lahey - - * camel-folder-search.c, camel-folder-search.h, - camel-remote-store.c, providers/imap/camel-imap-folder.c, - providers/imap/camel-imap-store.c: Fixed the #include lines to - deal properly with gal. - -2000-09-17 Dan Winship - - * camel-folder-summary.h: update CamelFolderInfo - * camel-folder-summary.c (camel_folder_info_free): New function to - free the contents of a CamelFolderInfo - -2000-09-15 Dan Winship - - * camel.c (camel_init): Set camel_verbose_debug to TRUE if - CAMEL_VERBOSE_DEBUG is set in the environment. - - * camel-remote-store.c (remote_send_line, remote_recv_line): only - log if camel_verbose_debug is TRUE. - -2000-09-14 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (get_folder): Don't use - dir_sep as top-level directory, use "/". - - * providers/imap/camel-imap-folder.c (imap_expunge): Get rid of - unused variable. - -2000-09-13 Dan Winship - - * providers/imap/camel-imap-folder.c (imap_expunge): Don't look at - the response of the command. camel_imap_command_extended() - processes EXPUNGE responses itself, so if we do it here too we - remove twice as many summary items as we should. - -2000-09-13 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (imap_folder_exists): Rewrote - to take a third argument (gboolean *selectable) so that we can - find out if the folder is selectable or not as we look to see if - it exists. Also, don't use EXAMINE because that will not work on - non-selectable folders, so use LIST instead. - (get_folder): Check to see if the folder exists even vefore - calling imap_create as this will save time. If the folder does - exist, find out if it's selectable. Moved the call to refresh_info - here. - - * providers/imap/camel-imap-folder.c (imap_get_uids): Check for a - NULL summary. - (camel_imap_folder_new): Don't call refresh_info here - call it in - get_folder() because we don't know if this folder even exists on - the server yet! And even if it does, we don't know if it can hold - messages or not yet. - -2000-09-12 Jeffrey Stedfast - - * camel-mime-parser.c (folder_scan_step): Make sure *datalength is - > 0 before calling camel_mime_filter_filter otherwise we will get - a segfault if the filter calls iconv(). - -2000-09-08 Christopher James Lahey - - * providers/nntp/camel-nntp-auth.c, - providers/nntp/camel-nntp-auth.h: Fixed a warning. - -2000-09-07 Dan Winship - - * camel-session.c (camel_session_get_storage_path): Make this not - leak. - -2000-09-07 Dan Winship - - * camel-session.c (camel_session_new): Make this take a path to a - directory that Camel can use for its own nefarious purposes. - (camel_session_get_storage_path): New function to return a path - that a service can use for its own nefarious sub-purposes. - - * camel-service.c (camel_service_get_path): New method (and - useful default implementation) to get a (relative) pathname - corresponding to the service. - -2000-09-06 Dan Winship - - * providers/pop3/camel-pop3-store.c (connect_to_server): Make KPOP - work again. - -2000-09-06 Jeffrey Stedfast - - * camel-mime-message.c (camel_mime_message_get_received_date): - Implemented (someone added these to camel-mime-message.h but never - implemented them!!) - though it may not be right. - (camel_mime_message_get_sent_date): Same. - -2000-09-05 Dan Winship - - * camel-mime-part.c (camel_mime_part_get_filename): If a MIME part - has no Content-Disposition, but does have a "name" on the - Content-Type, return that as the filename. - (process_header): strstrip the Content-Description - -2000-09-05 Chris Toshok - - * providers/nntp/camel-nntp-utils.c (get_OVER_headers): care about - response code. - (get_HEAD_headers): same. - (camel_nntp_get_headers): same. - - * providers/nntp/camel-nntp-store.h: get rid of - CAMEL_NNTP_OK/ERR/FAIL. - - * providers/nntp/camel-nntp-store.c - (camel_nntp_store_get_extensions): take CamelException arg and - pass along to camel_nntp_command. - (camel_nntp_store_get_overview_fmt): same. - (nntp_store_connect): convert to using constants in - camel-nntp-resp-codes.h - (nntp_store_get_folder): make use of camel_nntp_folder_new. - (camel_nntp_command_send_recv): new function to deal with auth - challenge. - (camel_nntp_command): split out most of this function into - camel_nntp_command_send_recv. also, return the actual response - code instead of CAMEL_NNTP_OK/ERR/FAIL. - - * providers/nntp/camel-nntp-resp-codes.h: new file. - - * providers/nntp/camel-nntp-folder.h: prototype for - camel_nntp_folder_new. - - * providers/nntp/camel-nntp-folder.c (camel_nntp_folder_new): new - convenience function. - (nntp_folder_get_message): care more about the actual response - code. - - * providers/nntp/Makefile.am (libcamelnntp_la_SOURCES): add - camel-nntp-auth.c. - (libcamelnntpinclude_HEADERS): add camel-nntp-auth.h. - - * providers/nntp/camel-nntp-auth.h: new file. - - * providers/nntp/camel-nntp-auth.c: new file. - -2000-09-05 Peter Williams - - * providers/imap/camel-imap-store.c (imap_folder_exists): Don't free the - result on error; the exception will have the relevant info. - - * providers/imap/camel-imap-folder.c (camel_imap_folder_new): Check for - exceptions here. - - * providers/imap/camel-imap-store.c (imap_connect): Check the exception - on the refresh_folders call. - - * providers/imap/camel-imap-store.h: Clean up some now-unused fields. - - * camel.c (camel_init): Call unicode_init again, now that libunicode - will not initialize itself twice. - -2000-09-02 Lauris Kaplinski - - * camel-folder-search (search_header_contains): Use e_utf8_strstrcase - -2000-09-01 Christopher James Lahey - - * providers/imap/camel-imap-utils.c: Removed some unused - functions. - -2000-09-01 Peter Williams - - * providers/nntp/camel-nntp-store.c (camel_nntp_command): Initialize - the statically-allocated CamelException so that it doesn't contain - junk data that camel_exception_set() may try to free. - (camel_nntp_store_get_extensions): Same. - (camel_nntp_store_get_overview_fmt): Same. - - * providers/pop3/camel-pop3-store.c (camel_pop3_command): Typo - fix (if (*ret) -> if (ret)). - - * providers/pop3/camel-pop3-store.c (pop3_connect): Set the - port # back to what was specified ASAP, so that the hash of - the URL doesn't change (which causes a failure in - service_cache_remove that leads to a segfault). - - * providers/imap/camel-imap-store.c (imap_connect): Clear the - exception after a failed LOGIN so that it doesn't pass through - to the upper level and make mail think that the login failed. - - * providers/pop3/camel-pop3-store.c (pop3_connect): As above. - -2000-08-31 Peter Williams - - * providers/pop3/camel-pop3-store.c (camel_pop3_store_get_type): - Implement POP3 with the CamelRemoteStore now. - (connect_to_server): Hack this a bit to get KPOP to work. Obey - the new connection semantics of the remote store (implicitly). - (query_auth_types_connected): Clear exceptions after attempts - to connect; the code at the bottom will catch hard errors. - Use camel_service_connect. - (camel_pop3_command): Take a CamelException; now, when an error - occurs, ret is set to NULL and the exception passes back the - appropriate information. - (pop3_get_response): Same as above. - (pop3_try_authenticate): Give camel_pop3_command its exception - and handle it properly. - (pop3_connect): Call the parent classfuncs. Don't disconnect - on error (done for us). - - * providers/pop3/camel-pop3-folder.c: Obey the camel_pop3_command - semantics. - - * camel-remote-store.c (remote_query_auth_types_connected): Don't - warn; just return NULL. - (remote_query_auth_types_generic): Same. - (remote_send_string): Filter out passwords in debugging output. - - * providers/pop3/camel-pop3-store.c (camel_pop3_store_init): Also - set the ALLOW_AUTH flag. - - * providers/imap/camel-imap-store.c (camel_imap_store_init): Same. - -2000-08-31 Chris Toshok - - * providers/nntp/camel-nntp-store.c (camel_nntp_store_class_init): - remove get_folder_name. - (nntp_store_get_folder_name): remove. - -2000-08-31 Lauris Kaplinski - - * camel-mime-part.c (write_to-stream): Use filter only if we have one - -2000-08-31 Chris Toshok - - * providers/nntp/camel-nntp-utils.c (get_OVER_headers): use - camel_remote_store_recv_line. - - * providers/nntp/camel-nntp-folder.c (nntp_folder_get_message): - use camel_remote_store_recv_line to build message. also, free our - buffer so we don't leak like mad. - - * providers/nntp/camel-nntp-store.c: - (camel_nntp_store_get_additional_data) remove. - (camel_nntp_store_get_extensions): use - camel_remote_store_recv_line. - (camel_nntp_store_get_overview_fmt): same. also, don't rely on - _get_additional_data anymore since it's easier to parse without. - (camel_nntp_command): use camel_remote_store_send_string and - camel_remote_store_recv_line. - - * providers/nntp/camel-nntp-store.h: CamelRemoteStore is the - parent class now. remove istream/ostream since CamelRemoteStore - takes care of that for us. also remove the prototype for - camel_nntp_store_get_additional_data. - - * providers/nntp/camel-nntp-newsrc.c (camel_nntp_newsrc_write): - make sure to clear dirty bit. - (camel_nntp_newsrc_read_for_server): don't worry about continually - trying to open the file - if it fails we just return an - unpopulated .newsrc file. - -2000-08-31 Chris Toshok - - * providers/nntp/camel-nntp-newsrc.c - (camel_nntp_newsrc_read_for_server): make this a bit more robust. - try to create an empty .newsrc file for the server if we can't - open it for reading. also, don't allocate everything until we've - opened the file. - - * providers/nntp/camel-nntp-utils.c (get_OVER_headers): make use - of our overview field indices. - (camel_nntp_get_headers): only call get_OVER_headers if the - extension is present. warn if it's not - since get_HEAD_headers - needs work before it works. - - * providers/nntp/camel-nntp-store.c - (camel_nntp_store_get_extensions): new function - query the server - for it's extensions. - (camel_nntp_store_get_overview_fmt): new function - query the - server for the overview format and build our table of the indices - we care about. support the "full" suffix on fields. - (nntp_store_connect): call camel_nntp_store_get_extensions and - camel_nntp_store_get_overview_fmt. - - * providers/nntp/camel-nntp-store.h: add codes for extensions - found on news.mozilla.org. only one that we care about is OVER. - also, add CamelNNTPOverField and an enum of the overview fields - that we care about. - -2000-08-31 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c (imap_translate_sexp): - Reimplemented. It should now work correctly for most possible - VFolder rules. - -2000-08-31 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (camel_imap_command_extended): - Don't save any exceptions caused by camel_imap_folder_changed - (camel_imap_fetch_command): Same. - - * providers/imap/camel-imap-folder.c (camel_imap_folder_changed): - Using a new way of calculating the first recent message that seems - more accurate. Also added code to make sure we don't accidently - add a duplicate summary. - -2000-08-31 Not Zed - - * camel-mime-part.c (write_to_stream): Use the proper type - checking function to check for text types. - (write_to_stream): If we have a charset on a text type that - isn't us-ascii or utf-8, then we need to reencode it, so add a - filter to do that too. - (write_to_stream): Fix some warnings/use the right constructor, - oops. - (write_to_stream): Rearrange the logic so it always does charset - conversion, and not just if we have a qp/base64 block. - - * camel-mime-utils.c (append_latin1): New function - even though - its broken, we'll assume mailers send latin1 headers instead of - us-ascii. We just have to encode high chars into utf-8. - (header_decode_text): Call append_latin1 for appending unencoded - text segments. - (append_latin1): Do an additional mask for account for c's - undefined behaviour for sign extension whilst shifting right. - -2000-08-30 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (camel_imap_fetch_command): - Rewrote to ignore strings that look like server responses until it - is sure that it has finished reading the literal string response. - -2000-08-30 Jeffrey Stedfast - - * camel-remote-store.c (remote_send_string): Don't wrap printed - strings in quotes, makes things messy - - * providers/imap/camel-imap-folder.c (imap_get_message): Updated - to use the camel_imap_fetch_command - - * providers/imap/camel-imap-stream.c (stream_read): Updated to use - camel_imap_fetch_command - - * providers/imap/camel-imap-store.c (camel_imap_command_extended): - No longer handles FETCH requests so no longer needs to be - concerned with checking to make sure that server responses are - valid (they have to be). - (camel_imap_fetch_command): New convenience function that handles - all FETCH requests - -2000-08-30 Peter Williams - - * camel-remote-store.c (remote_connect): Unify with remote_post_connect. - (remote_disconnect): Unify with remote_pre_disconnect. - (camel_remote_store_class_init): Don't use the post_connect and - pre_disconnect classfuncs anymore ; they weren't especially useful. - - * providers/imap/camel-imap-store.c (imap_connect): Use this again - instead of implementing post_connect. - (imap_disconnect): Analogous to above. - - * camel-session.c (camel_session_get_service_connected): New function. - Like camel_session_get_service() but also connects to the service - if needed. camel_session_get_{store,transport} (defined in the header) - used this now, preventing annoying when-to-connect problems. - - * camel-service.c (camel_service_new): Revert to the old behavior - of not connecting until told to do so. Otherwise doing auth - testing correctly is really hard. - (camel_service_connect): Fix behavior here (set the connected - flag). - (camel_service_disconnect): Unset the connected flag. - -2000-08-30 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c: General cleanup / moving - stuff around to make things easier to follow. - -2000-08-30 Jeffrey Stedfast - - * camel-remote-store.c: Prevent exceptions from being overwritten - - * providers/imap/camel-imap-folder.c (imap_expunge): Beautified - (imap_get_subfolder_names_internal): Removed old code as the - replacement code has now been tested and proven to work - -2000-08-29 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c: Removed old code that will - never be needed again - - * providers/imap/camel-imap-store.c: Removed old code for - try_connect - will never need this code - (slurp_response): Update to make sure we aren't falsely detecting - EXPUNGE flags - -2000-08-29 Peter Williams - - * camel-service.c (camel_service_connect): Uncomment this. - (camel_service_disconnect): Same. - - * camel-remote-store.[ch]: New files. Abstract remote storages - (IMAP, POP3, NNTP) and hides the lower-level networky stuff. - - * camel-service.c (camel_service_new): Take an extra argument, the - provider that created us, cause it's useful. - (camel_service_finalize): Unref our new provider member. - - * camel-session.c (camel_session_get_service): Pass the proper number of - arguments to camel_service_new(). - - * camel-imap-store.c: Massive update: 1) use the CamelRemoteService to - make our life Very Easy (TM). 2) Change the semantics of all - camel_imap_command* functions to take exceptions, centralize tons of - duplicate code, and use the handy RemoteStore utility functions - - * camel-imap-folder.c: Use the new semantics of camel_imap_command* - - * camel-imap-stream.c: Same. - -2000-08-29 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (camel_imap_command_extended): - Updated to check for EXPUNGE notifications - - * providers/imap/camel-imap-folder.c (camel_imap_folder_changed): - Updated to account for messages which have been expunged (now - takes a new arg, a GPtrArray of message id's that have been - expunged) - (imap_expunge): Updated (we may want to just use the code in - folder_changed now instead of doing our own summary - expunging...but that can be fixed later) - (imap_append_message): Updated. - (imap_copy_message_to): Updated. - (imap_move_message_to): Updated. - -2000-08-28 Peter Williams - - * camel-folder.c (camel_folder_refresh_info): New member function, - refresh_info, used for rereading folder state after its state has - somehow become unknown. Tries to preserve last-known status of - messages. - - * providers/mbox/camel-mbox-folder.c (mbox_refresh_info): Implement - ::refresh_info (split up ::init) - - * providers/mbox/camel-mbox-store.c (get_folder): Call ::refresh_info. - - * providers/imap/camel-imap-folder.c (camel_imap_folder_new): Call - ::refresh_info once initialized. - (imap_refresh_info): New member function; reads the summary from - the server (used to be in camel_imap_folder_new; split out). - - * providers/imap/camel-imap-store.c (imap_connect): Set - CamelService::connected a little early so that - camel_imap_command won't try to connect while already - connnecting. - (camel_imap_command*): Try to connect if not connected already. - - * providers/pop3/camel-pop3-folder.c (pop3_refresh_info): Same as above. - - * providers/pop3/camel-pop3-folder.c (camel_pop3_folder_new): Same - as above. - - * providers/pop3/camel-pop3-store.c (pop3_connect): Set - CamelService::connected a little early so that - camel_pop3_command won't try to connect while already - connecting - (connect_to_server): Same. - - * providers/nntp/camel-nntp-folder.c (nntp_folder_refresh_info): Same - as above. - -2000-08-28 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_message): Fixed the - hack around quoted string responses - should now handle them - according to the specifications in the RFC - - * providers/imap/camel-imap-stream.c (stream_read): Updated to - match the code currently used in camel-imap-folder.c - -2000-08-28 Ettore Perazzoli - - * providers/mbox/camel-mbox-summary.c (camel_mbox_summary_sync): - Never ever free `tmpname' as it comes from `alloca()'! - -2000-08-26 Ettore Perazzoli - - * camel-mime-utils.c (header_decode_text): Use `g_free()', not - `free()', to free `decword'. - -2000-08-25 Peter Williams - - * camel.c (camel_init): Don't call unicode_init; code in e-util - will do it, and if unicode_init is called twice, you get an - infinite loop when looking up nonexistant encodings (patch - has been submitted to libunicode's maintainer). - - * camel-provider.h: Add a new field, default_ports, which - helps the configuration code guess about how to make CamelURL's - from providers. - - * providers/*/camel-*-provider.c: Specify default ports. - -2000-08-25 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c - (imap_get_subfolder_names_internal): If the url path is "/" and - the folder path is "/", just LIST "" "*" (this should fix some - cyrus imapd problems). Also, INBOX is case insensitive so use - g_strcasecmp - -2000-08-24 Lauris Kaplinski - - * camel-folder-summary.c (summary_build_content_info): - Use UTF-8 as default - * camel-mime-part-utils.c (simple_data_wrapper_construct_from_parser): - Use UTF-8 as default - * camel-mime-utils.c (rfc2047_decode_word): Use UTF-8 - -2000-08-17 Not Zed - - * providers/mh/camel-mh-folder.c (mh_finalize): And here too. - - * providers/mbox/camel-mbox-folder.c (mbox_finalize): Close index - on exit. - -2000-08-23 Dan Winship - - * camel-mime-utils.c (header_address_list_format_append): put - commas between addresses. - -2000-08-22 Dan Winship - - * providers/imap/camel-imap-folder.c - (imap_protocol_get_summary_specifier): use BODY.PEEK, not BODY, so - we don't set the message \Seen. - -2000-08-22 Christopher James Lahey - - * providers/pop3/camel-pop3-store.c: Fixed a small warning. - -2000-08-22 Peter Williams - - * camel-service.c (camel_service_new): Connect automatically if the - URL is not empty. - (finalize): Disconnect automatically if connected. - (camel_service_query_auth_types): Split into two functions; one to - be called if we're connected to an actual server (_connected), one - to be called if we're just gauging the general authtypes supported - (_generic). - (is_connected): Remove. - - * camel-store.c (camel_store_get_folder): Don't connect explicitly to - the service. - - * providers/nntp/camel-nntp-store.c (query_auth_types_generic): Split - the query_auth_types function. Hook it up in _new. - (finalize): Don't try to disconnect here. - - * providers/pop3/camel-pop3-store.c (query_auth_types_generic): Same. - (finalize): Don't try to disconnect here. - - * providers/imap/camel-imap-store.c (query_auth_types_generic): Same. - (finalize): Don't try to disconnect here. - - * providers/smtp/camel-smtp-transport.c (query_auth_types_generic): Split - the query_auth_types (dummy, in this case) function. Hook it up in _new. - (finalize): Don't try to disconnect here. - -2000-08-21 JP Rosevear - - * providers/nntp/camel-nntp-folder.c (nntp_folder_get_subfolder_names): - Make sure newsrc is not null - (nntp_folder_get_subfolder_names): ditto - - * providers/nntp/camel-nntp-newsrc.c - (camel_nntp_newsrc_get_subscribed_group_names): Programming check - for newsrc == NULL - (camel_nntp_newsrc_get_all_group_names): ditto - (camel_nntp_newsrc_write_to_file): ditto - (camel_nntp_newsrc_write): ditto - -2000-08-21 JP Rosevear - - * providers/nntp/camel-nntp-store.c (camel_nntp_command): - Make sure respbuffer is not null before manipulating it. - If it is null, return CAMEL_NNTP_FAIL and a decent error - message. - -2000-08-18 Peter Williams - - * camel-internet-address.c (internet_encode): If the name is "" we - weren't outputting anything; output the address at least. - -2000-08-16 Peter Williams - - * camel-internet-address.c (internet_encode): Fix a leak when - name = "". It's a single-byte leak, but it's the little things - that count. - - * camel-object.c (camel_type_lock_up): Don't leave the type - system locked when a bad unlock happens. - - * providers/mbox/camel-mbox-store.c (get_folder): Fix a leak. - -2000-08-15 Peter Williams - - * providers/imap/camel-imap-folder.c (imap_copy_message_to): Typo fix. - -2000-08-14 Peter Williams - - * camel-folder-search.c (search_get_sent_date): New search function; - returns the time_t when the message was sent. - (search_get_receive_date): Same for when it was received. - (search_get_current_date): Gets the current time for use with the - above two. Is this in the right place? - - * camel-folder-search.h: Add the new functions above to the class. - -2000-08-13 Dan Winship - - * providers/nntp/Makefile.am (libcamelnntpinclude_HEADERS): Add - camel-nntp-utils.h - - * providers/imap/camel-imap-folder.c - (imap_get_subfolder_names_internal): do a strcasecmp rather than - just a strcmp when checking if a folder is "INBOX", since it is - a case-insensitive name. - -2000-08-12 Dan Winship - - * providers/imap/camel-imap-folder.c (imap_get_summary_internal): - Don't assume the FETCH results will come back in the order they - were requested. - (imap_get_subfolder_names_internal): Add "INBOX" to the list as - g_malloc'ed memory, not a static string. - -2000-08-12 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c - (camel_imap_command_continuation): Now takes a char * parameter - rather than a stream - (camel_imap_command_continuation_with_stream): Same function as - above but takes a stream parameter instead - - * providers/imap/camel-imap-folder.c (imap_append_message): Use - camel_imap_command_continuation_with_stream - -2000-08-12 Dan Winship - - * providers/pop3/camel-pop3-store.c (pop3_try_authenticate): New - function to do one round of attempted authentication. - (pop3_connect): Move a bunch of code out into - pop3_try_authenticate and fix some bugs in the edge cases. - -2000-08-12 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (query_auth_types): No longer - calls try_connect() to get authtypes - -2000-08-11 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c - (camel_imap_command_continuation): Changed param order a bit and - fixed some logic - - * providers/imap/camel-imap-folder.c (imap_append_message): Use - the new multi-transactional convenience functions - -2000-08-11 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c - (camel_imap_command_preliminary): New convenience function for - multi-transactional commands (opening request) - (camel_imap_command_continuation): New convenience function for - multi-transactional commands (followup data) - -2000-08-11 Christopher James Lahey - - * providers/mh/camel-mh-folder.c: Fixed a warning. - -2000-08-11 Chris Toshok - - * providers/nntp/camel-nntp-folder.c - (camel_nntp_folder_class_init): remove get_name and get_full_name - assignments, since the camel-folder.c implementation does what we - need. - -2000-08-11 Chris Toshok - - * providers/nntp/camel-nntp-store.c - (camel_nntp_store_get_toplevel_dir): use g_get_home_dir, since - evolution_dir isn't available in the providers. - -2000-08-11 Peter Williams - - * camel-folder.c (thaw): Fix a bug where the message_changed - signal wasn't being emitted. - -2000-08-11 Not Zed - - * providers/mh/camel-mh-folder.c (mh_set_message_user_tag): - Implement. - (mh_get_message_user_tag): Implement. - - * providers/mbox/camel-mbox-folder.c (mbox_get_message_user_tag): - (mbox_set_message_user_tag): Implement. - - * camel-folder.c (move_message_to): Yay so lets fix an already - fixed fix, again. - (copy_message_to): and here too ... update for api change to append(). - And removed another warning. - (camel_folder_set_message_user_tag): Routine to set message tags. - (camel_folder_get_message_user_tag): And accessor. - -2000-08-10 Christopher James Lahey - - * camel-folder-search.c, camel-folder-summary.c, camel-medium.c, - camel-mime-filter-charset.c, camel-mime-filter.c, - camel-mime-filter.h, camel-mime-message.c, camel-mime-parser.c, - camel-mime-part-utils.c, camel-mime-part.c, camel-mime-utils.c, - camel-movemail.c, camel-multipart.c, camel-object.c, - camel-stream-mem.c, providers/mbox/camel-mbox-folder.c, - providers/mbox/camel-mbox-summary.c, - providers/mh/camel-mh-folder.c, - providers/smtp/camel-smtp-transport.c: Fixed some warnings. - -2000-08-11 Not Zed - - * providers/vee/camel-vee-folder.c (vee_folder_build_folder): Free - the search properly. - (vee_folder_build): And here too. - -2000-08-10 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (camel_imap_folder_changed): - If we go over the max number of messages, don't keep requesting - new message summaries, just break. - -2000-08-11 Not Zed - - * camel-mime-parser.c (folder_scan_header): A better way to - compress leading whitespace. The code is probably invalid anyway, - I dont think it will work across buffer boundaries. - - * providers/mbox/camel-mbox-folder.c (mbox_append_message): And - write out proper format From lines here too. - - * providers/mbox/camel-mbox-summary.c - (camel_mbox_summary_build_from): New function to build a more - compatible mbox "From " line. - (camel_mbox_summary_sync): Write From lines in the proper format. - -2000-08-10 Not Zed - - * providers/mh/camel-mh-store.c (get_folder): Remove warnin g. - - * providers/mbox/camel-mbox-store.c (xrename): Kill some warnings - with constification. - - * providers/imap/camel-imap-folder.c (imap_append_message): Fixed - for append api change. Eek this routine seriously wastes memory. - - * providers/mh/camel-mh-folder.c (mh_search_free): Impelemnt. - (mh_append_message): Fix for api change, and include user flags - and tags in new message. - - * providers/vee/camel-vee-folder.c (vee_search_by_expression): Fix - for search api change. - - * camel-folder.c (camel_folder_search_free): New function for - freeing search results. - (search_free): Changed my mind, implement a default that actually - does something. Free as to the old interface. - (camel_folder_append_message): Changed to accept a - camelmessageinfo rather than flags, which just doesn't have enough - info in it. - (copy_message_to): Change for append_message api change. - (move_message_to): Likewise. - - * providers/mbox/camel-mbox-folder.c (mbox_search_free): - Implement. - (mbox_append_message): Fix for api change, and also copy user - flags/tags across to new summary. - - * camel-folder-search.c (search_user_tag): A search expression - that returns the current use flag by name. - (camel_folder_search_free_result): New function to free the result - of a search. - - * camel-folder-summary.c: Bump summary version. - (message_info_new): - (message_info_load): - (message_info_save): - (camel_message_info_dup_to): - (camel_message_info_free): Added support for arbitrary tag/value - pairs (CamelTag's). - (camel_tag_get): - (camel_tag_set): - (camel_tag_list_size): - (camel_tag_list_free): Operations for working with CamelTags. - -2000-08-09 Peter Williams - - * camel-store.c (camel_store_get_folder): Connect beforehand, if - necessary. - - * providers/imap/camel-imap-store.c (camel_imap_store_init): Default - the dir_sep to "/" so that certain functions can safely assume that - dir_sep is valid (at least, nonnull). - -2000-08-09 Ettore Perazzoli - - * providers/nntp/camel-nntp-folder.c - (nntp_folder_set_message_flags): Get rid of an unused variable. - - * providers/nntp/Makefile.am (INCLUDES): Fix includes so that we - don't use installed headers anymore. [I copied this over from the - IMAP provider, that does not seem to have this problem.] - -2000-08-09 Not Zed - - * camel-folder-search.c (camel_folder_search_execute_expression): - Reorder search result in summary order if we searched with a - summary. - -2000-08-08 Dan Winship - - * camel-uid-cache.c: New code to keep an on-disk cache of what - UIDs have been seen in a folder. - - * camel-provider.h: Add new flags CAMEL_PROVIDER_IS_SOURCE (mail - can arrive in it by non-Camel means) and CAMEL_PROVIDER_IS_STORAGE - (you can work with mail directly without needing to copy it local). - - * providers/*/camel-*-provider.c: Add flags as needed: imap and - mbox are SOURCE and STORAGE. mh and nntp are just STORAGE, pop3 is - just SOURCE. - - * camel-mime-message.c (process_header): Add another subject - g_strstrip that fejj's earlier commit missed. - -2000-08-08 Peter Williams - - * camel-provider.h: Remove some GTK stuff that I missed. - - * providers/imap/camel-imap-store.c (imap_noop): Turn this - back on with the new timeout interface in CamelSession. - - * camel-session.[ch] (camel_session_register_timeout): New - interface for Camel to register timeouts. Basically the - GTK timeout interface is copied. We do this because Camel isn't - allowed to use GTK anymore. - -2000-08-07 Not Zed - - * providers/mh/camel-mh-folder.c (mh_append_message): Only retry - another uid if we had a name clash, otherwise fail. - -2000-08-07 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c - (imap_get_subfolder_names_internal): If we are trying to get a - subfolder listing of the root folder, always make sure INBOX is - there... - - * providers/imap/camel-imap-utils.c (imap_parse_list_response): - Check for NIL as a directory separator. - -2000-08-07 Peter Williams - - * providers/nntp/Makefile.am: Reorder the INCLUDES to pull - in the camel headers from the local source tree before - the ones in $(includedir). This was causing compile problems - because the installed, Gtk-based camel-object.h was included - before the uninstall Camel-based one. - -2000-08-07 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c (imap_translate_sexp): Strip - all \n's from the expression - - * string-utils.c (strip): New convenience function to strip - occurences of a single char from a string - - * camel-mime-message.c (camel_mime_message_set_subject): Do a - g_strstrip on the subject so we can stop getting those annoying - leading spaces - -2000-08-07 Dan Winship - - * camel-folder.c (camel_folder_free_deep): Fix this to not require - NULL-termination of the array. - -2000-08-04 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (imap_connect): If we fail to - get a dir_sep, then supply the default of "/". - (get_folder): Undo changes by Peter - -2000-08-04 Peter Williams - - * providers/imap/camel-imap-store.c (get_folder): Prevent a coredump - when get_folder()ing from a store with dir_sep = NULL. - -2000-08-04 Peter Williams - - * camel-store.h: Include camel-object.h. Ettore said this wasn't - compiling. - -2000-08-04 Not Zed - - * camel-url.c (camel_url_set_protocol): - (camel_url_set_host): - (camel_url_set_path): - (camel_url_set_port): Url editing functions. - -2000-08-04 Dan Winship - - * providers/pop3/camel-pop3-folder.c (pop3_set_message_flags): - (pop3_sync): Indexes into the flags array are message_number minus - 1, not just message_number. - - * providers/pop3/camel-pop3-store.c: add a debugging macro for - doing protocol tracing. - -2000-08-03 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (camel_imap_folder_new): Only - call imap_get_summary_internal if the folder can hold messages - - * providers/nntp/camel-nntp-provider.c (camel_provider_module_init): - Initialize the service_cache for the news/nntp providers - -2000-08-03 Peter Williams - - * providers/nntp/Makefile.am (INCLUDES): Add -I$(top_srcdir) to - pull in libibex/ibex.h - -2000-08-02 Not Zed - - * providers/mh/camel-mh-summary.c (camel_mh_summary_sync): Expunge - from the end, so the index isn't messed up when you remove a - message. - - * providers/mh/camel-mh-folder.c (mh_append_message): Fix a bug - where it would never open an output file/uid. - - * providers/mbox/camel-mbox-store.c (rename_folder): - Implementation for mbox as well. - - * camel-store.c (camel_store_rename_folder): New method to rename folders. - (rename_folder): Default implementation. - - * providers/mh/camel-mh-store.c (delete_folder): Implement this. - (rename_folder): Implement a rename operation. - -2000-08-02 Dan Winship - - * providers/MH: Kill this. It doesn't have any code to do anything - the new mh provider doesn't do better. - - * providers/Makefile.am: Remove reference to MH subdir, and - promote nntp to fully-supported status, since it does compile and - all. - - * camel-mime-message.c (camel_mime_message_set_subject): Trim - trailing space from the subject. I've now seen replies from two - different people that tricked the threading code by (a) not having - References/In-Reply-To, and (b) adding an extra space to the end - of the subject line so the subject-based threading fails too. Who - writes these broken mailers anyway? - -2000-08-01 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_helo): When forced - to use the IP, place it in square brackets. - - * providers/imap/camel-imap-utils.c (imap_translate_sexp): New and - improved sexp parser. An honest try at using e-sexp is wrapped in - a #ifdef at the bottom of the file but is currently not used - - * providers/imap/camel-imap-folder.c (imap_search_by_expression): - We want to do a UID SEARCH so we get UIDs back instead of sequence - numbers - -2000-08-01 Not Zed - - * providers/mh: New mh provider implementation. - - * providers/Makefile.am (SUBDIRS): Added mh provider. - -2000-07-31 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_message_info_internal): - Some IMAP servers don't wrap the UID in ()'s so don't depend on that - (imap_get_summary_internal): Same - - * providers/imap/camel-imap-utils.c (free_sexp_node): Oops, forgot to - free node->function - not good. - -2000-07-31 Peter Williams - - * providers/vee/camel-vee-folder.c (vee_search_by_expression): Add - a NULL to the matches pointer array so that g_strfreev knows where - the end is. - -2000-07-31 Jeffrey Stedfast - - * providers/imap/camel-imap-utils.c (imap_translate_sexp): New - convenience function to translate a Camel sexp into the equivalent - IMAP sexp. - - * providers/imap/camel-imap-store.c: More places now use - imap_next_word - - * providers/imap/camel-imap-folder.c (imap_search_by_expression): - Implemented initial version (this may or may not work quite right) - -2000-07-28 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_expunge): Make sure - the third word/token (whatever) is "EXPUNGE" and not something - else like "EXISTS" or "RECENT". When removing the message from - the summary also make sure to free that data to avoid leakage. - Also make sure to subtract 1 from the 'id' since IMAP starts - at 1 and our summary starts at 0 :-) - -2000-07-28 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (camel_imap_status): Cleaned - up a bit, now uses imap_next_word() - (camel_imap_command_extended): Now uses imap_next_word(). When - checking for RECENT, allow the first digit of the recent-count - be between 0 and 9 inclusive instead of exclusive. - - * providers/imap/camel-imap-folder.c (imap_expunge): Optimized. - No longer will it need to reload the summary as it now instead - removes the appropriate message summaries from the cache. - (camel_imap_folder_changed): If recent == 0 then return. If - recent < 0 then just emit the folder_changed signal, don't reload - summaries. - -2000-07-28 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c - (imap_get_message_count_internal): Get message count when STATUS - is not available. - (imap_init): folder->has_search_capability is required for IMAP so - should always be set to TRUE (is currently being set to FALSE as - I've not yet implemented SEARCH support). - (camel_imap_folder_changed): Seem to have fixed my optimization - hack - -2000-07-28 Jon K Hellan - - * providers/imap/camel-imap-store.h (CamelImapServerLevel): New - enum. - (CamelImapStore): Added server_level and has_status_capability - members. - - * providers/imap/camel-imap-store.c (imap_connect): Detect - IMAP4REV1, IMAP4 and STATUS in capability response. - - * providers/imap/camel-imap-folder.c - (imap_get_message_count_internal): Use STATUS only if server - supports it. TODO: Get message count when STATUS not supported. - (imap_get_message, imap_get_summary_internal, - imap_get_message_info_internal): Handle IMAP4 as well. - (imap_protocol_get_summary_specifier): New function: Make a data - item specifier for the header lines we need, appropriate to the - server level. - -2000-07-27 Peter Williams - - * camel-mime-utils.c (header_decode_lwsp): More - checks for end of string. - - * providers/imap/camel-imap-store.c: - (imap_command_extended): Free the elements of our - array (huge mem leak) - - * providers/imap/camel-imap-folder.c: - (summary_get_internal): Same as above. - -2000-07-27 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (camel_imap_folder_changed): - Fixed my routine to only fetch new headers, my IDs were off by 1 - on the high end, so when it would fetch the last newly arrived - message it would fail and end up fetching all of the summaries - because of the corruption. - -2000-07-27 Jeffrey Stedfast - - * camel-url.c (camel_url_to_string): If the path doesn't begin - with a / and there is a host, prepend a / to the path. - -2000-07-27 Jeffrey Stedfast - - * providers/imap/Makefile.am: Added camel-imap-utils.[c,h] - - * providers/imap/camel-imap-utils.[c,h]: Utilities for parsing - server responses for use in both camel-imap-store.c and - camel-imap-folder.c - - * providers/imap/camel-imap-folder.c (imap_get_summary_internal): - Free all the pointers in the headers array. - (imap_get_subfolder_names_internal): Updated to use - imap_parse_list_response - (imap_parse_subfolder_list): Removed in favor of - imap_parse_list_response - - * providers/imap/camel-imap-store.c (camel_imap_command_extended): - Free all the pointers in the data array. - (imap_connect): Updated to use imap_parse_list_response and fixed - a leak - (folder_is_selectable): Updated. - -2000-07-27 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_message_info): Now - uses a hash table for looking up message info rather than a linear - search :) - -2000-07-27 Peter Williams - - * providers/*/Makefile.am: Don't specify SUBDIRS = - [nothing]. Messes up distcheck. - -2000-07-26 Peter Williams - - * camel-mime-parser.c (folder_scan_init): Initialize - outbuf to be "" -- it's not guaranteed to be zeroed. - - * camel-mime-utils.c (header_references_decode): Return - if the header is NULL -> or "" <-. Don't do our stupid - mailer trick if we point to \0. - (header_decode_quoted_string): Don't rip past end of - string! - -2000-07-26 Dan Winship - - * camel-movemail.c (movemail_external): routine to call an - external movemail program. - (camel_movemail): Nuke return value, use movemail_external when - available and useful, and don't delete "dest" on errors, since - it might have started non-empty. - -2000-07-26 Jeffrey Stedfast - - * camel-url.c (camel_url_to_string): Should now always prepend a '/' - before the path if it doesn't already exist. - - * providers/imap/camel-imap-folder.c: Fixed a few compiler warnings - -2000-07-25 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_summary_free): Fixed the - real problem that Peter was running into. - -2000-07-25 Dan Winship - - * camel-mime-message.c (write_to_stream): Don't add a Mime-Version - header to a message that already has one. - - * camel-internet-address.c (internet_encode): Don't put <>s around - addresses with no name part. - -2000-07-25 Peter Williams - - * providers/imap/camel-imap-folder.c (imap_expunge): Set - imap_folder->summary to NULL after calling imap_summary_free, - so we don't get stuck with a junk summary pointer. Should - we free it at all? - -2000-07-25 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (camel_imap_folder_changed): - Optimized to try and get the new message headers without reloading - the entire summary from scratch. - (imap_get_summary_internal): Will now sync() before attempting to - reload the summary so that flags are set in the reloaded summary - as well. - -2000-07-24 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (get_folder): Updated to give - special attention to the root folder. - - * providers/imap/camel-imap-folder.c - (imap_get_subfolder_names_internal): Updated to handle the root - folder - (imap_get_message_count_internal): return 0 if folder can't hold - messages - (camel_imap_folder_new): Change so that root folder gets special - attention and always gets can_hold_messages set to FALSE - -2000-07-24 Dan Winship - - * camel-folder.c: Remove exceptions from a number of methods that - work on what ought to be static data: get_parent_folder, - get_parent_store, get_message_count, get_unread_message_count, - get_permanent_flags, get_message_flags, set_message_flags, - get_message_user_flag, set_message_user_flag, get_uids, - get_summary, get_subfolder_names. Turn camel_folder_delete_message - into a macro. (Mostly a pull-up from the camel-async branch.) - - * providers/{imap,mbox,nntp,pop3,vee}: Update for CamelFolder - changes - -2000-07-24 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_message_info): Updated - to port easily to the new Camel API - (imap_init): Don't SELECT INBOX, we don't need to do that - -2000-07-24 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (camel_imap_folder_new): - Initialize the summary and subfolder listing. - (imap_summary_free): Now takes a GPtrArray arg rather than a - CamelImapFolder as it increases it's usefullness for free()'ing - temporary summaries. - (imap_get_message_count_internal): A new convenience function for - getting the actual message count on a server to be used by - imap_get_summary_internal) - (imap_get_message_count): Since the Camel API is on the move again, - the future version of this function will not be able to make a - call to the store, it must only access previously fetched data (thus - the creation of the _internal function) - (imap_get_subfolder_names_internal): Again, because the future version - of imap_get_subfolder_names will not take an exception, we must rename - this function which will be called by camel_imap_folder_new() - (imap_get_subfolder_names): We now return the previously collected - subfolder listing that the _internal function fetched previously - (imap_get_summary_internal): Again, same idea as the previous _internal - functions... - (imap_get_summary): Again... now returns a previously aquired summary - - * providers/imap/camel-imap-store.c (imap_noop): This will hopefully - prevent the imap store from disconnecting. - (imap_connect): Modified to add a gtk timeout event that will call - imap_noop() every 10 minutes (we may want to change this time value) - (imap_disconnect): Modified to remove the NOOP timeout event from the - store. - (camel_imap_command_extended): Commented out the code that would try - and detect if the store was disconnected and then reconnect if it was - needed. - -2000-07-24 Dan Winship - - * camel-folder.[ch]: Remove camel_folder_get_message_uid, which - was not used, and not implemented by any provider. - - * providers/nntp/camel-nntp-folder.c: Remove get_message_uid - non-implementation. - - * camel-folder-pt-proxy.[ch], camel-arg-collector.c, - camel-marshal-utils.[ch]: Bye bye bye. - - * Makefile.am: remove reference to camel-arg-collector.c - -2000-07-23 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (imap_disconnect): Made it a - little more forgiving. Also set current_folder to NULL as there is - no selected folder after a disconnect. - (stream_is_alive): Detects whether or not a socket is "alive" - (camel_imap_command_extended): Use stream_is_alive() to aid in the - detection of a disconnected state. - -2000-07-22 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (get_folder): Clear - CamelExceptions when appropriate (eg when folder is marked as - \NoSelect). Still needs some cleanup and perhaps Dan will have a - better way of doing this as this seems like a messy way of - handling this. - - * providers/imap/camel-imap-folder.c (imap_get_uids): Took out - some debug statements as they are no longer needed. - -2000-07-21 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_subfolder_names): - Updated to not strip out subfolders that are marked as \NoSelect - because this will be correctly handled in store->get_folder from - now on. - - * providers/imap/camel-imap-store.c (folder_is_selectable): New - convenience function for use in get_folder(). - (parse_list_response): Now takes a char **flags argument which is - needed by folder_is_selectable(). - (imap_connect): Updated to reflect changes to - parse_list_response(). - -2000-07-21 Jeffrey Stedfast - - * providers/imap/camel-imap-stream.c (stream_read): Updated with - some of the same fixes I've made to camel-imap-folder.c like - recalculating message part lengths. - - * providers/imap/camel-imap-store.c (camel_imap_command_extended): - Rewrote the code to check for "* %d RECENT". Still needs to be - modified, but should no longer cause an infinite loop by detecting - mis-detecting RECENT messages. - -2000-07-20 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_summary): - (imap_get_message_info): Oops. Fix UID parser to allow 0 and 9 to - be in the range of valid UID chars. - -2000-07-20 Peter Williams - - * camel-object.c (camel_object_unref): Add a new global mutex - 'refcount' held when refcounting operations occur. - -2000-07-19 Peter Williams - - * camel-object.c (camel_type_lock_up): Correct the recursiveness; - the locklevel is stored as a private, so each thread has its own - idea of the locklevel. Thus one thread can relock, but a different - one will think that it's a level 0 and try to lock the type_system - mutex. - -2000-07-19 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c: General cleanup working - towards getting Actions->Expunge working correctly. - - * providers/imap/camel-imap-store.c - (cammel_imap_command_extended): Added code to look for "* %d - RECENT" and to emit the folder_changed signal if there are any - recent messages. Note: this is a hack and needs to be rewritten - badly. - -2000-07-19 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_summary): If the - folder's message count is not the same as the number of summaries, - free the old summary and create a new summary. - -2000-07-18 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c - (camel_imap_folder_class_init): Added in - imap_[g,s]et_message_user_flag() methods - (imap_get_message_info): Rewrote to use the more efficient way of - downloading summary information and also added a UID comparison so - that if the UID requested doesn't match the UID received, it - returns NULL. FIXME: When the mailer gets NULL when it requested - message info, it seems that it displays a row for that message and - when you try and select the blank row, it segfaults. - - * providers/imap/camel-imap-store.c (get_folder): Oops, this - should not be checking against "/", it should be checking against - dir_sep. - - * providers/imap/camel-imap-folder.c (imap_parse_subfolder_line): - Updated to trim out the leading namespace. - (imap_get_subfolder_names): Let the subfolder parser trim the - namespace off the folder name. - -2000-07-17 Peter Williams - - * camel-object.c (camel_type_lock_up): New function; the - Camel type_system lock is now fakey-recursive, being controlled - by a semaphore that goes up and down and is protected by another - lock. Theoretically all we need is the lock on the semaphore, - but this we catch exceptions "better" (by deadlocking). - (camel_type_lock_down): Corresponding to above. - (all functions): s,G_LOCK,camel_type_lock_up, etc. - -2000-07-17 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (imap_disconnect): Send a - "LOGOUT" command. - - * providers/imap/camel-imap-folder.c (imap_get_message): Hacks to - get IMAP code to work with CommunigatePro and MS Exchange (and any - other servers that send back a UID at the end of each FETCH inside - of the main body of the message part). - (imap_sync): Un-#if 0 the code that sets the flags on the IMAP - server for messages that have changed. Oops, don't mask with - DELETED to find out if the message has been answered ;-) - (imap_expunge): sync before expunging. - -2000-07-16 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c: All SELECT calls now pass - a NULL folder argument to camel_imap_command_extended() since it's - not needed. - (imap_connect): Moved service_class->connect() to the point right - after a connection is established with the server rather than - waiting until the end of the function. - (camel_imap_command): Updated the documentation comment - (camel_imap_command_extended): Before sending a command, first - check to make sure we are connected; if we aren't, then reconnect. - Don't strncmp() command with "SELECT" as it's redundant. - - * providers/imap/camel-imap-folder.c: All SELECT calls now pass - a NULL folder argument to camel_imap_command_extended() since it's - not needed. Also s/camel_imap_command/camel_imap_command_extended as - I will probably be doing away with camel_imap_command() or at least - only using it for LOGIN and similar commands where the server won't - notify us of any recent messages. - -2000-07-15 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (camel_imap_folder_new): - One last fix to get rid of hard-coded "/" directory separators - -2000-07-14 Peter Williams - - * camel-object.c : Implement 'events', which are suspiciously - like signals except without all the marshalling baggage, and - with quasi-thread-safety. - (camel_object_class_declare_event): New func. - (camel_object_hook_event): Ditto. - (camel_object_trigger_event): Ditto. - (obj_class_init): Declare the "finalize" event. - (obj_class_finalize): Free the hashtable of events->preps - (obj_finalize): Free the hashtable of events->hooklists - (camel_object_unref): Trigger the finalize event (ourselves, - to prevent massively unpleasant looping things.) - -2000-07-14 Peter Williams - - * camel-object.c (make_global_classfuncs): Change to return - a CamelObjectClass. Change parents to a GSList and free it - when done. - (camel_object_new): Don't allocate a classfuncs for every object; - merely give it a reference to the global_classfuncs. Convert - parents to a GSList and free it when done. - (camel_object_unref): Don't free the classfuncs. Free the parents - list, which is changed to a GSList. - -2000-07-14 Jeffrey Stedfast - - * string-utils.c (string_unquote): New convenience function - to unquote a string if it's encapsulated by "'s - - * providers/imap/camel-imap-folder.c: - * providers/imap/camel-imap-store.c: Made the necessary changes - to stop using hard coded directory separators. - -2000-07-13 Dan Winship - - * providers/mbox/camel-mbox-summary.c (camel_mbox_summary_load): - If the summary is for a smaller mbox, and rebuilding from the - last-known end position fails, try rebuilding from the beginning. - Deals with the case where the user edits the mbox and makes it - bigger, without adding new messages. - -2000-07-13 Peter Williams - - * camel-object.c: Rewritten to not be based on GtkObject, - but a tiny threadsafe ripoff thereof. Objects still cannot - be shared across threads, but ref/unref/destroy/new/etc - will work. Signals are not implemented because doing it - robustly would be a major pain in the butt, but class - functions are. There's a small demonstration that it doesn't - crash in ./temp-test.c: build it with ./make-test.sh. - * camel-stream.c, camel-seekable-stream.c, camel-stream-mem.c: - moved over to CamelObject. Proof of concept: two levels of - subclass and class functions, all working without coredumps. - To port to CamelObject: - - s,GTK_,CAMEL_,g in the cast checks - - s,gtk_type_new,camel_object_new,g - - s,GtkType,CamelType,g - - Change get_type function over to camel_type_declare - - instead of hooking to finalize function, it goes into the - type declaration. - - remove signals. - - instead of GTK_OBJECT(so)->klass, CAMEL_OBJECT_GET_CLASS(so) - - s,gtk_type_class,camel_type_get_global_classfuncs,g - - don't chain finalize handlers; it will be done for you - -2000-07-13 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c: - * providers/imap/camel-imap-store.c: If a SELECT fails, set - imap_store->current_folder to NULL so a SELECT is forced before - any message/folder operations are requested. Also, because some - users don't use a namespace, make sure that if the url->path is - "/" we don't use it when creating the folder_path. - (camel_imap_command[_extended]): Since we allow the passing of - a NULL folder which we can use to bypass a forced SELECT, no need - to check for the individual commands that don't require a folder - to be selected. - -2000-07-13 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c: - * providers/imap/camel-imap-store.c: Updated to use CAMEL_IMAP_OK, - CAMEL_IMAP_NO, CAMEL_IMAP_BAD, and CAMEL_IMAP_FAIL rather than the - ones copied from the POP3 provider. - -2000-07-13 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_summary): Oops. - If the number of messages in the folder is 0, don't fetch - summaries 1 thru 0, just return an empty summary. - (imap_copy_message_to): Fixed to use message UID and also send - the source folder as an arg to camel_imap_command rather than NULL. - (imap_move_message_to): Same. - (imap_init): If SELECT is successful, we need to set the current - folder to the one selected, this was causing problems with move/copy - -2000-07-13 Dan Winship - - * camel-service.h: define a set of CAMEL_SERVICE_URL_ALLOW_* flags - parallel to the _NEED_* flags, and make the _NEED_* flags imply - the _ALLOW_* ones. - - * providers/imap/camel-imap-store.c (camel_imap_store_init): imap - urls ALLOW_PATH - -2000-07-13 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_summary): New - and improved approach to fetching an entire folder summary - that should be much much faster than the old way as it gets - the entire folder summary in 1 shot rather than requesting - message by message. As with the last update, this version - also only fetches the minimum number of header fields. - (imap_get_summary): Oops, forgot to free the temp - GPtrArray *headers - -2000-07-13 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_summary): Don't - fetch the entire RFC822 header, just fetch the fields we want. - (imap_get_message_info): Same. - -2000-07-13 Not Zed - - * camel-mime-filter-basic.c (camel_mime_filter_basic_new_type): - Reset filter on setup. - (reset): When resetting qp encoding, set the state to -1, instead - of 0. - - * camel-mime-utils.c (quoted_encode_step): Actually count the - characters output sofar (it never counted any). Bunch of other - fixes. - (quoted_encode_close): Also flush out final character, if there's - one. - -2000-07-12 Jeffrey Stedfast - - Chris forgot to add #include to the source files - - * providers/imap/camel-imap-store.c (imap_connect): Fixed Peter's - fix, we don't want to send a string to a %d. - -2000-07-12 Christopher James Lahey - - * camel-folder-search.c, providers/imap/camel-imap-store.c: - Changed from strstrcase to e_strstrcase. - - * string-utils.c, string-utils.h: Removed strstrcase (in favor of - e_strstrcase in e-util/e-util.c.) - -2000-07-12 Chris Toshok - - * providers/nntp/camel-nntp-folder.c - (nntp_folder_set_message_flags): get the article num out of our - uid and mark it read in the newsrc. - (nntp_folder_get_message): get the message id out of the uid to - fetch the article. - - * providers/nntp/camel-nntp-utils.c (get_XOVER_headers): the uid - is now , - (get_HEAD_headers): same. - - * camel-mime-parser.c (folder_scan_step): go to HSCAN_MESSAGE - state when ct->subtype is "news" as well as "rfc822". this makes - attachments of type "message/news" display properly. - -2000-07-12 Dan Winship - - * camel-folder.c (camel_folder_free_deep, - camel_folder_free_shallow, camel_folder_free_nop): Useful default - implementations for free_{uids,subfolder_names,summary}. - (free_subfolder_names, free_uids): Make these g_warning-ing - default implementations. - - * providers/*/camel-*-folder.c: Use the new functions where - appropriate, remove duplicated code. - -2000-07-12 Peter Williams - - * providers/imap/camel-imap-store.c (query_auth_types): Check for - NULL parameters when setting the exception so as to not crash on - Solaris (can't handle a %s passed NULL). - (imap_connect): Same. - -2000-07-12 Jeffrey Stedfast - - * providers/mbox/camel-mbox-folder.c (mbox_delete_message): Use - mbox_set_message_flags () instead of setting the flags by hand. This - fixes the problem of the "message_changed" signal not being emitted - at the correct time. - - * providers/imap/camel-imap-folder.c: "folder_changed" signals should - pass a third argument (which is ignored). - - * camel-folder.c: Undo gtk signal emits done in set_flags and - expunge. - (move_message_to): - (copy_message_to): Create info as a const CamelMessageInfo - -2000-07-12 Chris Toshok - - * providers/nntp/Makefile.am: don't add test-newsrc to the build - since it needs libcamel (which isn't built at the time test-newsrc - needs linking.) - - * providers/nntp/camel-nntp-utils.c (get_HEAD_headers): fill in - MessageInfo->message_id. - (get_XOVER_headers): same. - - * providers/nntp/camel-nntp-folder.c (nntp_folder_init): move - summary loading here. - (nntp_folder_sync): summary/newsrc changes should be stored here. - put a comment to that effect. - (nntp_folder_set_message_flags): don't save the newsrc here. - (nntp_folder_get_uids): use g_ptr_array_index instead of the - cast/addition. - (nntp_folder_get_summary): no need to check if we should generate - the summary here. already done. - (nntp_folder_get_message_info): implement. - - * providers/nntp/camel-nntp-store.c - (camel_nntp_store_get_toplevel_dir): use evolution_dir instead of - computing it ourselves. - (nntp_store_disconnect): call camel_nntp_newsrc_write. - (ensure_news_dir_exists): new function to create the news/ subdir. - (camel_nntp_store_class_init): hook up connect/disconnect and - finalize. - (nntp_store_connect): if ensure_news_dir_exists fails throw an - exception. - -2000-07-12 Peter Williams - - * camel-folder.c (camel_folder_set_message_flags): Emit a message_changed - signal once the flags are set on the message. - (camel_folder_set_user_flag): Ditto. - (camel_folder_expunge): Emit a folder_changed if no exception. - -2000-07-12 Jeffrey Stedfast - - * camel-stream.c: Use size_t and ssize_t for read/write methods - - * providers/imap/camel-imap-folder.c (imap_set_message_flags): - Updated to emit the message_changed signal. - (imap_delete_message): Updated to use imap_set_message_flags (). - (imap_move_message_to): Updated to use imap_set_message_flags () - and to emit the folder_changed signal on the destination folder. - (imap_copy_message_to): Updated to emit the folder_changed signal - on the destination folder. - (imap_append_message): Updated to emit the folder_changed signal - on the destination folder. - -2000-07-11 Jeffrey Stedfast - - * camel-folder.c (camel_folder_append_message): Now takes a - flags argument to specify the flags to be set on the message - since we might not necessarily want the flags to be wiped clean. - (move_message_to): - (copy_message_to): Updated to send a flags argument to - append_message (); currently sends the original message's flags. - - * providers/mbox/camel-mbox-folder.c (mbox_append_message): - * providers/imap/camel-imap-folder.c (imap_append_message): - Updated. - -2000-07-11 Dan Winship - - * camel-folder.c: Remove exceptions from a number of methods - that work on what ought to be static data: get_parent_folder, - get_parent_store, get_message_count, get_unread_message_count, - get_permanent_flags, get_message_flags, set_message_flags, - get_message_user_flag, set_message_user_flag, get_message_uid, - get_uids, get_summary, get_subfolder_names. Turn - camel_folder_delete_message into a macro. - - * providers/{mbox,pop3,vee}: Update for CamelFolder changes - - * providers/Makefile.am: Disable imap and nntp for now - -2000-07-11 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_search_by_expression): - This shouldn't return NULL, it should return g_ptr_array_new () - so the mailer gets what it expects. - -2000-07-10 Jeffrey Stedfast - - * camel-folder-summary.c (camel_folder_summary_decode_string): - Oops, an unsigned integer can never be < 0 - -2000-07-10 Dan Winship - - * providers/vee/camel-vee-folder.c (vee_search_by_expression): - Initialize a variable to make this not crash again. And fix a bug - so it actually does something. - -2000-07-10 Jeffrey Stedfast - - * camel-folder-summary.c: Cleaned up a bunch of compile warnings - -2000-07-10 Dan Winship - - * providers/vee: kill more debugging messages - -2000-07-10 Jeffrey Stedfast - - * providers/mbox/camel-mbox-folder.c (mbox_get_unread_message_count): - * providers/vee/camel-vee-folder.c (vee_get_unread_message_count): - * providers/imap/camel-imap-folder.c (imap_get_unread_message_count): - Implemented. - - * camel-folder.c (camel_folder_get_unread_message_count): New - convenience function to allow the mailer to query the number - of unread messages in a folder (for displaying message stats - in a folder tree?). - -2000-07-09 Dan Winship - - * camel-mime-utils.c (header_references_dup): New function to copy - a header_references structure. - - * camel-folder-summary.c (camel_message_info_dup_to): New function - to (deep) copy the data from one CamelMessageInfo into another. - (camel_message_info_free): And free the data. - - * providers/vee/camel-vee-folder.c (vee_sync): Implement. (empty). - (vee_search_by_expression): belatedly update for - camel_folder_search change. - (vee_folder_build): belatedly update for camel_folder_search - change. Use camel_message_info_dup_to and camel_message_info_free - (in particular, so that we get message_id and references info so - vfolders can be threaded). - (vee_folder_build_folder): Ditto. - -2000-07-08 Jeffrey Stedfast - - * providers/nntp/camel-nntp-folder.c: - * providers/nntp/camel-nntp-utils.c: - * providers/nntp/camel-nntp-store.c: Update to reflect past changes - in the Camel API. Use gtk macro casts wherever possible and use glib's - memory functions instead of standard c's (since they are not - compatable) - - * providers/smtp/camel-smtp-transport.c: - * providers/imap/camel-imap-store.c: Wrap debug print statements - in a macro - - * providers/imap/camel-imap-stream.c (stream_read): Make sure - that we get up to and including the last \n of the mime part. - - * providers/imap/camel-imap-folder.c (imap_get_message): Make sure - that we get up to and including the last \n of the mime part. - Wrap debug print statements in a macro. - - * providers/imap/camel-imap-stream.c (stream_read): Only cache - the important data (aka the mime part requested and no extra - server response stuff) - -2000-07-07 Dan Winship - - * camel-mime-utils.c (header_references_decode): Work around - In-Reply-To's with unquoted punctuation. So many broken mailers. - - * camel-folder.c (camel_folder_search_by_expression): Make this - return a GPtrArray rather than a GList. - - * camel-folder-search.c (camel_folder_search_execute_expression): - * providers/imap/camel-imap-folder.c (imap_search_by_expression): - * providers/mbox/camel-mbox-folder.c (mbox_search_by_expression): - * providers/nntp/camel-nntp-folder.c (nntp_search_by_expression): - Update to return a GPtrArray rather than a GList. - -2000-07-07 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (esmtp_get_authtypes): - Fixed the parser to actually work - -2000-07-06 Dan Winship - - * camel-mime-utils.c (header_references_decode): Make this deal - with the full RFC822 References/In-Reply-To format rather than - just the more-nicely-behaved RFC1036 version. (Needed to parse - In-Reply-To headers with extra junk in them.) - -2000-07-06 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_summary): Parse for - more header information to allow message threading in IMAP. - (imap_get_message_info): Same. - - * camel-folder-summary.c: Renamed summary_format_* to - camel_summary_format_* and moved them into public scope. - - * providers/smtp/camel-smtp-transport.c (smtp_connect): Oops. Don't - pass port # as a string in the error code (if it fails to connect). - - * providers/imap/camel-imap-folder.c (imap_append_message): Changed - over to camel_imap_command_extended as that was the source of the - problems - apparently appending replies with more than just 1 line. - -2000-07-05 Dan Winship - - * camel-folder-search.c (search_header_contains): make header - matching case-insensitive - - * camel-folder-summary.c: - * camel-session.c: - * providers/mbox/camel-mbox-folder.c: - * providers/mbox/camel-mbox-summary.c: Remove some non-error case - debugging-type messages. - -2000-07-05 Ettore Perazzoli - - * providers/mbox/camel-mbox-summary.c (d): Define to empty so that - we get rid of a ton of debugging messages. - -2000-07-05 Jeffrey Stedfast - - * camel-mime-utils.h: Added prototype for uudecode_step - - * camel-mime-utils.c (uudecode_step): Cleaned up some junk that - should have been cleaned up when debugging printf's were taken out. - -2000-07-05 Ettore Perazzoli - - * providers/mbox/camel-mbox-summary.c (camel_mbox_summary_sync): - Update the X-Evolution: header even if the in-memory UID and the - saved UID are not the same. Otherwise mboxes with clashing UIDs - can never be fixed. - - * camel-folder-summary.c - (camel_folder_summary_add_from_parser): Add the message to the - summary before doing any ibex stuff. In fact, this might also - have the side effect of reassigning the UID so it needs to be done - before we start using the UID. - - * providers/mbox/camel-mbox-folder.c (mbox_append_message): Add - debugging message to keep track of the UIDs we add. - -2000-07-05 Dan Winship - - * camel-folder-summary.c: Add "Cc" to summary and bump summary - version number. - - * camel-folder-search.c (search_header_contains): make "Cc" a - searchable header. - -2000-07-03 Ettore Perazzoli - - * camel-folder-summary.c (camel_folder_summary_next_uid_string): - New. - (camel_folder_summary_add): Use - `camel_folder_summary_next_uid_string()' instead of recomputing - the UID manually here. - (camel_folder_summary_add_from_parser): Likewise. - -2000-07-03 Ettore Perazzoli - - * camel-folder-summary.c (camel_folder_summary_set_uid): Removed. - -2000-07-03 Dan Winship - - * camel-folder-summary.c (message_info_new): Parse In-Reply-To - with header_references_decode, not header_msgid_decode. - - * camel-mime-message.c (camel_mime_message_class_init): message - headers are case-insensitive. - - * providers/pop3/camel-pop3-store.c (camel_pop3_command): Fix a - bug in error-setting code. - (pop3_connect): Don't re-prompt for password in the KPOP case. - (pop3_get_response): New function, split out from - camel_pop3_command. - (connect_to_server): Use pop3_get_response to parse the greeting - message, and error out appropriately if it's -ERR. - -2000-07-02 Dan Winship - - * camel-folder.c (camel_folder_freeze, camel_folder_thaw): New - functions to freeze and thaw a folder (to prevent message/folder - changed signals in the middle of a long series of operations). - (camel_folder_class_init): Change signals to GTK_RUN_FIRST. - (message_changed, folder_changed): Add default implementations - that stop the emission and record info for later if the folder is - frozen. - - * providers/mbox/camel-mbox-folder.c (mbox_sync): leftover fixes - from the close->sync change: don't destroy the ibex, summary, and - search when syncing. - (append_message): emit "folder_changed" on a successful append. - -2000-07-02 Jeffrey Stedfast - - * camel-mime-utils.c (uudecode_step): A rather complex uudecoder - written in the spirit of Zucchi-ness, is it up to par? Only the - Z-man can tell us :-) - -2000-07-01 Dan Winship - - * camel-service.c (camel_service_get_name): New method, to return - an end-user-friendly name corresponding to a service. (eg, "POP - service for danw on trna.helixcode.com"). - - * providers/imap/camel-imap-store.c, - providers/mbox/camel-mbox-store.c, - providers/nntp/camel-nntp-store.c, - providers/pop3/camel-pop3-store.c, - providers/sendmail/camel-sendmail-transport.c, - providers/smtp/camel-smtp-transport.c: Implement. - - * providers/imap/Makefile.am: remove unneeded - libcamelimap_la_LDADD. - - * providers/pop3/camel-pop3-store.c (connect_to_server): fix the - CAPA-parsing code to not get into an infinite loop. - -2000-07-01 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_message): Fixed - the bug that would sometimes leave part of the server response - tacked on to the end of the message. - - * camel-folder.c: Renamed _by_uid methods. Since we no longer - have get-by-number methods, no need to have the _by_uid - extensions. - (get_message_by_uid): Renamed to get_message - (delete_message_by_uid): Renamed to delete_message - (summary_get_by_uid): Renamed to get_message_info - - * providers/mbox/camel-mbox-folder.c: - * providers/pop3/camel-pop3-folder.c: - * providers/imap/camel-imap-folder.c: - * providers/vee/camel-vee-folder.c: Updated to reflect - camel-folder changes. - -2000-06-30 Jeffrey Stedfast - - * camel-folder.c (camel_folder_copy_message_to): New function, to - copy a message from one folder to another. The default - implementation just uses append_message, but providers can - implement more efficient versions for use when both folders are on - the same store. - - * broken-date-parser.[c,h]: Utilities for parsing broken - date strings. - - * providers/imap/camel-imap-folder.c (imap_move_message_to): - (imap_copy_message_to): Implemented. - - * camel-mime-utils.c (header_decode_date): Wrote some code to try - and un-mangle broken date formats and then parse that new string - instead. - -2000-06-30 Dan Winship - - * camel-folder.c (camel_folder_move_message_to): New function, to - move a message from one folder to another. The default - implementation just uses append_message and delete_message, but - providers can implement more efficient versions for use when both - folders are on the same store. - -2000-06-29 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_expunge): Should now - print a meaningful error message when it doesn't succeed - -2000-06-28 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (imap_connect): Changed to - keep prompting user for a valid password until it either - authenticates or until Canceled by the user. - (camel_imap_command_extended): Improved speed (replaced the - g_strjoinv call with a faster implementation) - - * providers/pop3/camel-pop3-store.c - (camel_pop3_command_get_additional_data): Fixed. - (pop3_connect): Changed to keep prompting the user for a - password until it either works or until Canceled by the user. - - * providers/mbox/camel-mbox-summary.c: General cleanup - (camel_mbox_summary_sync): Fixed a memory leak and added - CamelException handling. - - * providers/mbox/camel-mbox-store.c (delete_folder): Fixed a - memory leak - - * providers/mbox/camel-mbox-folder.c (mbox_append_message): - Default 'off_t seek' to -1 so as to make sure it's initialized - before it's used in the case of a bad stat() call. - (mbox_sync): Updated - (mbox_expunge): Updated - -2000-06-27 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (imap_connect): Move the - CAPABILITY command here so we don't have to keep checking - each time we open a folder. - (camel_imap_command_extended): If we are doing an EXAMINE, - don't bother doing a SELECT first. - - * providers/imap/camel-imap-folder.c (imap_init): Update so - folder->has_search_capability depends on the parent IMAP store - (since this is really dependant on the IMAP implementation and - not the folder) - -2000-06-27 Christopher James Lahey - - * providers/smtp/camel-smtp-transport.c: Don't close the filter - stream when done with it (this causes the source stream to close); - Instead, just flush it when done. - -2000-06-27 Michael Zucchi - - * camel-folder-search.c (search_header_contains): Make header - search 'to' match 'to', and not 'from', small typo, fixes #317. - -2000-06-26 Christopher James Lahey - - * providers/mbox/camel-mbox-summary.c: Added debugging - information. - -2000-06-23 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c: - * providers/imap/camel-imap-folder.c: Improved folder parsing. - Not specifying a namespace should no longer list the entire - filesystem. - -2000-06-22 Chris Toshok - - * providers/nntp/.cvsignore: ignore test-newsrc - - * providers/nntp/camel-nntp-store.c, - providers/nntp/camel-nntp-store.h, - providers/nntp/camel-nntp-folder.c, - providers/nntp/camel-nntp-folder.h, - providers/nntp/camel-nntp-utils.c: Bring the nntp provider up to a - state where it builds and is usable with the current camel. there - are still warts (semi-broken .newsrc file handling, and a lack of - a subscribe ui -- in fact no way to add a new server, really), but - it'll display news messages. - - * providers/nntp/Makefile.am (libcamelnntp_la_SOURCES): add - camel-nntp-newsrc.c - (libcamelnntpinclude_HEADERS): add camel-nntp-newsrc.h - also, add test-newsrc stuff. - - * providers/nntp/test-newsrc.c: new file that tests the newsrc - stuff by parsing and regurgitating a .newsrc file for a particular - server. - - * providers/nntp/camel-nntp-newsrc.c, - providers/nntp/camel-nntp-newsrc.h: new files, initial support for .newsrc files. - -2000-06-22 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_message_count): - Oops. Now appends the namespace to the folder before querying - for the number of messages. - - * providers/imap/camel-imap-store.c (imap_folder_exists): New - convenience function for use by imap_create(). - (get_folder): If folder is specified as "/", we really want - "INBOX". - - * providers/sendmail/camel-sendmail-provider.c: - * providers/vee/camel-vee-provider.c: - * providers/smtp/camel-smtp-provider.c: - * providers/mbox/camel-mbox-provider.c: - * providers/pop3/camel-pop3-provider.c: - * providers/imap/camel-imap-provider.c: Updated - - * camel-session.c: Moved service_cache hash table into the - providers. - (service_cache_remove): Updated. - (camel_session_get_service): Updated. - - * camel-url.c (camel_url_hash): Took out the hashing of - url->passwd. We don't want this anymore. - - * providers/imap/camel-imap-folder.c (imap_init): Took out - references to 'namespace' - (camel_imap_folder_init): Same - - * providers/imap/camel-imap-folder.h: No more namespace. We are - instead going to use url->path as the namespace. - -2000-06-21 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (imap_create): Modified to - use the "namespace" (url->path) if it exists. - - * providers/imap/camel-imap-folder.c (imap_delete_message_by_uid): - Now just sets the deleted flag on the summary rather than speaking - directly to the IMAP server. This is both faster and cleaner. - -2000-06-21 Dan Winship - - * providers/pop3/camel-pop3-store.c (query_auth_types): Fix dumb - bug. - -2000-06-21 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_message_by_uid): - We are getting mail in IMAP now!! whoo-hoo!. Stripped out the - filtering so messages may have some dot-stuffing, but the - filtering can always be added back in later when we know it - works and isn't the problem. - -2000-06-21 Peter Williams - - * providers/mbox/camel-mbox-folder.c (mbox_init): Use the basename - of the mailbox so we don't get pathnames like ~/evolution/inbox///movemail.ibex - -2000-06-21 Dan Winship - - * camel-folder-summary.c (message_info_new): Set date_received - based on the first (most recent) "Received" header. - -2000-06-20 Dan Winship - - * camel-mime-part.c (write_to_stream): flush the filter stream - before unreffing it, so it will camel_mime_filter_complete. - - * camel-stream-filter.c (camel_stream_filter_class_init): Fix a - braino so camel_stream_flush works here. - - * camel-stream-mem.c (stream_seek): Fix a bug that resulted in - large attachments being silently dropped. - - * providers/pop3/camel-pop3-store.c - (camel_pop3_command_get_additional_data): Don't use g_strjoinv - here, since it is O(n^2) on the length of the output string, and - we can do O(n). - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): add a CRLF decoder - after the QP/B64 decoder if it's text. - -2000-06-20 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_summary): Only - fetch the summary if the folder summary doesn't already exist. - When the summary *does* exist, start fetching from 1, not 0. - (imap_free_summary): Don't do anything here. - (imap_finalize): Free the summary here instead of in - imap_free_summary(). - (imap_set_message_flags): Implemented - (imap_sync): Added code to set flags on messages that have had - their flags changed (however I #if'd it out until we are more - confidant in the IMAP code :) - (imap_summary_get_by_uid): Now parese flags correctly. - (imap_get_summary): Now parese flags correctly. Also correctly - parses the UID correctly. - - * camel-url.c (check_equal): No need to check s1 if s2 is NULL - (camel_url_equal): Don't check the passwd component of the url. - -2000-06-20 Dan Winship - - * camel-folder-summary.c (camel_folder_summary_add): mark the - message info with CAMEL_MESSAGE_FOLDER_FLAGGED if we change the - uid, so the folder will know that it's dirty. - -2000-06-20 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (camel_imap_command_extended): - Now returns the last line of data that the server sends back as - well. This is needed for commands like SELECT (like Peter pointed - out). - (camel_imap_command): No longer checks for SELECT (no need) - - * providers/imap/camel-imap-folder.c: Added namespace stuff - which we will need later on... - (imap_parse_subfolder_line): Convenience function for use in - get_subfolder_names() - (imap_get_subfolder_names): Updated. Also changed it to use LIST - instead of LSUB (temporary change). - -2000-06-19 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (camel_imap_folder_init): Set - summary equal to NULL. - (imap_get_summary): Store the summary in the ImapFolder - (imap_summary_get_by_uid): If we have a summary cache in the - ImapFolder, first check to see if that message info is in the - cached summary first, if not fetch it directly from the IMAP - server and append it to the summary cache. - (imap_get_message_flags): Don't free the message info that we get - back from summary_get_by_uid as we don't want to be corrupting our - cached summary. - -2000-06-19 Peter Williams - - * providers/imap/camel-imap-store.c (camel_imap_command{,_extended}): When - SELECT'ing a folder for an IMAP command, use _extended to grab the entire - response (before we just used camel_imap_command and missed the OK codes) - -2000-06-18 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_summary_get_by_uid): - Now gets the message flags as it should. - (imap_get_summary): Same as imap_summary_get_by_uid - (imap_get_permanent_flags): Return the permanent flags stored - on the folder. - (imap_get_message_flags): Return message flags associated with - given uid. Note: we may want to somehow cache summary info so - that we don't have to keep querying the IMAP provider in - imap_summary_get_by_uid(). - -2000-06-17 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_free_summary): We were - leaking memory - but not anymore! - (imap_get_summary): We now get the UIDs and the beginnings of the - code to get the message flags as well. - -2000-06-17 Dan Winship - - * camel-mime-parser.c (folder_scan_header): Don't copy newlines - into the parsed header text, and turn any number of tabs and - spaces after a newline into a single space. - -2000-06-17 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_init): Should now - correctly do CAPABILITY. - -2000-06-17 Dan Winship - - * providers/mbox/camel-mbox-summary.c: Add some debugging printfs - when rebulding summary to help figure out why people's summaries - are always being rebuilt. - -2000-06-17 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_search_by_expression): - Began to implement, need to get information on how to - deconstruct @expression into an IMAP search expression and - parse the results. - (imap_init): Now queries the IMAP provider for CAPABILITY to - determine if SEARCH is implemented or not. - - * providers/imap/imap.c: Removed - no longer a need to have - this as an example for anyone interesting to help mecode IMAP - support. - -2000-06-16 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_sync): Added code - to expunge if called for (still need to finish coding this). - (imap_get_uids): Implemented. - (imap_get_summary): Found a way to get the date - (imap_summary_get_by_uid): Same. - (imap_free_summary): Implemented. - - * string-utils.c (strstrcase): Fixed a compile warning - - * providers/imap/camel-imap-summary.c: Removed - we don't - need a CamelImapSummary structure. - -2000-06-16 Dan Winship - - Move flag handling from CamelMimeMessage to CamelFolder. This - simplifies several flag-handling pieces of code in the mailer, and - lets you change a message's flags without having to fetch the - message body. It also means that fully-constructed - CamelMimeMessages are now essentially constant, which will help - simplify locking issues later since it means two threads - interested in the same message can just work with separate copies - of it. - - * camel-mime-message.h (struct _CamelMimeMessage): Removed flags - and user_flags (moved to summary). Removed expunged and - message_number which were unused. Removed message_uid and folder - which are no longer needed in the new scheme. - (struct CamelMimeMessageClass): Removed message_changed signal and - get/set_message_number methods. - - * camel-mime-message.c: Updates for CamelMimeMessage changes. - (camel_mime_message_get/set_flags, - camel_mime_message_get/set_user_flag): Replaced with methods in - CamelFolder. - (camel_flag_get, camel_flag_set, camel_flag_list_size, - camel_flag_list_free): Moved verbatim to camel-folder-summary.c - - * camel-folder.c (camel_folder_get/set_message_flags, - camel_folder_get/set_message_user_flag): New methods (and - corresponding useless default implementations) - (camel_folder_class_init): add a message_changed signal - - * camel-folder-summary.c (camel_flag_get, camel_flag_set, - camel_flag_list_size, camel_flag_list_free): Moved here from - camel-mime-message.c - - * providers/mbox/camel-mbox-folder.c (message_changed): Removed. - (mbox_get_message_flags, mbox_set_message_flags, - mbox_get_message_user_flag, mbox_set_message_user_flag): Tweak - summary bits as appropriate. (Functionality moved here from - message_changed.) - (mbox_get_message_by_uid): Update for CamelMimeMessage changes - (less stuff to initialize). - - * providers/imap/camel-imap-folder.c (message_changed): Remove - this. It was just copied from the mbox provider and doesn't deal - with the real IMAP flag stuff anyway. (So there's currently no - flag support in the IMAP provider.) - (imap_get_message_by_uid): Update for CamelMimeMessage changes. - - * providers/vee/camel-vee-folder.c: (message_changed): Remove old - one. Add a new one to listen for message_changed on each folder - and re-emit message_changed signals that correspond to messages in - the vfolder. - (vee_get/set_message_flags, vee_get/set_message_user_flag): Proxy - flag setting to the underlying real messages. - (vee_append_message): Removed for now; there's no way to translate - this into the new CamelMimeMessage/CamelFolder scheme, but (a) - there's also no code which would ever call it and (b) we're - probably going want a better interface than append_message for - message drag and drop to work anyway. To be revisited. - -2000-06-16 Dan Winship - - * camel-mime-utils.c (rfc2047_decode_word): - * camel-mime-part-utils.c (simple_data_wrapper_construct_from_parser): - * camel-folder-summary.c (summary_build_content_info): - KLUDGE! Since neither ETable nor GtkHTML supports UTF-8 yet, - output ISO-8859-1 instead, so Ettore can read his Italian mail. :) - This will be reverted later. - -2000-06-15 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_summary): Started to - implement - may want to use ENVELOPE instead of BODY.PEEK[HEADER] - (imap_summary_get_by_uid): Started to code, I've got to find a way to - get the date in time_t format and also get the flags - - * string-utils.c (strstrcase): Added this convenience function - I - know about strcasestr() but it's not portable. - -2000-06-15 Dan Winship - - * camel-service.c: Remove camel_service_connect_with_url. (URLs - must be specified when the service is requested from the session, - so that there can only ever be one service for any URL.) - - * camel-folder.c: (camel_folder_open, camel_folder_is_open, - camel_folder_get_mode): Kill. Folders are now always open, and - handle "closing" sorts of operations at sync or finalize time. - (camel_folder_sync): renamed from camel_folder_close. Syncs state - to the store but doesn't necessarily close/disconnect. - - * providers/*/camel-*-folder.c: Merge "open" methods into "init" - methods. Rename close to sync and update appropriately. - - * providers/imap/camel-imap-store.c: Remove camel_imap_store_open - and camel_imap_store_close, which should not have been copied from - the POP provider (where the exist to work around limitations of - the POP protocol). - - * providers/mbox/camel-mbox-summary.c: fix a bug. (don't expunge - deleted messages if called with expunge == FALSE) - - * providers/pop3/camel-pop3-store.c (connect_to_server): Check - server for various interesting extensions. - - * providers/pop3/camel-pop3-folder.c (get_uids): If the server - supports UIDL, use real UIDs rather than fake ones. - (etc): Map uids back to numbers appropriately - - * providers/mbox/camel-mbox-folder.c (mbox_append_message): Fix to - previous change: make sure the "seek" variable ends up with the - value it should. - - * providers/mbox/camel-mbox-summary.c (summary_rebuild): Update - summary mtime as well as size. - -2000-06-14 Dan Winship - - * providers/mbox/camel-mbox-folder.c (mbox_append_message): if the - mbox doesn't end with a '\n', write one before appending the new - message. - -2000-06-14 Jeffrey Stedfast - - * camel-mime-filter-crlf.c (filter): Updated the encoder to allocate - more memory (since we are also now adding dots). Also updated the - decoder as we have found that it sometimes passes the end of the - buffer. - - * providers/pop3/camel-pop3-folder.c (get_message_by_uid): Took out the - filter code (we already filter in - camel_pop3_command_get_additional_data) - - * camel-folder.c (init): Updated: a separator is now a char* rather - than a single char because IMAP can have a string for a directory - separator. Also, since IMAP does not begin with a directory separator, - there is a new argument (path_begins_with_sep) which decides if a - directory should begin with a directory separator. - - * providers/imap/camel-imap-store.c (imap_create): Since, on connect, - Camel tries to create INBOX (which already exists on every IMAP - provider) we can return TRUE when the folder name is "INBOX". - - * providers/vee/camel-vee-folder.c (vee_init): Updated. - - * providers/imap/camel-imap-folder.c (camel_imap_folder_new): Updated. - - * providers/mbox/camel-mbox-store.c (get_folder): Updated. - - * providers/mbox/camel-mbox-folder.c (mbox_init): Updated. - - * providers/pop3/camel-pop3-folder.c (camel_pop3_folder_new): Updated. - -2000-06-14 Dan Winship - - * providers/mbox/camel-mbox-summary.c (camel_mbox_summary_sync): - Renamed from camel_mbox_summary_expunge. Takes a gboolean saying - whether to expunge or just sync the mbox file. Change some - g_errors to g_warning so we don't abort. Make the quick - X-Evolution updating code lseek around correctly. Update the - mbox mtime in the summary file even in the quick case. - - * providers/mbox/camel-mbox-summary.h: make - CAMEL_MESSAGE_FOLDER_NOXEV not conflict with - CAMEL_MESSAGE_FOLDER_FLAGGED defined in camel-mime-message.h - - * providers/mbox/camel-mbox-folder.c (mbox_close): call - camel_mbox_summary_sync to save flag state if not expunging. - (mbox_expunge): Update for camel_mbox_summary_expunge rename. - -2000-06-13 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (camel_imap_store_open): - (camel_imap_store_close): Added. - (camel_imap_command_extended): Fixed a segfault and updated - to use camel_imap_status() - (camel_imap_command): Updated to use camel_imap_status() - (camel_imap_status): New convenience function for parsing - the return status of an IMAP command - -2000-06-12 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c (imap_get_message_by_uid): - Works like the POP fetch code, should work temporarily until - we get around to coding it the way it "Should Be". - - * providers/pop3/camel-pop3-folder.c (get_message_by_uid): Now uses - the camel-mime-filter-crlf decoder when retrieving messages. - - * camel-mime-filter-smtp.c: Deprecated. - - * providers/smtp/camel-smtp-transport.c (smtp_data): Updated to use - camel-mime-filter-crlf with my 'dot' extension in place of - camel-mime-filter-smtp - - * camel-mime-part.c (write_to_stream): Updated to reflect changes - made to camel-mime-filter-crlf.c - - * camel-mime-filter-crlf.c (filter): Modified to be able to - encode/decode dots ("\n.\n"<->"\n..\n"). Also fixed the decoder - so that it should no longer get caught in an infinite loop. - -2000-06-12 Dan Winship - - * providers/*/Makefile.am: don't pass a second (incorrect) -rpath - in addition to the (correct) one automatically provided by - automake. - - * camel-mime-filter-crlf.c: New filter to do CRLF<->LF conversion. - (Currently only tested in the LF->CRLF direction.) - - * camel-mime-part.c (write_to_stream): if content-type is text, - and it's QP or B64 encoded, pass through the CRLF filter before - the other filter to satisfy the "canonical encoding" rules in the - MIME spec. - -2000-06-09 Dan Winship - - * camel-session.c (camel_session_query_authenticator): Add another - argument, "mode", which can be CAMEL_AUTHENTICATOR_ASK or - CAMEL_AUTHENTICATOR_TELL, so callers can get the app to un-cache - bad info. - - * providers/pop3/camel-pop3-store.c (pop3_connect): uncache the - password if it doesn't work. - -2000-06-09 Jeffrey Stedfast - - * providers/imap/camel-imap-stream.c (stream_read): Updated to reflect - changes made in camel-imap-store.c - - * providers/imap/camel-imap-store.c (imap_create): No longer checks to - make sure a folder doesn't already exists (as this is no longer needed) - (camel_imap_command): Now takes a CamelFolder argument so it can detect - whether or not it needs to SELECT a folder or not - (camel_imap_command_extended): Same. - - * providers/smtp/camel-smtp-transport.c (smtp_connect): Will now always - send EHLO first, if that fails it will fall back on HELO. - (esmtp_get_authtypes): Should now correctly parse authtypes. - -2000-06-07 Jeffrey Stedfast - - * providers/imap/camel-imap-summary.c: Now builds (not that it's worth - much yet). - - * providers/imap/camel-imap-folder.c (imap_get_uids): Now uses the - correct cast to a CamelImapMessageInfo structure (should get rid of - compile warnings). - - * providers/imap/Makefile.am: Added rules to build - camel-imap-stream - - * providers/imap/camel-imap-store.c (get_folder): Update. - Moved imap_create here. - - * providers/imap/camel-imap-folder.c (delete_messages): Remove. - (imap_create): Removed. - (imap_delete): Removed. - (imap_exists): Removed. - - * providers/imap/camel-imap-stream.h: Added typedef's for the stream - - * providers/imap/camel-imap-stream.c: Modified to build cleanly - -2000-06-07 Not Zed - - * camel-mime-utils.c (header_msgid_decode_internal): Properly - dereference warning/debug messages. - (header_references_decode): Check we actually have msgid stuff - before trying to decode it ... - -2000-06-06 Jeffrey Stedfast - - * camel-imap-stream.[c,h]: Removed - - * providers/imap/camel-imap-stream.[c,h]: Relocated to this - location - - * providers/imap/camel-imap-summary.c: Added - -2000-06-06 Dan Winship - - * camel-folder.c: Remove exists, create, delete. A CamelFolder - now always references an existing folder. Remove delete_messages - too since it wasn't being used. Add a "create" flag to - get_subfolder saying whether or not to create the subfolder if it - doesn't yet exist. - - * camel-store.c (camel_store_get_folder): Add a "create" flag to - say whether or not to create the folder if it doesn't yet exist. - (camel_store_delete_folder): New method, moved from CamelFolder. - (cache_folder, uncache_folder): Fix up a bit. - (get_folder_name): Explain what this is for. - - * providers/mbox/camel-mbox-folder.c: - * providers/mbox/camel-mbox-store.c: Update. Remove support for - hierarchical folders to simplify this for now, since we're not - using it, and it's not completely clear how they should work in an - ELocalStorage world. Needs to be revisited. - - * providers/pop3/camel-pop3-folder.c (delete_messages): Remove. - * providers/pop3/camel-pop3-store.c (get_folder): Update. - - * providers/vee/camel-vee-folder.c (exists): Remove. - * providers/vee/camel-vee-store.c (vee_get_folder): Update. - -2000-06-06 Jeffrey Stedfast - - * providers/imap/camel-imap-*.[c,h]: Started on getting - imap to build cleanly (tho some work has not been completed - so it still won't build until camel-imap-summary is finished - along with a few methods in camel-imap-folder) - - * camel-stream.[c,h]: Changed the read and write method prototypes - to return an ssize_t type rather than an int and also changed - the 'number of bytes' to read or write to a size_t type - - * camel-stream-fs.c: same as above - - * camel-stream-mem.c: again, same as above - - * camel-stream-buffer.c: same - - * camel-imap-stream.[c,h]: Added this new stream, cache's previously - read data so each successive call will instead read from the cache - -2000-06-05 Dan Winship - - * camel-mime-part.c (camel_mime_part_set_disposition): fix - typo/braino (set "Content-Disposition", not "Content-Description") - (camel_mime_part_set_filename): const poison - -2000-06-02 Not Zed - - * camel-mime-utils.c (base64_encode_step): Ick, damn signs! Fix a - bug with sign extended bytes. - - * camel-mime-filter-smtp.c (filter): Changed layout/logic slightly - (to match From filter) - -2000-06-02 Jeffrey Stedfast - - * camel-mime-filter-smtp.c (filter): Fixed the filter so that it - wouldn't insert garbage under certain conditions. - -2000-06-02 Christopher James Lahey - - * camel-session.c: Don't ref the services in the cache. - -2000-06-02 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c: Rearanged where debug - fprintf statements we placed so that any data the server sends - back is printed out before an exception is set and the function - returns. - -2000-06-02 Not Zed - - * camel-mime-utils.c (header_decode_date): If we get a funny - result, just throw it out. Basically a fix for the one true - broken TradeClient. - -2000-06-01 Not Zed - - * camel-folder-summary.c (message_info_free): Free - references/messsage id. - (message_info_save): Save them. - (message_info_load): Load them. - (message_info_new): And get them from the new message. - (CAMEL_FOLDER_SUMMARY_VERSION): Bumped for new changes. - - * camel-folder-summary.h: Added references and messageid to - summary. - -2000-06-02 Christopher James Lahey - - * camel-session.c: Ref and unref objects in the service cache - properly. - - * camel-store.c: Ref the folder when returning it using - lookup_folder. Used the folder's full name for the key for the - folder cache since that's used to uncache it. - -2000-06-02 Dan Winship - - Fun with purify. - - * providers/pop3/camel-pop3-store.c (pop3_connect): free msg on - success as well as failure. - (camel_pop3_command_get_additional_data): free buf after reading - the last line ("."). - - * providers/pop3/camel-pop3-folder.c (get_message_by_uid): free - body data after creating the memstream from it (which will copy - the data). - - * providers/mbox/camel-mbox-folder.c (mbox_finalize): free summary - and index paths. - - * camel-data-wrapper.c (finalize): unref the stream, if it exists. - -2000-06-01 Not Zed - - * camel-mime-part.c (construct_from_parser): For a message part, - set the default content-type to message/rfc822. Maybe needs to be - done for multiparts too? - -2000-05-31 Not Zed - - * camel-mime-message.c (construct_from_parser): Typo in assersion. - - * camel-mime-parser.c (folder_scan_step): Use a default type of - message/rfc822 for multipart/digest. Bug Z192. - (folder_scan_drop_step): Remove warning. - -2000-05-30 Not Zed - - * providers/mbox/camel-mbox-folder.c (mbox_append_message): Init - filter_from to NULL, for exception case. - (mbox_get_message_by_uid): Cast off_t to long int for diagnostics. - - * camel-url.c (camel_url_hash): Hash funciton for using camel - url's as hash keys. - (camel_url_equal): equal function for same. - - * camel-session.c (camel_session_finalise): Free cached services. - (camel_session_init): Init service cache. - (service_cache_remove): destroy callback to remove a service from - the cache. - - * camel-store.c (get_folder_internal): Remove the extra ref of the - folder. That seems the right behaviour ...? - (camel_store_get_type): Doh, actually call store init, so the - cache works. - (cache_folder): strdup the folder name! no wonder it never found - it again. - -2000-05-30 Jeffrey Stedfast - - * providers/imap/camel-imap-folder.c: Implemented a few more - methods like imap_append and 1 or 2 others - -2000-05-29 Not Zed - - * camel-store.c (camel_store_init): Move it to here. If this - level is going to maintain it, it should set it up. Lets see what - caching folders breaks :( - - * providers/pop3/camel-pop3-store.c (camel_pop3_store_init): Dont - init folder cache here. - - * providers/mbox/camel-mbox-summary.c - (camel_mbox_summary_expunge): Make sure we copy messages which are - still intact to the new folder. - (camel_mbox_summary_expunge): Update the frompos as well when - moving the content. - (camel_mbox_summary_expunge): Remove some debug, and dont offset - frompos? - - * providers/vee/camel-vee-folder.c (vee_folder_build): Check the - searched folder is open before trying to search it. - (message_changed): Track changes to the source message in the - summary. - (folder_changed): Track folder changes, re-query the folder that - changed, and cascade the changed event as well. - (camel_vee_folder_finalise): Free subfolder and subfolder summary. - -2000-05-29 Dan Winship - - * camel-service.c (camel_service_new): Fix up some glib - precondition stuff. Try to set the URL in camel_service_new before - checking whether or not it's "empty" so that you can successfully - set "sendmail:" as a URL. - -2000-05-28 Dan Winship - - * camel-provider.h: Add a domain field to CamelProvider, to say - what kind of data it provides. - - * providers/imap/camel-imap-provider.c: - * providers/mbox/camel-mbox-provider.c: - * providers/pop3/camel-pop3-provider.c: - * providers/sendmail/camel-sendmail-provider.c: - * providers/smtp/camel-smtp-provider.c: Set domain to "mail". - - * providers/nntp/camel-nntp-provider.c: Set domain to "news". - - * providers/vee/camel-vee-provider.c: Set domain to "vfolder". (So - it doesn't end up being listed as a potential mail source in the - mail config wizard.) - - * providers/pop3/camel-pop3-store.c: Split apart password and APOP - auth, since some servers seem to do both, but don't really. - (connect_to_server): Renamed from try_connect. Now actually does - the connection up to the point of checking the greeting for APOP - support. - (query_auth_types): Return APOP, if appropriate. Call - pop3_disconnect after connect_to_server since we don't really want - to be connected. - (pop3_connect): Use connect_to_server rather than duplicating - code. Fix a one-byte buffer overrun in the APOP code. - (pop3_disconnect): Make this able to clean up after a partial - connect. - (connect_to_server): Remove port number from error message since - it's not terribly useful and we were getting it from the wrong - place anyway. - - * camel-mime-utils.c (header_address_list_format_append): Use - `foo@bar' rather than `"" ' for email addresses with no - name component. - -2000-05-27 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c: Removed - camel_imap_command_get_additional_data() as it was - completely useless, replaced with - camel_imap_command_extended() which may eventually replace - camel_imap_command() as well. - - * providers/imap/camel-imap-store.h: Modified to reflect - changes made to camel-imap-store.c - - * providers/imap/camel-imap-folder.c: Wrote the first of many - methods: camel_imap_init(), imap_open(), imap_expunge(), - imap_get_message_count(), and imap_get_subfolder_names() - -2000-05-26 Dan Winship - - * camel-multipart.c (camel_multipart_init): Don't set a default - boundary. Require the caller to do that. - (set_boundary): if boundary is NULL, generate a "random" boundary. - - * camel-mime-part-utils.c - (camel_mime_part_construct_content_from_parser): Add a call to - camel_multipart_set_boundary after creating a new multipart. - -2000-05-25 Jeffrey Stedfast - - * providers/imap/camel-imap-store.c (try_connect): Removed - Exception code - Pop doesn't seem to set exceptions - - * providers/imap/camel-imap-folder.c: Initial code, mostly - just a template for future code - - * providers/imap/imap.[c,h]: Source code from my personal - mailer - for reference only! - -2000-05-25 NotZed - - * camel-mime-part-utils.c - (camel_mime_part_construct_content_from_parser): Replace simple - data wrapper here too, oops. - - * Makefile.am (libcamel_la_SOURCES): Removed - camel-simple-data-wrapper again. Less code to maintain == better - code. - - * camel-data-wrapper.c (construct_from_stream): Fixes for bug - where text attachments dont work. Made data-wrapper concrete for - the second time. - -2000-05-23 NotZed - - * providers/vee/camel-vee-folder.c (vee_folder_build_folder): - Update the vfolder details for a single folder. - -2000-05-25 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (_send_to): Took out code - that had been there to reconnect to the server if it was not - already connected - Mailer code was fixed so that this should not - be needed. - - * providers/imap/camel-imap-store.[c,h]: Initial code. - -2000-05-24 Dan Winship - - * camel.h: Re-add camel-simple-data-wrapper.h, which was removed - for some reason. - -2000-05-24 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.[c,h]: Moved global - variables into struct CamelSmtpTransport to make SMTP - thread-safe - - * providers/imap/camel-imap-*.h: Stolen from Mbox. Rough structure - for Imap. - -2000-05-23 Jeffrey Stedfast - - * providers/imap: Added some initial code to the camel tree - for IMAPv4 - - * providers/imap/.cvsignore: Added to repository - - * providers/smtp/camel-smtp-transport.c: Added debug fprintf's - so that testers can provide more information. Tested with simple - messages and a reply to the hello@helixcode.com default message - but should really be tested more. - (smtp_data): Fixed to use data_wrapper_write_to_stream. - - * camel-mime-filter-smtp.c (filter): Modified to escape all lines - beginning with a '.' and to place a \r before each \n if one did - not previously exist. Removed code to escape "From " as it was - found to not be needed for SMTP. - -2000-05-22 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c (smtp_data): Fixed the - filtered stream. Fixes for stream changes, updated to use - camel-mime-filter-smtp. - - * Makefile.am: Added camel-mime-filter-smtp.c - - * camel-mime-filter-smtp.[c,h]: Added to camel tree - Smtp filter used to change \n into \r\n, escape lone dots, - and escape "From "'s. - -2000-05-19 NotZed - - * camel-simple-data-wrapper.c (construct_from_stream): If we - already have been constructed, unref our content. - (write_to_stream): Check we've been constructued, and change for - stream api changes. - - * camel-mime-parser.c: Removed exception stuff. - - * md5-utils.c (md5_get_digest_from_stream): repaired. - - * camel-mime-message.c: Remove exception from write_to_stream, and - fix, and fix formatting. - - * providers/sendmail/camel-sendmail-transport.c (_send_internal): - Fix for stream changes. - - * providers/pop3/camel-pop3-store.c (camel_pop3_command): Fixes - for stream changes. - - * providers/mbox/camel-mbox-folder.c, and elsewhere, fix all - stream api changes. - (mbox_append_message): Use stream_close() now its back. - (mbox_append_message): unref the from filter. - - * camel-stream-mem.c: And here. - - * camel-stream-fs.[ch]: Here too. - - * camel-stream-filter.c: Likewise. This is getting tedious. - - * camel-stream-buffer.c (stream_write): Fix a few little problems. - (stream_close): Reimplement. - (camel_stream_buffer_read_line): Slightly more efficient version, - that also only allocates the right amount of memory for strings. - - * camel-seekable-substream.c: Likewise. - - * camel-seekable-stream.[ch]: Remove exceptions, fix formatting, - changes for stream (re)fixes. set_bounds returns an error. - - * camel-stream.[ch]: Remove exceptions. Make flush and reset return - an error code, repair all the screwed up formatting, and put back - close. - - * camel-mime-part-utils.c - (camel_mime_part_construct_content_from_parser): And here. - - * camel-mime-part.c (camel_mime_part_set_content): And this too. - (write_to_stream): Fixed for stream changes. - - * camel.h: Fixed. - - * providers/vee/camel-vee-folder.c (vee_search_by_expression): - Implement. Performs an intersection of the two searches. - (camel_vee_folder_finalise): Unref search folders. - (vee_append_message): Implement append. - -2000-05-18 Dan Winship - - * camel-folder.c: remove message_number_capability and require uid - capatibility. - (camel_folder_list_subfolders, camel_folder_get_uid_list, - camel_folder_get_subfolder_info, camel_folder_get_message_info): - removed - (camel_folder_get_subfolder_names, - camel_folder_free_subfolder_names): new subfolder interfaces. - (camel_folder_get_uids, camel_folder_free_uids): new uid - interfaces - (camel_folder_get_summary, camel_folder_free_summary): new summary - interfaces - - * providers/mbox/camel-mbox-folder.c, - * providers/nntp/camel-nntp-folder.c: - * providers/vee/camel-vee-folder.c: Update for changes - - * providers/pop3/camel-pop3-folder.c: Implement get_uids, update - for other changes. - -2000-05-18 NotZed - - * providers/vee/camel-vee-folder.c: Guess! - - * camel-folder-search.c (search_user_flag): Implement user_flag - search term. - - * camel-folder-search.h: Added user_flag search capability - (user-flag "blah") - - * providers/mbox/camel-mbox-folder.c (mbox_init): Set USER flag in - permanent flags for the folder. - -2000-05-17 Dan Winship - - * camel-folder.c: Remove unused async open/close and - copy_message_to functions. - Rename functions without initial _. Fix glib preconditions and - gtk-doc comments. - -2000-05-17 Dan Winship - - * camel-data-wrapper.c: remove get/set_output_stream operations. - They're redundant with write_to_stream, and CamelMimePart and - CamelMimeMessage only implement the latter, meaning that trying to - get_output_stream on a CamelMimeMessage that was built from pieces - rather than being parsed from a stream doesn't work. Anything that - uses get_output_stream can be rewritten to use write_to_stream, so - we'll standardize on that. - (camel_data_wrapper_new): remove this: CamelDataWrapper is - supposed to be an abstract class. - (write_to_stream): remove default implementation. (Moved to - CamelSimpleDataWrapper) - - * camel-simple-data-wrapper.c: resurrect, although it's not really - the same thing it was before. A simple data wrapper, which is - backed by a CamelStream. - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): Use - construct_from_stream rather than set_output_stream. - (camel_mime_part_construct_content_from_parser): Change - camel_data_wrapper_new to camel_simple_data_wrapper_new. - - * camel-mime-part.c (camel_mime_part_set_content): Change - camel_data_wrapper_new to camel_simple_data_wrapper_new. - -2000-05-17 Darin Adler - - * camel-folder-summary.c: (message_info_load): - Quick fix to get it to compile. I hope I don't get into trouble. - -2000-05-17 Dan Winship - - * camel.h: Don't include the no-longer-distributed - possibly-to-be-removed headers. - - * providers/smtp/camel-smtp-transport.c - (smtp_get_email_addr_from_text): fix an off-by-one error in - address parsing - (smtp_data): use camel_data_wrapper_get_output_stream rather than - data_wrapper->output_stream - -2000-05-17 NotZed - - * providers/mbox/camel-mbox-folder.c (message_changed): Snoop - changes to user flags on the message into the summary as well. - - * providers/mbox/camel-mbox-summary.c (camel_mbox_summary_init): - Changed version init to include the parent class version info - (i.e. add it not overwrite it). - - * camel-folder-summary.c (message_info_new): Initialise user_flags - to empty. - (message_info_load): And load user flags. - (message_info_save): And save user flags. - (message_info_free): And free them. - (CAMEL_FOLDER_SUMMARY_VERSION): Bumped file revision. - - * camel-folder-summary.h: Added user-flags to summary. - - * camel-mime-message.c (camel_mime_message_set_user_flag): Dont - use a hashtable for user flags. - (camel_mime_message_get_user_flag): And changed here too. - (camel_flag_get): New interface to get a flag from a flag - list. Flag lists are easier to work with than hash tables, and - save memory too. - (camel_flag_set): And set. - (camel_flag_list_free): And free. - (free_key_only): Discard. - (finalize): Remove the flag list. - -2000-05-17 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c: (smtp_helo): Error - checking on gethostbyaddr() eliminating a possible segfault. - -2000-05-16 NotZed - - * providers/mbox/camel-mbox-folder.c (mbox_delete_message_by_uid): - Implement. - -2000-05-12 NotZed - - * camel-movemail.c (camel_movemail): Open the destination with - O_APPEND, so we dont blow away a partially transferred mbox. - (camel_movemail): Loop if we get errno=INTR, and not fail. - -2000-05-11 NotZed - - * providers/mbox/camel-mbox-summary.c (summary_rebuild): Update - the summarised file size, if everything went ok. - (camel_mbox_summary_expunge): Clear header flags after updating. - -2000-05-16 Chris Toshok - - * providers/nntp/camel-nntp-folder.c: - * providers/nntp/camel-nntp-folder.h: - * providers/nntp/camel-nntp-provider.c: - * providers/nntp/camel-nntp-store.c: - * providers/nntp/camel-nntp-utils.c: - * providers/nntp/camel-nntp-utils.h: - get things working with new camel summary stuff. - - * providers/nntp/camel-nntp-summary.c: - * providers/nntp/camel-nntp-summary.h: - removed files since camel-folder-summary does all we need. - -2000-05-15 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c: Added some preliminary - AUTH support. - -2000-05-15 Dan Winship - - * camel-folder.h: Remove camel_folder_get_summary, which no longer - exists. - -2000-05-11 Dan Winship - - * Makefile.am: remove some cruft that we're not currently using. - - * camel-stream-mem.c (camel_stream_mem_new_with_buffer): Change - to match prototype (size_t vs unsigned int) so it works on 64-bit - machines. Noted by msw. - -2000-05-11 NotZed - - * providers/mbox/camel-mbox-folder.c (message_changed): Indicate - the summary changed also. - -2000-05-11 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c: (smtp_helo): - Updated to more closely comply with RFC 821 standards - -2000-05-11 NotZed - - * camel-mime-part.c (write_to_stream): Unref the filter after - adding it to the filtering stream. - - * providers/mbox/camel-mbox-summary.c - (camel_mbox_summary_finalise): Free the folder path. - (camel_mbox_summary_update): Also save summary when done. - (camel_mbox_summary_expunge): Unindex items when deleting them. - (camel_mbox_summary_expunge): Save the index as well as the - summary. - - * camel-folder-summary.c (camel_folder_summary_finalise): Free the - summary path. - (camel_folder_summary_touch): New function, indicate the summary - info changed. - (camel_folder_summary_remove): Dirty here. - - * camel-internet-address.c (internet_decode): Free multiple entry - addresses properly. - - * camel-mime-utils.c (header_decode_mailbox): Plugged another - memleak, free text after converting it. - (header_decode_addrspec): More leaks plugged. - - * camel-mime-message.c (finalize): Free message_uid. - (finalize): Free the recipients hashtable. - -2000-05-11 NotZed - - * camel-folder-summary.c (camel_folder_summary_finalise): Free - summary items and charset filters. - -2000-05-10 NotZed - - * camel-folder-summary.c (camel_folder_summary_finalise): Don't - free stuff in p, after we've free'd p. - - * providers/mbox/camel-mbox-folder.c (mbox_append_message): Unref - the stream we created for appending. - -2000-05-10 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c: (camel_smtp_transport_class_init): - Added initialization for service_class - -2000-05-10 Dan Winship - - * camel-multipart.c (write_to_stream): fix a stupid typo. Thank - you, C. - - * camel-mime-part.c (write_to_stream): don't ref the stream before - wrapper a filter around it, since nothing will ever unref it. - -2000-05-10 Christopher James Lahey - - * Makefile.am: Added camel-types.h, camel-folder-pt-proxy.h, and - camel-thread-proxy.h. - -2000-05-09 Dan Winship - - * providers/sendmail/camel-sendmail-transport.c (_send_internal): - Bleah. Can't fsync a pipe. As a quick kludge, just don't - stream_flush it. The right fix will require bringing back - stream_close though. - -2000-05-09 Jeffrey Stedfast - * camel-internet-address.[c,h]: Undid my changes (moved - struct _address back into came-internet-address.c) - * providers/smtp/camel-smtp-transport.c: (_send): changed - from using it's own address manipulation (using struct _address) - to using camel_internet_address_get(). Also some format changes - to keep consistant with the rest of Camel - -2000-05-09 Jeffrey Stedfast - - * camel-internet-address.[c,h]: Moved struct _address from - camel-internet-address.c to camel-internet-address.h - (hopefully this doesn't break anything...) - * providers/smtp/camel-smtp-transport.c: (_send): now - populates the recipient list with To, Cc, and Bcc addresses. - Should now be able to use this module. - -2000-05-09 Dan Winship - - * providers/mbox/camel-mbox-folder.c (mbox_get_message_by_uid): - one more refcounting fix I missed before. - -2000-05-08 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c: no longer frees memory it - shouldn't, updated to reflect camel-stream changes involving - CamelException (perhaps it should use a different CamelException - variable than is passed to the camel smtp module?) - -2000-05-08 Dan Winship - - * camel-stream.c (camel_stream_read, camel_stream_write, - camel_stream_flush, camel_stream_reset, camel_stream_printf, - camel_stream_write_to_stream): Use CamelException to signal - failure. - (camel_stream_write_strings): Remove. camel_stream_printf is more - useful in most of the places that used this. - (camel_stream_write_string): Change from macro to function to - prevent problems with double-evaluation. - - * camel-seekable-stream.c (camel_seekable_stream_seek, - camel_seekable_stream_set_bounds): Use CamelException. - (reset): Update. - - * camel-seekable-substream.c, camel-stream-buffer.c, - camel-stream-filter.c, camel-stream-fs.c, camel-stream-mem.c: - Update. - - * camel-stream-fs.c: Remove the virtual init functions and move - the code into the creator functions. Add CamelExceptions to - creation functions that could fail. - - * camel-data-wrapper.c (camel_data_wrapper_write_to_stream): Use - CamelException. - * camel-mime-message.c, camel-mime-part.c, camel-multipart.c - (write_to_stream): Update. - - * camel-mime-parser.c: add an exception to the mime parser private - data and pass that to stream functions as needed. - - * gmime-content-field.c, md5-utils.c: Update (badly) for stream - changes. - - * camel-exception.h (camel_exception_is_set): convenience macro. - - * providers/Makefile.am: disable SMTP for now - - * providers/mbox/camel-mbox-folder.c (mbox_append_message): Pass - CamelException to the functions that now need it. Check the - exception after calling camel_stream_flush, and fail if it fails. - (mbox_get_message_by_uid): More updates. - - * providers/pop/camel-pop3-folder.c, - providers/pop/camel-pop3-store.c, - providers/sendmail/camel-sendmail/transport.c: Update. - - -2000-05-08 NotZed - - * camel-mime-message.c (process_header): Format From and Reply-To - to at least a decoded string. Should probably store them as an - camelinternetaddress. - - * Merged NEW_SUMMARY branch back to trunk, and resolved conflicts. - - * providers/mbox/camel-mbox-summary.c (camel_mbox_summary_update): - Return status. - (camel_mbox_summary_expunge): Force an update of the summary - before we do anything. - (camel_mbox_summary_expunge): Build new xev line in xevnew, and - free that, and consify xev. - (camel_mbox_summary_load): If we are rebuilding from scratch, make - sure we clear the summary content. - - * camel-stream-filter.c (do_close): We NEED a stream close. - -2000-05-07 Dan Winship - - Make camel not leak like a sieve. - - * camel-object.c: New subclass of GtkObject which is now the base - of the Camel object hierarchy. Currently the only difference - between CamelObject and GtkObject is that CamelObjects don't start - out floating. - - * *.h: Move a bunch of typedefs to camel-types.h. Standardize on - using in header files rather than , "foo.h", - or "camel/foo.h". Remove some unneeded includes. - - * camel-address.c, camel-data-wrapper.c, camel-folder-search.c, - camel-folder-summary.c, camel-folder.c, camel-mime-filter.c, - camel-mime-parser.c, camel-service.c, camel-session.c, - camel-stream.c: These are now subclasses of CamelObject. - - * camel-data-wrapper.c (set_output_stream): - * camel-medium.c (set_content_object): - * camel-seekable-substream.c - (init_with_seekable_stream_and_bounds): - * providers/mbox/camel-mbox-folder.c (mbox_get_message_by_uid): - remove gtk_object_sink calls. - - * camel-stream-buffer.c (init_vbuf): - * camel-stream-filter.c (camel_stream_filter_new_with_stream): - ref the original stream. - - * camel-folder-summary.c (camel_folder_summary_finalise): unref - the filters when finalizing. - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser, - camel_mime_part_construct_content_from_parser): - * camel-mime-part.c (camel_mime_part_set_content): Unref objects - that are created only to be handed off to other objects. If - they're going to be needed later, they will have been additionally - ref'ed by the object that needs them. - - * providers/pop3/camel-pop3-folder.c (get_message_by_number): - unref the message stream after creating the data from it. - - * camel-stream.c, camel-stream-buffer.c, camel-stream-filter.c, - camel-stream-fs.c, camel-stream-mem.c: Remove camel_stream_close, - since its semantics are dubious (what happens when you close a - stream other people still have references on?). - - * providers/nntp/camel-nntp-store.c: - * providers/smtp/camel-smtp-transport.c: - * providers/pop3/camel-pop3-store.c: - replace camel_stream_close calls with gtk_object_unref. - - * providers/mbox/camel-mbox-folder.c: - * providers/nntp/camel-nntp-folder.c: - * providers/sendmail/camel-sendmail-transport.c: - replace camel_stream_close with camel_stream_flush + - gtk_object_unref - -2000-05-06 Dan Winship - - * providers/pop3/camel-pop3-store.c (query_auth_types): A machine - which serves neither POP nor KPOP is not a POP server. - - * providers/smtp/camel-smtp-provider.c: Note in the description - that this provider is not yet tested. - -2000-05-08 NotZed - - * camel-mime-part.c (write_to_stream): Free the filter stream when - done. - - * camel-mime-parser.c (folder_seek): Make sure we add the \n - terminal when we seek as well (frob!). - - * camel-mime-utils.c (header_decode_addrspec): Plug minor memleak. - - * camel-mime-part.c (finalize): Free header tables once finished. - - * camel-folder-summary.c (camel_folder_summary_remove): Dont try - to access info after its free'd. - -2000-05-07 NotZed - - * camel-mime-part.c (write_to_stream): Apply encoding to content - part, when writing to a stream *sigh*. - - * camel-stream-filter.c (do_write): implement write for the - filtering stream. Writes shouldn't be mixed with reads. - (do_flush): Implemented flush. Again write/flush shouldn't be - mixed with reads. Only flushes if the last op was write. - (do_close): Force flush on close. - - * camel-mime-filter.c (filter_run): Oops, make sure we include the - backlen in the total length before passing onto the filter. - - * camel-mime-filter-from.c: New filter, munges 'From ' lines into - '>From ', for mbox. - - * camel-mime-parser.c (camel_mime_parser_header_remove): New - function to remove the parser's raw header, rather than - manipulating the header directly (wich doesn't work with - mempools). - - * camel-mime-utils.c (header_address_list_clear): Fixed some - broken(tm) logic, which would leak entries on multivalued lists. - - * providers/mbox/camel-mbox-summary.c (camel_mbox_summary_load): - Use ibex_save() to save the ibex. Makes a big difference to - startup times for very large mailboxes. - (camel_mbox_summary_expunge): Dum de dum, reimplemented. Designed - to be much more robust, and to stop immediately if anything awry - happens. - (copy_block): Utility function to copy n bytes from one fd to - another. - (header_write): Utility function to write out raw headers to an - fd. - (camel_mbox_summary_update): Incremental summary updater. - - * providers/mbox/camel-mbox-folder.c (mbox_get_message_by_uid): - Dont unref the stream, because of the broken(tm) ref model of gtk - widget that for some odd reason is being perpetuated in camel. - (mbox_expunge): Reenable expunge again. - (mbox_append_message): Removed the optimised mbox append. If its - an issue, it can go back later. Cleaned up a lot, checks error - returns, and automagically translates 'From ' into '>From' as - necessary. - -2000-05-07 NotZed - - * camel-mime-filter.c (filter_run): Oops, forgot to add the - backlen to the pre-buffer (*poof*). - -2000-05-07 NotZed - - * camel-mime-message.c (construct_from_parser): Allow - HSCAN_FROM_END to terminate the processing of a message. - - * camel-folder-summary.c (perform_content_info_load): Ick, dont - try and append a node onto its own list. - (camel_folder_summary_clear): Actually clear the indexes after - we've removed the messages. - (camel_folder_summary_clear): Set dirty if it changes. - (camel_folder_summary_load): Clear dirty. - (camel_folder_summary_save): Only save if dirty. - - * providers/mbox/camel-mbox-summary.c (summary_header_load): Oops, - remember to call that parent class first ... - (summary_header_save): Here too. - (camel_mbox_summary_load): Do more checking to verify the index - contents as well as teh summary contents, against the mbox - contents. - (camel_mbox_summary_load): Removed some fo that checking, it needs - more code to work reliably. - -2000-05-07 NotZed - - * providers/mbox/camel-mbox-summary.c (camel_mbox_summary_load): - Set the size and mtime of the mbox we indexed once done. - - * camel-folder-summary.c (camel_folder_summary_set_index): Dont - write the index if it changes - let the claler fix it (uh, kind of - impacts performance). - (camel_folder_summary_load): close in. - - * camel-folder-summary.c (summary_format_string): Check header - exists before trying to strip its leading spaces. - -2000-05-06 NotZed - - * camel-folder.h: Removed summary info from here, and include - camel-folder-summary.h as well. - - * camel-mime-parser.c (camel_mime_parser_step): Allow it to accept - a NULL databuffer. - - * providers/mbox/camel-mbox-summary.c: Totally new file, now - subclasses camel-folder-summary. - - * camel-folder-summary.c (message_info_load): Load the uid as a - string. - (message_info_save): And save too. - (camel_folder_summary_clear): New function, clears the contents of - the summary. - - * providers/mbox/camel-mbox-folder.c: Fixes for summary changes. - (mbox_get_message_by_uid): Completely redone. Now cross-checks - the summary information to make sure we get a real message. - (mbox_append_message): Disabled the copy version of append for - now. - (mbox_expunge): Temporarily disabled the expunge function, until - it is put back in camel-mbox-summary.c - -2000-05-05 NotZed - - * camel-folder-summary.c: And same here ... - (camel_folder_summary_encode_fixed_int32): Ugh, fwrite doesn't - return -1 on error .. - (camel_folder_summary_decode_fixed_int32): Neither deos fread. - (camel_folder_summary_encode_token): Fix here too. - (summary_build_content_info): Use start-headers to get the pos of - the message, not parser_tell(), which might not be what we - expected because of parser_unstep(). - (camel_folder_summary_encode_token): Use bserch() to tokenise the - values, rather than a linear search. - - * camel-mime-utils.c: Defined out some memory profiling stuff I - left there by mistake. - (header_decode_mailbox): Dont try to append the word part of a - local address if we ran out of words. - - * camel-mime-parser.c (folder_scan_content): Apply the fix from - the header scanner to here too. - (folder_scan_header): Only check for end of header if we have - space for it (didn't end the read with a newline) - (folder_scan_header): inptr is the only real thing we need - registerised for performance. Try to help the compiler be smart - about it .. - (folder_scan_header): Simplified the save header case a tad. - - Commented out some memory profiling stuff. - -2000-05-05 NotZed - - * camel-mime-utils.c (header_decode_mailbox): Plug a memory leak. - (header_decode_text): Fixed memory leaks with g_string_append(). - (header_encode_string): And here too, and a few other places. The - glib api is so awful ... - (header_content_type_decode): More memory leaks. - -2000-05-05 NotZed - - * camel-mime-parser.c (folder_scan_init_with_fd): Make sure we - init the end of buffer sentinal! - (folder_scan_init_with_stream): And here too ... - -2000-05-04 NotZed - - * providers/mbox/camel-mbox-folder.c (summary_get_message_info): - Maxcount is minimum of the max and the requested count, not the - maximum :) - - * camel-mime-parser.c (folder_scan_content): Properly set midline, - so we dont falsely catch offset boundary markers (i.e. From inside - content). - (folder_read): Set a sentinal on the end of the read data (\n) so - we dont have to check the buffer boundary in the inner loop. - (mempool_*): New experimental memory management routines, speed - up simple structure parsing by about 25% ... not compiled in by - default. Something similar may be needed for camel-mime-utils to - address performance issues with g_malloc and friends. - - * camel-mime-utils.c: Added a macro w(x) used to wrap all warnings - about mime/rfc violations, so they can be turned off. - - * camel-folder-summary.c (summary_build_content_info): Step after - the end of a message ... - Turn into a stand-alone program for testing and profiling. - -2000-05-04 Dan Winship - - * providers/pop3/camel-pop3-store.c (pop3_connect): Don't fall - back to plaintext passwords if APOP fails, since it should also - fail. - -2000-05-04 Dan Winship - - * camel-session.c (camel_session_list_providers): New function to - replace camel_provider_scan. Returns a list of either (a) all - currently-loaded providers, or (b) all available providers. - - * camel-url.[ch]: Add an "empty" flag to CamelURL (indicating that - it contains only a protocol). - - * camel-service.c (camel_service_query_auth_types): Make this take - a CamelException (since it may have to try to connect to the - server, and it might not able to.) - - * providers/pop3/camel-pop3-store.c: add KPOP (Kerberized POP) - support. This is mostly so I have two kinds of authmech to play - with instead of just one. (But it does actually work.) - - * providers/smtp/camel-smtp-transport.c (query_auth_types): update - for prototype change, but disable the functionality, since it - doesn't really support any auth types yet. - (camel_smtp_transport_get_type): add an object init function to - set the service url_flags. - -2000-05-04 NotZed - - * providers/mbox/camel-mbox-summary.c: Yes, and anotherone. - - * camel-mime-utils.c: And another one. - - * camel-mime-part.c: And another one. - - * camel-mime-part-utils.c: And another one. - - * camel-folder-search.c: And another one. - - * camel-mime-parser.c: Reverted a change wihtout a ChangeLog entry. - -2000-05-04 NotZed - - * camel-folder-summary.[hc]: Yes, CamelFolderSummary is back ... - ... re-usable class to summarise and index any stream or message - and to manage/load/save the created summaries. - - * camel-folder.c: Include string.h to kill a warning. - -2000-05-03 Jason Leach - - * Makefile.am (INCLUDES): add $(UNICODE_CFLAGS) to the INCLUDES, - people who installed libunicde in non-standard include paths need - this. - -2000-05-03 NotZed - - * camel-folder.h: Added pos/bodypos/endpos to the basic message - content info object. Size to be removed? Moved the - messageconentinfo and messageinfo back to camel-folder-summary.h. - - * camel-mime-filter-index.c (camel_mime_filter_index_set_ibex): - New function to (re)set the index to use on a filter. - - * camel-mime-parser.c (camel_mime_parser_scan_from): Whole bunch - of inline docs. - (camel_mime_parser_drop_step): New function to drop a state from - the parser. Needs more testing. - - * camel-mime-utils.c (rfc2047_decode_word): If the iconv handle is - -1, then dont try and convert (crashes unicode_iconv?). - (rfc2047_decode_word): Use alloca for variables instead of - g_malloc - by the rfc they should always be short. - (rfc2047_decode_word): If we can't do the charset conversion, undo - the quoted-printable/base64 at least? Should probably convert - unknown characters to the utf-8 unknown character. - -2000-05-02 Larry Ewing - - * camel-mime-utils.c (header_decode_date): fix typo when - dereferencing saveoffset. - -2000-05-02 NotZed - - * camel-folder-search.c: Added some header doco. - - * camel.h: REmove gmime-utils.h from here. - - * providers/mbox/camel-mbox-search.[ch]: Removed. Functionally - redundant. - - * providers/mbox/camel-mbox-folder.c (mbox_search_by_expression): - Use the new CamelFolderSearch class to do the actual searching, - just setup the search here. - - * camel-folder-search.[ch]: A helper class that providers may - subclass to provide their own search functionality, or they can - simply use as is, it supports body searches if an ibex is - supplied, and header searches if a summary is supplied. - -2000-05-02 Matt Loper - - * Makefile.am: set G_LOG_DOMAIN. - * providers/MH/Makefile.am: same. - * providers/maildir/Makefile.am: same. - * providers/mbox/Makefile.am: same. - * providers/nntp/Makefile.am: same. - * providers/pop3/Makefile.am: same. - * providers/sendmail/Makefile.am: same. - * providers/smtp/Makefile.am: same. - -2000-05-02 NotZed - - * providers/mbox/camel-mbox-search.c - (camel_mbox_folder_search_by_expression): Dont store/remove - current search from the search list. - - * providers/mbox/camel-mbox-folder.h: Removed searches list, - searches are all sync now. - - * gmime-utils.[ch]: What the hell, remove it. This will break the - nntp provider. The mime parser can be used instead though. - Removed from all code including it (but none were using it). - - * gmime-utils.c (_store_header_pair_from_string): Removed bizarre - string_dichotomy version of this. This code is somewhat redundant - now, and is headed for death anyway. - - * gstring-util.c (g_string_dichotomy): Same with this one. - (g_string_clone): Removed a memory leak, g_string_new() allocates - its own memory. - (g_string_append_g_string): Allow to append an empty gstring onto - another gstring, dont abort()! - - * string-utils.c (string_dichotomy): Removed this incredibly weird - function. - - * camel-folder.c (_create): Replaced the rather obtuse use of - "string_dichotomy" function with a simple strrchr(). Still not - sure it'll work. - - * camel-folder-summary.c: cvs removed a long-removed file. - - * camel-mime-parser.c (folder_scan_header): Fix the previous - overflow problem properly (can happen in 2 places). - (header_append): A new macro to include the code changed above, so - it only appears in one place. - (folder_scan_step): Change the content type to text/plain if the - multipart is broken. Doesn't actually change the header though. - (header_append): Also move the header-start tracking stuff here. - Could be a static function to save code. - -2000-05-02 NotZed - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): Dont use autofill on - these fucking long function anmes!!!!!! - -2000-05-02 NotZed - - * providers/mbox/camel-mbox-summary.c - (camel_mbox_summary_expunge): Fix the offset for the summary when - an item is expunged to take account of the From line. - -2000-05-01 NotZed - - * providers/mbox/camel-mbox-folder.h (CamelMboxFolder): Removed - search_id. - - * providers/mbox/camel-mbox-search.c - (camel_mbox_folder_search_cancel): Remove.d - (camel_mbox_folder_search_complete): Removed. - (camel_mbox_folder_search_by_expression): Changed back to sync - api. - (struct _searchcontext): Removed cancelled flag. - (find_context): Removed. - (func_header_contains): Debug out some search stuff. - - * providers/mbox/camel-mbox-search.h - (camel_mbox_folder_search_by_expression): Moved back to sync api. - - * providers/mbox/camel-mbox-summary.c - (camel_mbox_summary_set_flags_by_uid): New function to update the - flags in the summary. - (camel_mbox_summary_expunge): Expunge messages from a folder. - (offset_content): Re-align offsets of summary when messages - added/removed to an existing summary. - (camel_mbox_summary_remove_uid): Remove a message summary entry by - uid. - (index_folder): Restore flags from X-Evolution header, if they are set. - (index_folder): Make sure we index using a decimal uid, since - thats what everything else indexes off (oops). - Upped SUMMARY_VERSION as a result. - (camel_mbox_summary_expunge): Oops, my wrong, use the string uid - to unindex on. - - * providers/mbox/camel-mbox-folder.c (_get_message_by_uid): - Connect to the message_changed signal. - (_init): Set permanent flags to something reasonable. No user - flags yet ... - (message_changed): If the flags of the message change, update the - flags in the summary. - (mbox_expunge): Implement the expunge. - (camel_mbox_folder_class_init): Renamed all leading _'s to mbox_'s - (mbox_expunge): Emit a folder_changed signal on expunge (uh, even - if it didn't ...) - - * camel-folder.c (_finalize): Uh, dont free permanent_flags - anymore (this wouldn't failed anyway, it was a GList !!!) - (camel_folder_search_complete): Removed. - (camel_folder_search_cancel): Removed. - (camel_folder_expunge): Changed to only allow expunge on an open - folder. It doesn't make sense for mbox, otherwise (?) - (camel_folder_class_init): Added a folder_changed signal. - - * camel-folder.h (struct _CamelFolder): Change permanent_flags to - a bitfield. - (list_permanent_flags): Renamed to get_permanent_flags, and - returns a bitfield. - (camel_folder_expunge): Changed expunge to a void type. The - messages would no longer be useful after they have been removed - ... - (CamelFolderClass): New function summary_get_by_uid() to get a single - summary. - (*search*): Moved back to synchronous search api ... *sigh* - - * camel-folder.h: Removed CamelSearchFunc. - - * camel-mime-message.c (set_flag): Removed. - (camel_mime_message_set_flag): Removed. - (get_flag): Removed. - (camel_mime_message_get_flag): Removed. - (add_flag_to_list): Removed. - (get_flag_list): Removed. - (camel_mime_message_get_flag_list): Removed. - (camel_mime_message_get_flags): New interface to get system flags. - (camel_mime_message_set_flags): " to set ". - (camel_mime_message_get_user_flag): To get a user flag. - (camel_mime_message_set_user_flag): To set a user flag. - (finalize): Hmm, the old one free'd the key and data, not good - when the data is a boolean ... - -2000-04-30 Dan Winship - - * camel-provider.h: Tweak the definition of CamelProvider. Among - other things, a provider may now be both a store and a transport. - - * camel-provider.c: Remove a lot of code we had no intention of - using. This now only contains two functions: camel_provider_init - to read the installed .urls files, and camel_provider_load to - load and register a new provider. - - * camel-session.c: Remove more unused code and simplify some of - the remaining code. The list of available provider modules is now - stored in the session, and it handles calling camel_provider_load - to load them as needed. Provider registration is now done by - calling back from the module init routine, which allows a single - module to register providers for multiple URL types. - - * providers/*: Update provider structures and init routines for - the new stuff. Add a .urls file to each provider specifying what - urls it handles, and install that with the library. - - * providers/nntp/camel-nntp-provider.c: Add hints towards - supporting both news: and nntp: URLs, and using nntp as both a - store and a transport. - -2000-04-29 Dan Winship - - * camel-internet-address.c (camel_internet_address_get): const - poison - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): - camel_mime_parser_tell() returns an offset from where it started - parsing, not necessarily from the start of data. Since we're - parsing a bounded seekable_stream, we need to add the stream's - starting bound to camel_mime_parser_tell's return value to - create the substream in the right place. - - * camel-seekable-substream.c - (camel_seekable_substream_new_with_seekable_stream_and_bounds): - say CAMEL_STREAM_UNBOUND rather than -1 in doc. - - * camel-seekable-stream.c (camel_seekable_stream_seek): Add more - info to docs. - -2000-04-28 Dan Winship - - * camel-mime-parser.c (folder_scan_header): fix a bug that would - cause corruption with very long headers. - -2000-04-27 Ettore Perazzoli - - * providers/pop3/Makefile.am (INCLUDES): Add `-I$(srcdir)/../../..' - to pick the Camel includes. - * providers/sendmail/Makefile.am (INCLUDES): Likewise. - - * camel.h: Don't #include anymore. - -2000-04-27 NotZed - - * camel-mime-utils.c (check_header): Dont try and check a NULL - header. - - * camel-recipient.[ch]: Dead. Its not pining. - - * camel-mime-message.h: Dont include recipients.h anymore. - - * camel-mime-message.c (camel_mime_message_add_recipient): Accept - name/address separately, and store in an CamelInternetAddress. - (add_recipient): Removed. - (remove_recipient): Removed. - (remove_recipient_address): Renamed from remove_receipient, works - via address. - (camel_mime_message_remove_recipient_name): New function to remove - by name. - (get_recipients): Removed. - (camel_mime_message_get_recipients): Return a camel-internet-address. - (write_to_stream): No longer write receipients directly. - (write_recipients_to_stream): Removed. - (write_one_recipient_to_stream): Removed. - (camel_mime_message_init): Setup recipients hashtable, rather than - usign the recipients stuff. - (set_recipient_list_from_string): Killed, a violent and lengthy - death. - (process_header): Simplified recipient handling code a lot. - (received_date_str, sent_date_str, reply_to_str, subject_str, - from_str): Removed some oddly-defined global statics. - (camel_mime_message_class_init): Dont initialise above variables - anymore. - (init_header_name_table): Removed, use a table to init this, and - do it in class init (2 lines of code ...). - - * camel-news-address.c: Class to represent news addresses - - currently empty, and not built. - - * camel-internet-address.h: Class to represent internet (email) - addresses. - - * camel-address.h: Abstract class to represent (lists of) - addresses. - -2000-04-27 Dan Winship - - * camel-mime-part.c (write_to_stream): Revert previous change. I - was confused. - - * camel-url.[ch] (camel_url_encode, camel_url_decode): expose - these routines. - -2000-04-26 Dan Winship - - * camel-mime-part.c (write_to_stream): Only write a newline - between the headers and the content object if the content object - is not a CamelMedium. (If the content is a medium, it may have its - own headers, which then need to go before the blank line.) - - * camel-mime-body-part.[ch]: Remove. We weren't using the fields - that made this different from camel-mime-part, so it basically - just forced us to do lots of gratuitous typecasting. - - * camel-multipart.[ch]: Use CamelMimePart. Remove the multipart - parent stuff, since we weren't using that either. - - * etc: update for CamelMimeBodyPart -> CamelMimePart - -2000-04-26 Dan Winship - - * camel-medium.c (set_content_object): sink the content object - after referencing it. - - * camel-mime-part.c: fix various little things in the handling - of CamelMedium methods. Change camel_mime_part_set_text to the - more generic camel_mime_part_set_content. - - * camel.h: sync to current reality - - * camel-folder-utils.[ch]: removed - - * camel-mime-utils.c (header_format_date): fix format specifier - for time zone. Fix typo in month names array. - -2000-04-26 NotZed - - * camel-seekable-substream.c (stream_seek): Changed to have - absolute seek semantics, not relative to the bounds. - - * camel-seekable-stream.c (reset): When we reset, seek to the - start of the bound, if there is one. - (stream_tell): Make tell virtual. - - * camel-stream-filter.c (do_available): Removed. - - * camel-stream-buffer.c: Remove leading _'s from static functions. - (stream_read): Renamed from read(). Fancy that conflicting! (my - boo!) Others too. - - * providers/pop3/camel-pop3-folder.c (get_message_by_number): - Changed to stream_mem interface. - - * providers/mbox/camel-mbox-folder.c (_get_message_by_uid): Fixed - for streamfs interface changes, and implement a failure case. - (_append_message): Changed for fs stream interface change. - - * camel-multipart.c (print_part): Iterate rahter than callback. I - hate glists's interface (hence, move this to write_to_stream). - (write_to_stream): Return an error (yuck, this is a royal PITA to - do with the stream write interface). - - * camel-mime-message.c: Removed leading _ from static names. - - * camel-mime-part.h: construct_from_parser() now returns an error - code. - - * camel-mime-part-utils.c - (camel_mime_part_construct_content_from_parser): Changed to use a - camel-data-wrapper instead of a camel-simple-data-wrapper (no - change needed elsewhere?). - (simple_data_wrapper_construct_from_parser): Fixes for stream-mem - interface changes. - - * camel-simple-data-wrapper.[ch], - camel-simple-data-wrapper-stream.[ch], - camel-stream-data-wrapper.[ch], removed. Fixed including of these - files. - - * camel-mime-part.c (camel_mime_part_set_text): Remove the use of - the camel-simple-data-wrapper-stream, just use a mem stream. - (write_to_stream): Renamed from my_* - (construct_from_stream): Return an error on error. - - * camel-stream-mem.c (camel_stream_mem_new*): Remove mode - parameter. - - * camel-stream-mem.h (enum CamelStreamMemMode): Removed. It - wasn't used at all. - - * camel-data-wrapper.h: Add camel_data_wrapper_new() to create - these. - (write_to_stream, construct_from_stream): Return an error - indicator for success. Fixed all methods to match (ICK). - - * Makefile.am (libcamel_la_SOURCES): Remove - camel-simple-data-wrapper.c, camel-simple-data-wrapper-stream.c, - camel-stream-data-wrapper.c. Obsoleted by code re-use! - - * camel-data-wrapper.c (construct_from_stream): Change the default - implementation to just set the output stream == construction - stream. Well, this lets me get rid of both simple-data-wrapper - and stream-data-wrapper (unused anyway), and - simple-data-wrapper-stream in one hit. CamelDataWrapper is now - also a concrete class. - (write_to_stream): Use camel_stream_write_to_stream() to - calculate/return values (and save code). - Include for obvious reasons. - - * camel-stream.c (eos): Provide a default implementation of .eos(). - (camel_stream_write_to_stream): Make it return an error code on - error. - (camel_stream_printf): Changed to return the number of bytes - written/error. - (camel_stream_available): Removed. - - * camel-stream-fs.h (enum CamelStreamFsMode): Removed. Changed to - use unix modes and so forth (wasn't used for anything but new file - creation and didn't work well either). - - * camel-stream-fs.c: Removed leading _'s for names. And removed - some virtual method 'documentation'. - (destroy): Dont try and close a closed/error fd. Only report - error if close returns -1. Moved all the code to finalise(), and - killed this function. - (init_with_fd): Properly setup the seek offset, if it is a - valid and seekable file descriptor. - (init_with_fd_and_bounds): Use off_t for bounds, set bounds on the - seekable stream. - (init_with_name): Return error codes. - (init_with_name_and_bounds): Ditto. - (camel_stream_fs_new_with_name): REturn NULL object if it failed. - (camel_stream_fs_new_with_name_and_bounds): Return NULL object on - failure. Changed with_name* api's to take unix open style args - and flags. - (read): The bounded stream bounds checking seemed off, simplified - code a bit. - (write): Implement bounds checking for writing, the comment was - wrong, it could make sense to bound writing. Cleaned up a little. - (available): Gone. - (eos): Removed. Use CamelStream's implementation now. - (close): Reset the fd to -1, provide a warning for bad usage. - (seek): Cleaned up. Changed the behaviour a little, the returned - offset is the absolute position in the file, even in bounded - streams. - (seek): Seek from end mirrors lseek() behaviour (reverse seeking). - -2000-04-25 NotZed - - * camel-stream-fs.h (struct _CamelStreamFs): Moved bounds and eof - indicator to other parent classes. - - * camel-stream.c (camel_stream_printf): New utility - function. Obvious use. - - * camel-stream-mem.c: Removed leading _'s from static func's. - (camel_stream_mem_new_with_byte_array): Fixed for api changes, set - the owner for the byte array to us. - : Removed A bunch of gtk doc stuff for static (implementation) functions. - (available): Removed. - (write): Fixed the write implementation so that seek() works on a - seekable memory stream, as expected. Seeking past the end of the - buffer has unix semantics (filling with 0). - (available): Removed. - (write): Implement seekable stream bounded stream. - (read): Implement seekable stream bounded stream. - (close): Dont free the stream_mem if we're not the owner. - (seek): Allow to seek beyond the end of memory area, - implement bounds checking. - (seek): Set errno on bad policy. - - * camel-stream-mem.h (struct _CamelStreamMem): Changed position to off_t. - (new_with_buffer): Changed len to be a size_t. - (set_buffer, set_byte_array): New interface functions. - (struct _CamelStreamMem): Removed position, it is stored in the - superclass. - - * camel-stream.h: Removed some of the seemingly random - whitespace. Removed the available method (its not - impelemented/useful enough). - - * camel-seekable-substream.c - (init_with_seekable_stream_and_bounds): Remove the data_available - stuff, it hasn't been properly implemented/finished, and may never - work (unfortunately *sigh). - (reemit_parent_signal): Removed part of the above change. - (set_bounds): Removed (moved to seekable-stream). - : Fixed up some of the generally unreadable indenting (sorry, - wrapping at 80 characters with - camels_really_long_function_names() - just_doesnt_work_very_well_does_it(). - (available): Removed. - (stream_seek): Fixup for object changes. Make sure we return -1 - if the parent stream can't seek. - - * camel-seekable-stream.c (ccamel_seekable_stream_set_bounds): New - function to bound any seekable stream. - : Removed _'s. - (camel_seekable_stream_class_init): Implement an init function, to - setup the stream bounds to unbound. - - * camel-seekable-stream.h (CamelSeekableStreamClass): New virtual - method set_bounds for seekable streams. - (CAMEL_STREAM_UNBOUND): New define for no bound. - - * camel-seekable-substream.h (struct _CamelSeekableSubstream): - Removed sup_bound and inf_bound, moved to CamelSeekableStream (and - renamed, and changed to off_t's). - (new_with_seekable_stream_and_bounds): Use off_t as the bounds. - (CamelSeekableSubstreamClass): Uh, why was the intialiser virtual? - Removed. - - * camel-seekable-stream.[ch] (CamelSeekableStreamClass): Changed seek - to accept an off_t as the offset. - (struct _CamelSeekableStream): Renamed cur_pos to position and - changed it to an off_t type. - (enum CamelStreamSeekPolicy): Set to match the SEEK_* constants - from lseek(). - (get_current_position): Renamed to tell(). - - * camel-stream-buffer.h: Commented out set_vbuf - never implemented. - -2000-04-25 Dan Winship - - * camel-stream-buffer.c (_eos): only return TRUE if the parent is - at eos AND the buffer has been exhausted - - * camel-mime-message.c: fix some incorrect macro usage that - resulted in bogus casts - -2000-04-24 Dan Winship - - * camel-mime-part-utils.c - (simple_data_wrapper_construct_from_parser): fix a cut-and-pasto. - - * providers/mbox/camel-mbox-folder.c (_get_message_by_uid): ref - (and sink) the message stream if we're going to unref it later. - Otherwise it could get destroyed while there are still substreams - attached to it. This needs a cleaner solution. - - * camel.h: remove data-wrapper-repository.h include(s) - -2000-04-24 NotZed - - * camel-mime-message.c (construct_from_parser): Allow MESSAGE_END - _or_ EOF as valid termination conditions. - - * providers/mbox/camel-mbox-summary.c (message_struct_new): Decode - and then re-encode the addresses, so they are consistently - formatted. - - * camel-mime-utils.c (header_decode_mailbox): Store the address in - a _header_address. And try to get a comment-stored name if there - is one. - (header_decode_address): Actually return an address. - (header_to_decode): Renamed to header_address_decode() - (header_mailbox_decode): New function to get a single mailbox. - (header_mime_decode): Return the major/minor value, as - appropriate. - (header_address_new, and friends): Whole bunch of utility - functions for working with the address thingies. - (header_decode_domain): Free the string header, and dont expand - '.' into ' . '. - - * camel.c (camel_init): No longer call - data_wrapper_repository_init. - - * camel-medium.c (write_to_stream): Moved (back) to - camel-mime-part. - (add_header): - (set_header): - (remove_header): - (get_header): Make all these abstract, and spit warnings if - called. I guess it could manage the list, but well, it doesn't. - - * camel-medium.h (struct _CamelMedium): Dont store headers here, - the implementor is the only one who knows their format. - (CamelMediumClass): Changed header values to be void *'s. They - need not be strings? - - * camel-simple-data-wrapper.c (construct_from_stream): And we're - back. Set the output stream. - (construct_from_parser): Moved to camel-mime-part-utils. - - * camel-mime-part-utils.c - (camel_mime_part_construct_content_from_parser): Create the - contents of multipart and simple messages. - (camel_mime_part_construct_content_from_parser): Oops, this was - totally screwed up, try creating the right cotnent on the right - object. - - * camel-multipart.c (construct_from_parser): Moved to - camel-mime-part-utils. - (separate_part): Removed. - - * camel-mime-part.c (construct_from_stream): Back again! This now - switches over to using a mime parser for any mime parts, only. - (my_write_to_stream): Write our headers and so forth here. - (add_header): Add header directly, parent class is abstract. - (remove_header): Ditto. - (set_header): Ditto. - - * camel-data-wrapper.c (camel_data_wrapper_construct_from_stream): - Remade abstract. - (camel_data_wrapper_construct_from_parser): Moved to - camel_mime_part. - - * camel-data-wrapper.h: Put back construct_from_stream. - - * camel-mime-part.h: Put construct_from_parser in here, the - data-wrapper shouldn't know about mime. Ok, so now to undo half - of the last hours changes ... duh. - -2000-04-23 Dan Winship - - * camel-mime-utils.c (header_to_decode, header_mime_decode): fix - some obvious minor bugs noted by -Wall. - -2000-04-23 NotZed - - * providers/pop3/camel-pop3-folder.c (get_message_by_number): Use - construct_from_stream instead of set_input_stream(). - - * camel-simple-data-wrapper-stream.c - (camel_simple_data_wrapper_stream_construct): REmoved the destroy - callback code. - (wrapper_destroy_cb): Removed. - - * camel-simple-data-wrapper.h: Add prototype for _construct() - method. - - * camel.c: Include unicode.h to kill a warning. - - * camel-data-wrapper.h (CameldataWrapperClass): Removed - construct_from_stream virtual method. - Removed get/set input stream. - - * data-wrapper-repository.[ch]: Removed&from build. Obsoleted? - The justification as is follows: It is mixing storage - protocol/format with message architecture. It really just doesn't - serve any purpose, as each medium implementor will have to have its - own type->handler mapping, and the only current implementor, - mimepart has a very simple structure and no need for this. - - * camel-medium.c (write_to_stream): Moved here from most of the - stuff in camel-mime-part. Well, the MEDIUM is the one that knows - what the headers are, and the content is, let it write it out. - - * camel-mime-part-utils.c (camel_mime_part_construct_content): - Copied from camel-mime-part.c, removed handling of message - followon state (moved to camel-mime-message). - (camel_mime_part_construct_content_from_parser): Renamed from - construct_content. - (camel_mime_part_construct_headers_from_stream): - (camel_mime_part_construct_content_from_stream): - (camel_mime_part_store_stream_in_buffer): Removed. Replaced by - the new construct from parser stuff. - - * camel-mime-message.c (construct_from_parser): Do - construct_from_parser for mime-message. - (_write_to_stream): Set the mime-version header for medium to - write out, rather than writing it out ourselves. - - * camel-data-wrapper.c (set_mime_type_field): Ref the - content_field when we get it? - (construct_from_stream): Removed. - (camel_data_wrapper_construct_from_stream): Changed to a helper - function, creates a mime_parser, and constructs from that. - (set_input_stream): Removed. - (camel_data_wrapper_set_input_stream): Removed. - (get_input_stream): Removed. - (camel_data_wrapper_get_input_stream): Removed. - - * camel-mime-parser.c (camel_mime_parser_unstep): New function. - Cause a subsequent call to mime_parser_step() to return the same - state over again. - - * providers/mbox/camel-mbox-folder.c (_get_message_by_uid): - Initial test code using the mime parser to construct the message. - (_get_message_by_uid): Use construct_from_stream() instead of - creating our own parser. - - * camel-mime-part.c (construct_from_parser): part constructor. - (camel_mime_part_construct_content): Basically a simpler - replacement for the datawrapper repository. - (camel_mime_part_init): Set the default type to text/plain. - (camel_mime_part_construct_content): Removed to - camel-mime-part-utils.c - (my_get_output_stream): Removed. The streeam is in the - data-wrapper. - (my_get_content_object): Removed. The content object is stored in - the medium. If none is there, the object wasn't created properly. - (my_write_content_to_stream): Removed. The content object is the - one that knows how to write itself out!!!!!!!! - (my_write_to_stream): Remove the base header writing stuff - has - been moved to camel-medium, where it belongs. This can just be - used to check for mandatory headers. - (my_construct_from_stream): Removed. - (my_set_input_stream): What the hell, i'll remove this too. - Nobody seems to understand how it differs from create from stream, - and they both seem to serve the same purpose ... - - * camel-simple-data-wrapper.c (construct_from_parser): Initial - implementation of a content constructor. - (construct_from_stream): Removed! Job taken over by - construct_from_parser. - - * camel-multipart.c (construct_from_parser): Multipart - construction routine. - (camel_multipart_init): Set the default multipart type to - multipart/mixed. Duh, no subtype is not allowed anyway. - (set_input_stream): REmoved. Replaced by construct_from_parser. - -2000-04-22 Dan Winship - - * camel-multipart.[ch]: clean, document, etc. - (camel_multipart_init): pick a prettier default boundary. Still - need to deal with the larger problem - -2000-04-22 NotZed - - * camel-mime-message.h (struct _CamelMimeMessage): Removed - send_date, and received_date, and replaced it with a time_t - 'date' (this is what the header is called), and date_offset to - store the GMT offset of the date. - - * camel-mime-message.c (camel_mime_message_set_from): Update raw - header as we go. - (_set_from): Removed. - (_get_from): Removed. - (camel_mime_message_get_from): Moved implementation here. - (camel_mime_message_get_subject): Move implementation here. - (_get_subject): Nuked. - (camel_mime_message_set_subject): Handle utf-8 input, and also - update raw header when changed. - (_set_subject): Removed. - (_set_received_date): Removed. - (camel_mime_message_set_received_date): Removed. - (_get_received_date): Removed. - (camel_mime_message_get_received_date): Removed. - (_get_sent_date): Removed. - (camel_mime_message_get_sent_date): Removed. - (camel_mime_message_get_date): New function to get the date as a - time_t/offset. - (camel_mime_message_set_date): Set the date as a time_t/offset. - (camel_mime_message_get_date_string): Get the date as a string. - (camel_mime_message_init): Initialise the current date as - 'CMAEL_MESSAGE_DATE_CURRENT'. - (_set_reply_to): Removed. - (camel_mime_message_set_reply_to): Moved implementation here. - This is still broken, reply-to can have multiple addresses. - (_get_reply_to): Removed. - (_set_field): Removed, no longer used anywhere. - (_get_field): Also removed. - (_init_header_name_table): Add the Date header. - (process_header): Also handle snooping of Date header here. - - * camel-stream-filter.c (finalise): Unref the source stream on - finalise, and also call the parent class (oops). - - * camel-mime-parser.c (camel_mime_parser_state): New function to - get the current parser state. - (camel_mime_parser_stream): Allow you to get the stream back from - the mime_parser. - (camel_mime_parser_fd): Alternative to allow you to get the fd - back from the mime_parser. - (folder_scan_init_with_stream): Properly ref/unref the stream. - (folder_scan_close): Properly unref the stream/close the fd on - exit. - (folder_scan_init_with_fd): Close the old fd if there is one. - - * camel-data-wrapper.c (camel_data_wrapper_construct_from_parser): - New method, construct a data wrapper from an initialised parser. - (construct_from_parser): Empty implementation. - - * providers/mbox/camel-mbox-summary.c (message_struct_new): - Convert subject line to unicode, before storing in the summary. - (strdup_trim): Removed, no longer needed. - - * providers/mbox/camel-mbox-folder.c (_get_message_by_uid): Ref - the folder after setting it in the new message. - - * camel-mime-part.c (my_set_content_object): Have the headers - follow the content-type change here too. - (my_write_to_stream): Dont write content-type here, automatically - stored in the headers ... - (my_write_to_stream): Use header_disposition_format() to format - the content-disposition header. - (my_write_to_stream): Removed old code, all headers are now stored - in the camel-medium level, always. Need to do the same with - camel-mime-message i suppose ... - (my_write_to_stream): Write the content using the parent class, - not some weird function. - (camel_mime_part_class_init): Dont override get_output_stream. - (camel_mime_part_encoding_from_string): Bleh, make it - case-insensitive. - - * camel-mime-utils.c (header_content_type_is): Handle empty types. - (header_encode_string): Start of an implementation of the rfc2047 - encoder. It does iso-8859-1, and us-ascii, and utf-8 (others get - tricky *sigh*) - (rfc2047_encode_word): Convert a single word/string into rfc2047 - encoding. - (quoted_encode): Different quoted-printable encoding for rfc2047 - encoding of headers. - - * gmime-content-field.c (gmime_content_field_write_to_stream): Use - header_content_type_format() to format it. - -2000-04-21 NotZed - - * camel-mime-utils.h: Add prototype for header_param_list_free. - - * camel-recipient.c: New function to remove all the types of a - recipient list. I think this whole object needs a major review. - - * camel-mime-message.c (camel_mime_message_class_init): Removed - parse_header_pair override, override add_header instead. - (_parse_header_pair): Renamed to add_header. - (remove_header): Add this method, to make sure we keep upto date - with removed headers too. - (_set_field): If given a NULL value, clear it out. - (_set_recipient_list_from_string): Constify. - (set_header): Override set_header from camel_medium. - (process_header): Local function to handle set/add/remove of each - header we know about. - - * camel-mime-part.c (camel_mime_part_class_init): Removed - parse_header_pair setup. - (my_parse_header_pair): Moved into add_header(), removed. - (my_set_disposition): Allow a NULL disposition to clear it. - (my_set_content_id): Allow NULL content id to clear it. - (remove_header): Track removed headers. - (my_set_description): Allow NULL description to clear it. - (my_set_content_MD5): Make sure we copy the md5 value, and allow a - NULL value to reset it. - (my_set_filename): Copy the filename. - (my_set_header_lines): Removed. Nothing uses it, it doesn't - actually serve any purpose. - (camel_mime_part_set_header_lines): Ditto. - (my_get_header_lines): Ditto. - (camel_mime_part_get_header_lines): Ditto. - (camel_mime_part_class_init): Remove *_header_lines setup. - (camel_mime_part_init): Remove header_lines init. - (my_finalize): Remove header_lines finalise. - (my_write_to_stream): Write the headers here. This is just WRONG, - camel_medium should be doing this. - (my_get_output_stream): Kill a warning. - (camel_mime_part_encoding_to_string): Ditto. - (camel_mime_part_set_description): Unvirtualiase, use add_header() - to do the processing. - (my_set_description): Removed. - (set_disposition): Renamed from my_set_disposition. - (camel_mime_part_get_description): Get the descriptionf rom the - get_header method. - (my_get_description): Removed. - (my_set_filename): Removed. - (camel_mime_part_get_filename): Get the parameter from the - disposition. - (camel_mime_part_encoding_from_string): Handle NULL string. - (camel_mime_part_init): Remove reference to filename. - (my_finalize): Dont free filename. - - * camel-mime-part.h (CamelMimePartClass): Removed - parse_header_pair() method, it doesn't add anything that - add_header() can't be used for. - (CamelMimePartClass): Remove *_header_lines methods. - (struct _CamelMimePart): Remove header_lines list. - (struct _CamelMimePart): Removed filename attribute. - - * camel-medium.c (camel_medium_init): Init headers to null, not a - hashtable. - (add_header): Append the headers as a list. - (remove_header): Remove headers as a list. - (get_header): Likewise for lookup. - (free_header): Removed, no longer needed. - (finalize): Free headers using header_raw_clear(). - (camel_medium_set_header): New function, to reset and override all - values of a header with a new value. - - * camel-medium.h (struct _CamelMedium): Changed to use a - header_raw struct rather than a hash table, to store headers - (many headers can occur multiple times). - - * camel-mime-utils.c (header_raw_find_next): New function, allows - you to find multi-valued header fields. - (header_disposition_format): New function to format/create - content-disposition header string. - (header_param_list_format_append): Function to format parameter - lists into a GString. - (header_content_type_format): Function to format content-type into - a usable format. - (header_set_param): allow NULL value to remove the parameter. - (decode_token): Renamed from header_decode_token. - (header_decode_token): New interface for external use. - (quoted_decode): Made static to kill annoying warnings. - (g_strdup_len): Killed, replaced with calls to g_strndup(). - (rfc2047_decode_word): Made static to kill warnings. - (decode_coded_string): Terminated. - (g_string_append_len): Made static to kill warnings. - (header_decode_text): Made static to kill warnings. - (header_decode_text): Constify. - (rfc2047_decode_word): Constify. - (header_param): Constify. - (header_content_type_new): Copy the type/subtype strings. - (header_param_list_decode): Made static. - (header_param_list_format_append): Made static. - (quoted_decode): Constify. - (g_string_append_len): Constify. - (header_token_decode): New function to decode a single token. - - * providers/mbox/camel-mbox-summary.c (header_write): Append a - trailing \n when writing headers. - (strdup_trim): Killed a warning. - (camel_mbox_summary_set_uid): Make sure the next uid is at least 1 - higher than any existing one. - (header_evolution_decode): Use header_token_decode to get the - token. - - * camel-mime-parser.c (folder_scan_header): Strip the trailing \n - of the end of all header lines. - -2000-04-20 NotZed - - * providers/mbox/camel-mbox-utils.[ch]: Removed. - - * providers/mbox/camel-mbox-parser.[ch]: Removed. Removed - references to it. - -2000-04-20 Dan Winship - - * camel-mime-utils.c (rfc2047_decode_word): use libunicode iconv - functions rather than libc ones (since libc might not have them). - (header_decode_date): add autoconfiscation on timezone code - - * camel.c (camel_init): call unicode_init () - -2000-04-20 NotZed - - * providers/mbox/camel-mbox-summary.c (message_struct_new): Trim - leading/trailing spaces off the raw headers. - - * MERGE NEW_PARSER branch into HEAD, fixed conflicts. - - * gmime-content-field.c (_print_parameter): Duh, removed again - (@@#$@ cvs merge). - - * camel-mime-utils.c (header_content_type_is): Constify. - (header_content_type_unref): Killed a couple warnings. - - * camel-folder.c (_init): Removed more log crap. - - * providers/Makefile.am (SUBDIRS): Removed nntp, pending fixes for - summary changes. - - * providers/mbox/camel-mbox-folder.c (_get_message_by_number): - Fixed for new summary interface. Added a warning for using this - broken api. - (_get_message_by_uid): Fixed for message new with session - vanishing. - -2000-04-19 Dan Winship - - * camel-simple-data-wrapper-stream.c - (camel_simple_data_wrapper_stream_get_type): This is a subtype of - CamelSeekableStream, not CamelStream. - - * camel-seekable-substream.c: clean up a lot. - (eos): When testing for end-of-stream, reset the parent position - before testing if it is at end-of-stream, since either (a) it may - have been seek'ed to eos by someone else, or (b) we may have been - seek'ed away from eos and it hasn't been synced yet. - - * camel-medium.[ch] (camel_medium_add_header): const poison. - (Belatedly goes with my change of 2000-02-23.) - (camel_medium_init): Use g_strcase_{hash,equal} on the header - array. - -2000-04-18 Dan Winship - - * camel-mime-part.c (my_set_input_stream): - * camel-data-wrapper.c (set_input_stream, set_output_stream): do - better reference counting of streams so they actually go away - when they should. - - * camel-log.[ch], *: Nuke camel log stuff. Replace calls to - CAMEL_LOG_WARNING with calls to g_warning. - - * camel-data-wrapper.[ch]: - * camel-simple-data-wrapper.[ch]: - * camel-medium.[ch]: Clean, polish, document. Most of the gtk-doc - comments added to camel-data-wrapper.c note serious problems that - need to be fixed. - -2000-04-17 Dan Winship - - * camel-mime-message.[ch]: Remove the "session" field from - CamelMimeMessage. Nothing uses it, about half of the existing - calls to camel_mime_message_new_with_session pass NULL, and - there's no obvious reason for it to be there. - - * providers/MH/camel-mh-folder.c: - * providers/maildir/camel-maildir-folder.c: - * providers/mbox/camel-mbox-folder.c: - * providers/mbox/camel-mbox-utils.c: - * providers/nntp/camel-nntp-folder.c: - * providers/pop3/camel-pop3-folder.c: Use camel_mime_message_new - instead of camel_mime_message_new_with_session. - - * camel-session.c (get_store_for_protocol_with_url): Set the - exception if no provider is found. - - * camel-url.c: Add code to encode and decode %-escapes in URLs, - and do some additional correctness-checking on URL syntax. From - Tiago Anto with modifications by me. - -2000-04-14 Chris Toshok - - * providers/Makefile.am (SUBDIRS): add nntp - -2000-04-14 Christopher James Lahey - - * providers/mbox/camel-mbox-folder.c: Fix switch statement. - -2000-04-14 Chris Toshok - - * providers/nntp/camel-nntp-folder.c (_exists): always return TRUE - for now. we need to check the server response to make sure the - group exists. - (_get_message_by_uid): make sure to account for the \n we add to - the string after every line. - - * providers/nntp/camel-nntp-utils.c (get_XOVER_headers): function - to get the headers using the XOVER command. - (get_HEAD_headers): function to get the headers using the HEAD - command on each message. slooooooow. - (camel_nntp_get_headers): make this function use either XOVER or HEAD - versions depending on whether or not the server extension is present. - -2000-04-14 Dan Winship - - * camel-formatter.[ch]: This didn't belong in Camel. Move to mail/ - - * Makefile.am, camel-types.h: remove references to - camel-formatter. - -2000-04-12 Matt Loper - - * camel-folder-pt-proxy.c (_folder_open_cb): Print warning message - for broken function. - (_folder_close_cb): Same. - -2000-04-12 Miguel de Icaza - - * Makefile.am (pthread_SRC): Use correct names for the pthread - source variables. - -2000-04-10 Dan Winship - - * providers/pop3/camel-pop3-store.c (pop3_connect): fix various - bugs in APOP code (still untested) and some of the error cases. - - * camel-provider.h: Clarify what provider.protocol, provider.name, - and provider.description should be. - - * providers/mbox/camel-mbox-provider.c: - * providers/pop3/camel-pop3-provider.c: - * providers/sendmail/camel-sendmail-provider.c: - * providers/smtp/camel-smtp-provider.c: update protocols, names, - and descriptions - - * providers/mbox/camel-mbox-folder.c (_get_message_by_number): - implement get_message_by_number for the mail fetch code. - -2000-04-09 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c: reformatted to fit - the standard indent format used by helix code - -2000-04-09 Dan Winship - - * camel-movemail.c: New file with new function to dot-lock an mbox - file and copy it to a safe private directory. - -2000-04-08 Christopher James Lahey - - * providers/smtp/.cvsignore: Added a .cvsignore file. - -2000-04-08 Dan Winship - - * providers/sendmail/camel-sendmail-transport.c (_send_internal): - actually record the pid returned by fork(). Noticed by clahey. - - * providers/smtp/camel-smtp-transport.c: #include - for MAXHOSTNAMELEN. (This is a stopgap: some of the uses of - MAXHOSTNAMELEN are wrong anyway...) - -2000-04-07 Jeffrey Stedfast - - * providers/smtp/camel-smtp-transport.c: fixes to numerous bugs; - should now build fine. - * providers/Makefile.am: Readded smtp now that smtp builds without - error. - -2000-04-20 NotZed - - * providers/mbox/camel-mbox-summary.c - (camel_mbox_summary_next_uid): Public function to get the next - uid, makes sure its saved to disk too. - - * camel-mime-part.c (my_finalize): Fix disposition crap with a - real disposition. - (my_set_disposition): Likewise. - (my_get_disposition): And here. - (my_write_to_stream): And here, needs more cleanup. - - * providers/mbox/camel-mbox-folder.c (_append_message): Assign a - new uid at this point. - - * gmime-content-field.c (gmime_content_field_write_to_stream): - Make something up if we have an invalid/missing content type - (i.e. text/plain). - -2000-04-19 NotZed - - * providers/mbox/camel-mbox-folder.c (_delete): Fixed completely - broken switch() syntax, only compiled because errno is a macro on - some systems. - (_list_subfolders): Likewise. - -2000-04-18 NotZed - - * camel-mime-parser.c (folder_scan_init): init stream to null. - - * providers/mbox/camel-mbox-summary.c - (CAMEL_MBOX_SUMMARY_VERSION): Moved to .c file, incremented. - (index_folder): Changed to have index passed via the summary. - (decode_string): Do a sanity check on the string size, so we dont - visit g_malloc()'s friendly abort(). - - * camel-folder-pt-proxy.c (camel_folder_pt_proxy_class_init): - Removed reference to set_name. - (_set_name): Removed. - - * providers/mbox/camel-mbox-utils.c - (parsed_information_to_mbox_summary): Removed. Most of this file - is about to be binned. - - * providers/mbox/camel-mbox-search.c (func_header_contains): Fixes - for changes to summary interface. - (struct _searchcontext): Remove pointer to message info, get it - straight from the mboxsummary. - (camel_mbox_folder_search_by_expression): New summary interface. - (camel_mbox_folder_search_by_expression): Uh, the summary is not - an object anymore (well not yet). - - * providers/mbox/camel-mbox-folder.c - (camel_mbox_folder_class_init): Removed set_name init. - (_set_name): Removed. - (_open): Call new summary interface. - (_close): Use new summary interface. - (_create): Removed a summary object leak. - (_get_message_count): New summary interface. - (_get_uid_list): Use new summary interface. FIXME: this is leaky. - (_get_message_by_uid): Use the new summary interface, some - cleanup. - (_append_message): Totally changed, basically just appends the - message directly, ignores the summary (for now), the summary will - fix itself up if it needs to. - (_check_get_or_maybe_generate_summary_file): Bye bye old code. - (summary_get_message_info): Implement get_message_info again, for - folder. - - * camel-folder.c (camel_folder_class_init): Removed set_name - setup. - (_set_name): Moved contents into _init. - (_init): Perform the old functions of set_name here. - - * camel-folder.h: Removed the set_name internal interface. - -2000-04-14 NotZed - - * providers/mbox/camel-mbox-summary.[ch]: Completely replaced with - new code. - - * Makefile.am (libcamel_la_SOURCES): Removed - camel-folder-summary.[ch]. - - * camel-folder.h (struct _CamelFolder): Removed summary. - (struct _CamelFolder): Changed flags to be 1 bit bitfields. - - * camel-folder-summary.[ch]: Class removed entirely. - - * camel-folder.c (camel_folder_get_summary): Removed. - (camel_folder_summary_get_message_info): Moved from - camel-folder-summary.c - (camel_folder_summary_get_subfolder_info): Moved from - camel-folder-summary.c - - * camel-mime-parser.c (folder_scan_step): Store the start of - headers and start of from in the scan state. - (camel_mime_parser_tell_start_headers): Query the start of the - headers. - (camel_mime_parser_tell_start_from): Query the cached start of - from marker. - -2000-04-13 NotZed - - * gmime-content-field.c (gmime_content_field_free): Removed this - function. If its too dangerous to use, it shouldn't be here. - (gmime_content_field_ref): Also ref the embedded content-type. - (gmime_content_field_unref): Ditto to unref it. - - * camel-mime-utils.h: Add a refcount for content-type header. - - * camel-mime-utils.c (header_content_type_unref): Implement unref - for content-type. - (header_content_type_ref): Implement ref for header content type. - -2000-04-12 NotZed - - * gmime-content-field.h: Changed to use a _header_content_type. - Added type/subtype back for compatability with clients. - - * gmime-content-field.c: Basically a total rewrite, and now just a - thin wrapper ontop of header_content_type. - (_free_parameter): Got rid of it. - (gmime_content_field_new): Use header_content_type_* functions. - (gmime_content_field_set_parameter): Likewise. - (_print_parameter): Blow away. - (gmime_content_field_write_to_stream): Get details from the - content_type field. Should check if it needs to escape chars in - the paramter value. - (gmime_content_field_get_mime_type): Likewise. - (___debug_print_parameter): Get rid of this rather annoyingly - named function. - (gmime_content_field_get_parameter): Simplified function. - (gmime_content_field_construct_from_string): Fixed this to use a - real parser. - (gmime_content_field_is_type): New function to test if a type matches. - (gmime_content_field_construct_from_string): Track type/subtype - from subordinate content_type header struct. - - * gmime-rfc2047.[ch]: Removed. Unused. - - * camel-stream-b64.[ch]: Blown away more duplicated code. - - * Makefile.am: Removed camel-stream-b64.[ch], and - gmime-base64.[ch]. - - * camel-mime-part.c (my_get_content_object): Replaced - camel-stream-b64 with camel-stream-filter/camel-mime-filter-basic. - (my_write_content_to_stream): Replaced camel-stream-b64 with the - camel-stream-filter with an encoder. - (my_get_content_object): Also implement quoted-printable decoding. - (my_write_content_to_stream): Also implement quoted-printable - encoding. - (my_get_output_stream): Took out stream-b64 code (nothing's being - executed yet anyway). - - * gmime-base64.[ch]: Blown away. Not used, dont need it. - - * camel-mime-utils.h: Added offset for this header. Records where - it is in the source. - - * camel-mime-utils.c (header_raw_append_parse): Add offset - parameter, to store where the header is stored in the stream. - (header_raw_append): Added offset param. - (header_raw_find): Return offset, if a pointer supplied for it. - (header_raw_replace): Add offset param. - (header_content_type_new): New function, to create an empty - content type. - (header_content_type_set_param): Set a parameter in the - content-type. - (header_set_param): Generic header parameter setting function. - (header_decode_string): Handle NULL input. - - * camel-mime-parser.c (camel_mime_parser_headers_raw): New - function to get access to all the raw headers. - (folder_scan_header): Keep track of the header start position, and - store it when saving the header. - -2000-04-11 NotZed - - * camel-mime-utils.c: Moved a bunch of printf's to debug. - - * camel-mime-parser.c: Moved a bunch of printf's to debug. - (folder_scan_header): Detect end of each header line using the - last scanned char, and not the last scanned position. - - * camel-mime-filter-index.[ch]: Indexing filter. Indexes unicode - sequences into ibex files. - -2000-04-09 NotZed - - * camel-mime-part.c: Dont include gmime-base64.h - - * camel-mime-filter-charset.c (complete): Implement the completion - function. - - * camel-mime-parser.c (folder_scan_step): If we get to the end of - the body data, check any filters for outstanding completion data. - (camel_mime_parser_scan_from): Set whether we scan for "From " - headers or not. - - * camel-stream-filter.c (do_read): If we get to end of stream on - the source, then call the filtering completion function to see if - we have any more data to return. - - * camel-mime-filter-basic.c (filter): Implement quoted printable - encoding and decoding filters. - (complete): And the complete function as well. - - * camel-mime-utils.c (base64_encode_close): Also take an input - buffer, allow closing of filters. - (quoted_encode_step): First cut, simple quoted-printable encoder. - Doesn't handle trailing spaces/tabs on end of line properly yet. - (quoted_encode_close): Complete a quoted-encoding. - (is_qpsafe): New type check, for quoted-printable safe characters - (that do not need encoding). Thats all bits used in the type - table! Rebuilt the types table. - (header_content_type_is): Checks a content type against at - type/subtype match. - (header_content_type_param): Handle NULL content type pointer. - -2000-04-08 NotZed - - * camel-mime-filter-basic.c (filter): Implement the base64 - encoder. Problem is, there is no way to know when to close it. - Close/Reset will have to provide the same args as filter, so it can - flush remaining data *sigh* - - * camel-mime-utils.c (base64_encode_step): A rather complex base64 - encoder, fast? - (base64_step_close): Companion function to finish off the base64 - sequence. - - * camel-mime-part.c (my_write_content_to_stream): Changed to use - camel_stream_write_to_stream(). - - * camel-stream.[ch] (camel_stream_write_to_stream): From - camel_stream_b64_write_to_stream(). Fixed some infinite loop - bugs with error conditions. - - * camel-stream-b64.[ch] (camel_stream_b64_write_to_stream): Removed. - This has nothing to do with stream-b64, so i've moved it to - CamelStream. - - * camel-mime-utils.h: Add a comment about refcounting - header_content_type struct. - - * Makefile.am: Added camel-stream-filter*.[ch]. - - * camel-stream-filter.[ch]: Class to implement a generic - (multipass) filter ontop of a stream. Only implements a read-only - stream. - - * camel-mime-parser.c (camel_mime_parser_filter_add): Ref the - filter we just added. - - * Makefile.am: Added camel-mime-filter*.[ch]. - - * camel-mime-filter-charset.[ch]: A filter to preform character set - conversion (uses unicode_iconv). - - * camel-mime-filter-save.[ch]: A simple filter which will save all - data directly to a file or file descriptor. - - * camel-mime-filter-basic.[ch]: Implements the basic mime filters, - base64 and quoted-printable decoding (encoding not implemented yet). - - * camel-mime-filter.[ch]: A filtering class, which can filter streams - of data without having to copy them. Simpler than stream classes, - and can be plugged into a single stream class (when i write it). - -2000-04-07 Dan Winship - - * providers/pop3/camel-pop3-store.c (pop3_connect): Clarify error - messages. - (finalize): fix a bug in camel_exception usage - (pop3_connect): Remember the password after asking for it the - first time. - -2000-04-07 NotZed - - * Makefile.am: Added camel-mime-parser/camel-mime-utils. - - * camel-mime-parser.c: Fast mime parser. - - * camel-mime-utils.c: Mime utility functions, and email header - parsers. - -2000-04-07 NotZed - - * providers/Makefile.am: Removed smtp for now, its a long way from - building. - * providers/smtp/Makefile.in: Removed file that shouldn't have been - checked in. - -2000-04-06 Matt Loper - - * camel-folder-pt-proxy.c (_get_full_name): Remove exception param - from get_full_name() called, since get_full_name() was changed to - not have an exception in the last param (see dan's notes below). - (_get_name): same. - -2000-04-06 Dan Winship - - * camel-store.[ch]: Reorganize the folder-fetching methods and - implement a folder cache so that multiple requests for the same - folder will yield the same CamelFolder object (as long as it - remains active). Includes some code to remove no-longer-active - folders from the cache, but it doesn't get used since nothing is - ever unref'ed in Camel right now... - - * providers/mbox/camel-mbox-store.c: - * providers/pop3/camel-pop3-store.c: update for CamelStore - changes. - - * camel-folder.[ch]: Remove the (unused) CamelException argument - from camel_folder_get_name and camel_folder_get_full_name. - (camel_folder_set_name): make this go away since changing a - folder's name after it has been created could result in it - conflicting with a separately-issued folder. - -2000-04-05 Dan Winship - - * g_url_new really wanted to take a CamelException. So, rename - Gurl to CamelURL, g_url_* to camel_url_* (with camel_url_new - taking an exception), and url-util.[ch] to camel-url.[ch]. Also - force url->port to be numeric and remove camel_service_getport. (I - was confused before: the URL RFC says the port must be numeric, so - we don't want to do getportbyname.) - -2000-04-01 Dan Winship - - * providers/mbox/camel-mbox-folder.c - (_check_get_or_maybe_generate_summary_file): Compare - mbox_file_size and mbox_modtime to the results of stat()ing the - mbox file, not the summary file. Duh. - (_close): Update the summary's mbox_file_size and mbox_modtime - before writing it to disk. - - * providers/mbox/camel-mbox-summary.c (camel_mbox_summary_save, - camel_mbox_summary_load): Wow. I must have been tired when I wrote - this code. First, the comparison bug above. Second, it was using - ntohs and htons instead of ntohl and htonl. Third, I was reading - the status flag byte in two different places and thus getting out - of sync. Fourth, it was writing out field_length bytes of each - header field after having converted field_length to network byte - order, resulting in lots of random crap being appended, and the - summary files being huge. (Fortunately, since the size/modtime - comparison was biffed, the garbage summary read from disk was - always immediately discarded.) - - * providers/mbox/camel-mbox-parser.c (camel_mbox_parse_file): fix - an off-by-one error that caused the last-used UID to be reused if - the summary file was regenerated. (That one wasn't my fault. :-) - -2000-03-31 Dan Winship - - * camel-stream-mem.c: implement unimplemented methods - - * gmime-content-field.c - (gmime_content_field_construct_from_string): - * data-wrapper-repository.c - (data_wrapper_repository_get_data_wrapper_type): - * camel-simple-data-wrapper.c (my_write_to_stream): - * camel-mime-part.c (my_set_input_stream): - remove debugging printf()s that no longer seem useful. - -2000-03-31 Matt Loper - - * camel-formatter.c (text_to_html): Added "convert_newlines_to_br" - boolean param, to give the option of not converting '\n's to
- tags. This way, when we stick stuff in a
 tag, newlines stay
-	newlines.
-
-2000-03-30  Matt Loper  
-
-	* camel-formatter.c (handle_text_plain): Use 
 tag to force
-	the use of monospaced fonts.
-
-2000-03-30  Dan Winship  
-
-	* camel-service.c (camel_service_getport): Add a htons in the
-	default_number case, and document the fact that the function
-	returns the port in network byte order.
-
-	* providers/pop3/camel-pop3-store.c (pop3_connect): Revert
-	Miguel's change. The port number bug was actually somewhere
-	else, and the IP address copying code was fine already.
-	
-2000-03-29  Miguel de Icaza  
-
-	* providers/pop3/camel-pop3-store.c (pop3_connect): Add htons
-	(port), and only copy 4 bytes for the IP address to prevent a DNS
-	attack. 
-
-2000-03-28  Dan Winship  
-
-	* camel-seekable-substream.c
-	(camel_seekable_substream_new_with_seekable_stream_and_bounds):
-	make this return a CamelStream rather than a
-	CamelSeekableSubstream, because that's the way Gtk objects tend to
-	work.
-
-	* camel-service.c (camel_service_gethost,
-	camel_service_getport): convenience functions to canonicalize
-	the host and port values of a service's URL.
-	* providers/pop3/camel-pop3-store.c: use them
-
-	* providers/mbox/camel-mbox-folder.c
-	(_check_get_or_maybe_generate_summary_file): Make this work when
-	the inbox file doesn't yet exist.
-
-2000-03-27  Dan Winship  
-
-	* providers/mbox/camel-mbox-folder.c (_append_message): uncomment
-	the call to unlink the temp file: there's no way to tell
-	camel_stream_fs to truncate a file, so reusing the same file was
-	resulting in junk at the ends of messages.
-
-	* camel-folder.[ch]: add delete_message_by_{number,uid}.
-
-	* providers/pop3/camel-pop3-folder.[ch]: implement
-	delete_message_by_uid. Add a close method to do expunging
-	of deleted messages if requested.
-
-	* providers/pop3/camel-pop3-store.[ch]: support for
-	CamelPop3Folder::close. (You have to close the connection
-	in order to expunge the folder, thus the store may be
-	connected in the CamelService::is_connected sense when it
-	is not actually connected to the server.) Also some bugfixes.
-
-2000-03-27  NotZed  
-
-	* providers/mbox/camel-mbox-folder.c (_append_message): Unref the
-	output_stream when done, close doesn't do it.
-	(_append_message): Clear all uid's from the appending messages, so
-	they are reassigned proper unique id's.
-
-	* gmime-utils.c (get_header_array_from_stream): Actually free the
-	header, it is copied elsewhere.
-
-2000-03-26  NotZed  
-
-	* providers/mbox/camel-mbox-utils.c (camel_mbox_write_xev): Added
-	folder parameter to function.  Fixed callers.
-	(index_message): Index a message as it is assigned a unique id.
-
-	* camel-mime-part.c (my_set_content_id): Make sure we malloc and
-	copy the content_id, otherwise *poof*
-
-2000-03-25  NotZed  
-
-	* camel-medium.c (_finalize): Another leak, unref the content if
-	finished with it.
-
-	* camel-recipient.c (camel_recipient_table_free): Plug another
-	memory leak - actually free the recipient table.
-
-	* camel-mime-message.c (_finalize): Plugged a memory leak with the
-	flags table.
-
-	* gmime-utils.c (_store_header_pair_from_string): A simpler, more
-	debuggable and functionally identical header extraction function.
-
-2000-03-24  NotZed  
-
-	* gmime-content-field.c (gmime_content_field_set_parameter):
-	Remove the hash table entry before freeing its key and data.
-
-2000-03-27  Dan Winship  
-
-	* providers/Makefile.am (SUBDIRS): Add pop3.
-
-	* providers/pop3/camel-pop3-store.c: keep separate input and
-	output streams so the output doesn't end up being buffered.
-
-	* providers/pop3/camel-pop3-folder.c (get_message_by_number):
-	finish implementing this.
-
-2000-03-27  Michael Meeks  
-
-	* camel-mime-part.c (my_set_disposition): fix so less broken.
-	(my_finalize): remove dodgy disposition free.
-
-	* camel-data-wrapper.c (my_set_mime_type_field): unref instead of
-	free on mime_type.
-
-2000-03-27  Dan Winship  
-
-	* camel-service.c (camel_service_free_auth_types): new routine to
-	free the data allocated by camel_service_query_auth_types.
-
-	* providers/pop3/camel-pop3-store.c (free_auth_types): implement
-
-	* camel-stream-mem.c (camel_stream_mem_new_with_buffer): rename
-	camel_stream_mem_new_with_buffer to ..._with_byte_array and add a
-	new ..._with_buffer that takes a char * rather than a GByteArray.
-
-	* Remove CamelStreamBufferedFs, since CamelStreamBuffer makes it
-	redundant.
-
-2000-03-25  Dan Winship  
-
-	* camel-folder-summary.[ch]: change the CamelFolderSummary
-	interfaces to allow partial summary queries (for dealing
-	with very large folders). Remove the "extended_fields" from
-	CamelFolderInfo and CamelMessageInfo: this is better dealt
-	with by subtyping.
-
-	* providers/mbox/camel-mbox-summary.[ch]: Make CamelMboxSummary a
-	subclass of CamelFolderSummary. Update interfaces for that. Remove
-	the internal/external summary distinction. Remove the (unused) md5
-	checksum in the folder summary. Change the summary file format
-	(primarily to make it no longer byte-order dependent) and add a
-	version number to it so it will be easier to change in the future.
-	
-	* providers/mbox/camel-mbox-folder.[ch]
-	* providers/mbox/camel-mbox-search.c
-	* providers/mbox/camel-mbox-utils.c: update for summary changes
-
-	* camel-exception-list.def: add
-	CAMEL_EXCEPTION_FOLDER_SUMMARY_INVALID
-	
-2000-03-23  NotZed  
-
-	* providers/mbox/camel-mbox-provider.c: Added flag to provider
-	initialisation, to match changed structure.
-
-2000-03-22  NotZed  
-
-	* camel-folder.[ch]: Added async search api.
-
-	* providers/mbox/camel-mbox-search.c
-	(camel_mbox_folder_search_by_expression): Changed to use an
-	asynchronous interface.
-	(camel_mbox_folder_search_cancel): Cancel function for async
-	interface.
-
-2000-03-23  Dan Winship  
-
-	* camel-stream-buffer.c (camel_stream_buffer_read_line): Function
-	to read one line of any size from a stream and return it in
-	allocated memory.
-
-2000-03-22  Dan Winship  
-
-	* camel-service.c (camel_service_query_auth_types): New function
-	to query a service for the authentication protocols it supports.
-	* providers/pop3/camel-pop3-store.c (query_auth_types): implement
-
-	* camel-provider.c (camel_provider_scan): New function to
-	scan the provider dir and return a list of all providers.
-
-	* providers/pop3/camel-pop3-folder.c: fill this in partially
-	* providers/pop3/camel-pop3-store.c: make camel_pop3_command
-	return the text after "+OK"/"-ERR" and add a separate
-	camel_pop3_get_additional_data to get the message body or
-	whatever. Also make them take a CamelPop3Store rather than
-	a CamelStreamBuffer.
-
-2000-03-22  Matt Loper  
-
-	* camel-formatter.c (debug): Disabled some useless debug
-	messaging.
-
-2000-03-21  Dan Winship  
-
-	* providers/pop3: some initial bits of the POP3 provider, to
-	make Matt happy. Incomplete, untested, etc.
-
-2000-03-21  bertrand  
-
-	* providers/mbox/camel-mbox-summary.c 
-	(camel_mbox_summary_append_internal_to_external): copy the size field
-
-	* providers/mbox/camel-mbox-folder.c (_get_message_by_uid): initialize 
-	message_info to NULL
-
-	* camel-folder-summary.h: added the size field.
-
-	* providers/mbox/camel-mbox-summary.h: 
-	added the received_date field.
-
-	* providers/mbox/camel-mbox-summary.c:
-	documented all functions.
-
-	* camel-folder-summary.h: name change and 
-	new fields.
-
-	* providers/mbox/camel-mbox-search.c: update to 
-	conform to name change in the summary fields.
-
-2000-03-10  bertrand  
-
-	* camel-service.h: cosmetic changes.
-
-2000-03-09  Dan Winship  
-
-	* s/HelixCode/Helix Code, Inc./ in the copyrights
-
-2000-03-07  bertrand  
-
-	* camel-formatter.c (handle_mime_part): 
-	plug mem leaks due to bad documentation
-	of camel_content_field_get_mime_type
-	(print_camel_body_part): idem
-	(handle_multipart_alternative): idem
-
-	* gmime-content-field.c (gmime_content_field_get_mime_type): 
-	documentation fix.
-
-
-	* camel-mime-part.c (my_finalize): unref the 
-	content_input_stream if any. 
-
-2000-03-06  bertrand  
-
-	* camel-stream-fs.c (_seek): fix a bogus calculation
-	in the return position.
-
-2000-03-05  bertrand  
-
-	* camel-session.h: cosmetic fixes.
-
-	* camel-stream-fs.c (_read): 
-	(_seek): fixed the current position so that it refers
-	to the current position in the stream, not in its parent.
-
-2000-03-04  NotZed  
-
-	* providers/mbox/camel-mbox-search.c
-	(camel_mbox_folder_search_by_expression): Ref the summary
-	after we have got it.
-
-2000-03-04  bertrand  
-
-	* camel-mime-part.c (my_write_content_to_stream): 
-	stream the raw content instead of nothing if the encoding
-	is not supported.
-
-	* camel-stream-fs.c (_seek): handle eos more
-	properly.
-
-	* camel-formatter.c (get_bonobo_tag_for_object): 
-	bonobo-goad-id is the good key to look for. 
-	(get_bonobo_tag_for_object): close the  tag.
-	(get_bonobo_tag_for_object): the correct syntax for the
-	to set a parameter inside an  tag is :
-	  
-	
-
-2000-03-03  bertrand  
-
-	* providers/mbox/camel-mbox-folder.c (_get_message_by_uid): 
-	use set_input_stream instead of construct_from_stream
-	to feed the message object. 
-
-	* camel-data-wrapper.c (my_write_to_stream): reset output stream.
-	(my_set_input_stream): unref the previous input stream.
-	use the set_output_stream for default behaviour.
-	(my_set_output_stream): unref previous output stream.
-
-	* camel-mime-part.c (my_write_content_to_stream): reset content
-	object output stream.
-
-2000-03-03  NotZed  
-
-	* providers/mbox/camel-mbox-utils.c (camel_mbox_write_xev): Make
-	sure we open with create with a creation mask.
-
-2000-03-01  NotZed  
-
-	* camel-mime-part-utils.c
-	(camel_mime_part_construct_content_from_stream): DO NOT assert on
-	content type, we have fallback code 4 lines below it ... *sigh*
-
-2000-02-29  NotZed  
-
-	* Makefile.am (libcamelinclude_HEADERS): Added camel-stream-buffer
-	to build.
-
-	* camel-stream-buffer.[ch]: Generic buffer which can be applied to
-	any stream.
-
-2000-03-03  bertrand  
-
-	* camel-formatter.c (handle_image): in the case
-	of images, put the content object output stream
-	in the url. This allows the message browser
-	to show inline images.
-
-	* camel-stream-b64.c (my_read_encode): fixed state
-	0 keep value. 
-
-2000-03-02  bertrand  
-
-	* camel-stream-b64.c (my_read_encode): don't forget to 
-	set the state to 0 after 3.
-	(my_read_encode): don't forget to encode, even in state 3.
-
-	* camel-simple-data-wrapper.c: static functions are prefixed 
-	with my_ instead of _
-	* camel-multipart.c: static functions are prefixed 
-	with my_ instead of _
-	(my_write_to_stream): commented.
-	(my_write_to_stream): warning in case the boudary is set
-	but is a zero length string.
-
-	* camel-mime-part.c (camel_mime_part_encoding_from_string): 
-	remove debug trace. 
-	
-	* camel-mime-part.c: Replaced all static functions
-	with name begining with _ by the same name begining
-	with "my_" to prevent the possible conflicts 
-	with system symbols Dan warned us about. 
-	
-	* camel-stream-b64.c (camel_stream_b64_write_to_stream): 
-	use CamelStreamB64 type for the input stream.
-
-	* camel-mime-part.c (_get_content_object): remove 
-	debugging trace
-	(_write_content_to_stream): implement the b64 
-	encoding the new way (that is using camel_stream_b64)
-
-	* camel-data-wrapper.c (my_write_to_stream): 
-	fix implementation so that it writes properly
-	to the output stream even.
-
-	* camel-stream-b64.c (camel_stream_b64_write_to_stream): 
-	fix implementation. 
-
-2000-02-29  bertrand  
-
-	* camel-stream-b64.c (camel_stream_b64_write_to_stream): new
-	utility function. 
-
-	* camel-data-wrapper.c (_write_to_stream): default
-	implementation. 
-
-	* gmime-utils.c (_store_header_pair_from_string): 
-	revert strange changes. 
-
-	* camel-stream-b64.c (my_read_decode): set eos to true when we
-	have read the whole input stream. 
-	(my_reset): set eos to FALSE.
-
-2000-02-28  NotZed  
-
-	* camel-mime-part.c (_parse_header_pair): Dont free this either.
-
-	* camel-medium.c (_remove_header): Ugh, dont free the header
-	before we actually remove it.
-	(_add_header): Ugh, dont free hashtable entries which may be
-	duplicated (hash_insert _will_ reference that memory).
-
-	* string-utils.c (string_trim): Trimming a 0-length string is not
-	an error.
-
-	* camel-mime-message.c (_parse_header_pair): Fixed very broken
-	memory handling of header_name/value.
-
-	* providers/mbox/camel-mbox-utils.c (camel_mbox_write_xev):
-	Initialise end_of_last_message always.
-	(camel_mbox_copy_file_chunk): Stop trying to read if we run out of
-	data, rather than looping forever.
-	(camel_mbox_write_xev): Use an open flag when opening with create.
-
-	* camel-folder.c (camel_folder_search_by_expression): No, its not
-	a fatal error to search on a non-searchable folder, you just dont
-	get any matches.
-	(_open): Dont open an opened folder (i dont see why this is really
-	a bug, but what the hell ...)
-
-	* providers/mbox/camel-mbox-folder.c (_init): Set search cap on.
-	(_open): Call parent class to perform open.  Remove folder-open
-	check to parent instead.
-	(_create): open takes a creation mask, dont use umask to try and
-	set the open mode.
-	(_delete): Dont bother checking folder==NULL, its already been
-	checked on the external interface (changed to an assertion, this
-	would have to be a camel bug).
-	(_delete_messages): Likewise.
-	(_create): Ditto.
-	(_init): Dont go and clear all the paths and shit that the parent
-	open just setup for us.
-	(_delete_messages): Get rid of more umask stuff.
-	(_append_message): Make sure we pass file mode to open with create.
-	(_append_message): Cleaned up some indenting to make it readable.
-
-	* camel-stream-b64.c (my_read_encode): Fixed a typo.
-
-	* providers/mbox/camel-mbox-search.c: Changed to use e-sexp,
-	rather than filter-sexp.
-
-2000-02-28  bertrand  
-
-	* camel-stream-b64.c (my_read_encode): encoding
-	filter.
-
-2000-02-23  bertrand  
-
-	* camel-stream-b64.c: changed the __static 
-	suffix into a my_ prefix. 
-	(camel_stream_b64_set_mode): reset the persistent
-	status. 
-	(my_read_decode): remove superfluous %
-	
-	* providers/mbox/camel-mbox-utils.c (camel_mbox_copy_file_chunk): 
-	fix exception description message.
-
-2000-02-24  Dan Winship  
-
-	* camel-session.c: Add camel_session_get_transport_for_protocol.
-
-	* camel-transport.h:
-	* camel-transport.c: Add an abstract CamelTransport class.
-
-	* providers/sendmail/*: A CamelTransport that uses sendmail
-	to deliver mail.
-
-2000-02-24  Dan Winship  
-
-	* camel-folder.c: use CamelExceptions for run-time errors, not
-	incorrect code. Don't bother validating that an object exists from
-	inside one of its methods, since you couldn't have gotten there if
-	it didn't. Fix some code style bugs.
-
-	(_init): Rename init_with_store to init and add parent_folder,
-	separator, and name arguments.
-	(_set_name): Get separator from self, not parent_store now.
-
-	* camel-store.h:
-	* camel-store.c: Remove get/set_separator.
-
-	* providers/mbox/: Update for above.
-
-2000-02-23  Dan Winship  
-
-	* camel-medium.c (_finalize): Free the data in the headers hash
-	table.
-	(_add_header): g_strdup the header name and value when adding it.
-
-	* camel-mime-part-utils.c
-	(camel_mime_part_construct_headers_from_stream): Free the header
-	data after calling camel_medium_add_header, since it will have
-	g_strdup()ed it itself.
-
-2000-02-22  NotZed  
-
-	* providers/mbox/camel-mbox-search.c: Dont compile by default.
-
-	* providers/mbox/Makefile.am: Fuck off the filter code.
-
-2000-02-22  bertrand  
-
-	* camel-stream-b64.c (read_decode__static): 
-	don't read the char if we reached the length
-	of the output buffer. Hours lost on this
-	%$!@# bug : 3.5
-
-	* camel-folder.c (camel_folder_get_subfolder): 
-	(camel_folder_create): 
-	(camel_folder_delete): 
-	(camel_folder_delete_messages): 
-	(camel_folder_list_subfolders): 
-	(camel_folder_expunge): 
-	(camel_folder_get_message_by_number): 
-	(camel_folder_get_message_count): 
-	(camel_folder_append_message): 
-	(camel_folder_copy_message_to): 
-	(camel_folder_get_summary): 
-	(camel_folder_get_message_uid): 
-	(camel_folder_get_message_by_uid): 
-	(camel_folder_get_uid_list): 
-	Check folder state (open/close) and raise an
-	exception if it is not ok. 
-	
-	* providers/mbox/camel-mbox-folder.c (_create): 
-	create the file and the path with two different
-	names.
-
-	* camel-folder.c (_create): handle the case 
-	when the folder name starts with '/'
-
-	* camel-exception.c (camel_exception_new): use 
-	(void) instead of () in decl.
-
-	* camel-exception.h: cosmetic fixes.
-
-	* camel-exception.c (camel_exception_init): new routine.
-	Fix a bug in mail/message-list.c
-	
-
-	* camel-folder.h: cosmetic changes.
-
-	* camel-stream-b64.c (reset__static): added a
-	reset method. Thanks message-browser to find
-	so much bugs :)
-
-	* providers/mbox/Makefile.am (libcamelmbox_la_LIBADD): readd
-	Unicode libs.
-
-2000-02-21  bertrand  
-
-	* camel-formatter.c (lookup_unique_id): 
-	awful hack to test get_output_stream.
-	* camel-stream-b64.[ch] :
-	b64 encoding/decoding is now implemented as
-	a stream. 
-
-2000-02-21  bertrand  
-
-	* camel-seekable-substream.c (_reemit_parent_signal): 
-	emit "data_available" when parent stream emits it. 
-
-2000-02-21  NotZed  
-
-	* providers/mbox/Makefile.am: Uh, fixed LIBADD again.  What was
-	there was never ever going to work, wasn't it tested?
-
-2000-02-21  Dan Winship  
-
-	* camel-session.h: (struct _CamelSession): Add authenticator.
-
-	* camel-session.c (camel_session_new): Add authenticator.
-	(camel_session_query_authenticator): New function to query the
-	session authenticator for password, etc, information.
-
-2000-02-21  Dan Winship  
-
-	* camel-session.c: add CamelExceptions to several functions. Use
-	camel_session_new to initialize the session and URL fields of
-	created CamelStores as appropriate.
-
-	* camel-store.h:
-	* camel-store.c
-	* camel-service.h:
-	* camel-service.c: Move the session and url (and associated
-	functions) from CamelStore to CamelService. Add url_flags to
-	CamelService so subclasses can specify which URL components
-	are mandatory for them.	Add camel_session_new for
-	camel_session_get_store* to use.
-
-	* providers/mbox/camel-mbox-folder.c:
-	* providers/mbox/camel-mbox-store.c:
-	* providers/mbox/camel-mbox-store.h: Update for above changes.
-
-	* camel-exception-list.def: Once camel is being used for real,
-	exceptions won't be renumberable. So renumber them now to make
-	more room to add exceptions to the various categories later, and
-	add a big warning message.
-
-2000-02-20  Dan Winship  
-
-	* providers/mbox/Makefile.am: add libibex back to
-	libcamelmbox_la_LIBADD
-
-2000-02-18  NotZed  
-
-	* providers/mbox/camel-mbox-search.h
-	(camel_mbox_folder_search_by_expression): Added exception to call,
-	and fixed caller.
-
-	* providers/mbox/camel-mbox-search.c
-	(camel_mbox_folder_search_by_expression): Major changes, to use
-	the sexp evaluator from filter/filter-sexp.c to implement the
-	searching.
-	(func_body_contains): Changed to support multiple strings in 1
-	command (results or'd together)
-
-	* url-util.c (g_url_new): Fixed a typo (colon == 0 isn't right),
-	and made it so full url's are absolute pathed (Dan, this is how it
-	has to work!).  Also, always include a path part, even if it is an
-	empty string.
-
-2000-02-18  Dan Winship  
-
-	* camel/camel-types.h: New header with the typedefs for all camel
-	classes. Now the class headers can just include this and the
-	header for the parent type. This makes it possible for
-	CamelService to include a CamelSession without creating an
-	#include loop.
-
-	* camel/*:	
-	* composer/e-msg-composer-attachment-bar.h:
-	* mail/folder-browser.c:
-	* mail/message-list.c: frob #includes to match the new reality
-
-2000-02-17  Dan Winship  
-
-	* camel/camel-service.h:
-	* camel/camel-service.c: Make camel-service us a Gurl internally.
-	Remove the login/password interfaces and instead provide
-	camel_service_connect_with_url. Add CamelExceptions
-
-2000-02-17  bertrand  
-
-	* camel/camel-formatter.c (handle_text_plain): 
-	(handle_text_html): use camel_stream_reset instead
-	of seek. The formatter should be able to work 
-	with all streams, not only seekable streams. 
-	In the case where some provider implementation
-	would not be able to provide a reset method 
-	to their stream, implementors would have
-	to find a workaround.
-
-	* camel/camel-session.c (camel_session_new): use
-	(void) instean of () in function decl.
-
-	* camel/camel-folder.c: ifdef async operation 
-	related code. 
-
-	* camel/camel-seekable-stream.c (_seek): added a warning.
-	(_reset): default implementation of reset for seekable
-	stream.
-
-	* camel/camel-mime-message.h: set_received_date declaration fix.
-	cosmetic changes.
-
-	* camel/providers/mbox/camel-mbox-provider.c (camel_provider_module_init): 
-	use (void) instead of ().
-
-	* camel/camel-stream.c (camel_stream_reset): 
-	new method for CamelStream.
-
-2000-02-17  Dan Winship  
-
-	* camel/url-util.c (g_url_to_string): New function to convert
-	a Gurl back into a char *.
-
-2000-02-17  bertrand  
-
-	* camel/camel-formatter.c (handle_text_plain): 
-	revamped so that it uses the output stream
-	of the data wrapper
-	(handle_text_html): ditto.
-	
-	
-	* camel/camel-simple-data-wrapper.h: 
-	* camel/camel-simple-data-wrapper.c (camel_simple_data_wrapper_new): 
-	use (void) instead of ().
-	(_get_output_stream): simple implementation. 
-
-2000-02-16  bertrand  
-
-	* camel/camel-data-wrapper.c (_set_input_stream): ref input stream
-	(_set_output_stream): ref output stream
-	(_finalize): unref input and output streams
-
-	* camel/camel-seekable-substream.c (_set_bounds): don't
-	seek the begining of the substream.
-	(_eos): fix eos condition testing. 
-	(_finalize): unref parent stream
-	(_init_with_seekable_stream_and_bounds): ref parent stream
-
-	* camel/gstring-util.c (g_string_equal_for_hash): 
-	(g_string_equal_for_glist): return type is int.
-
-	* camel/camel.h: 
-	* camel/camel.c (camel_init): use (void) 
-	instead of ().
-	
-2000-02-16  NotZed  
-
-	* providers/mbox/Makefile.am (libcamelmbox_la_LIBADD): Added
-	libfilter to link line (temporarily?).  Required for
-	filter-sexp.
-
-2000-02-15  bertrand  
-
-	* camel/camel-multipart.c (_localize_part): 
-	this routine replaces the _read_part routine
-	and does not store the part in a buffer. 
-	(_set_input_stream): use the set_input_stream
-	instead of the construct_from_stream.
-	each bodypart is given an input stream. 
-
-	* camel/camel-mime-part-utils.c: 
-	include the data-wrapper-repository header. 
-	(camel_mime_part_construct_content_from_stream): 
-	use the set_input_stream instead of the 
-	construct_from_stream method. 
-
-	* camel/camel-seekable-substream.c (_set_bounds): 
-	cur position is set to 0 not to inf_bound.
-
-2000-02-15  bertrand  
-
-	* camel/camel-mime-part.c: include gmime-base64.h
-	various compilation and runtime fixes.
-	(_set_input_stream): store the input substream 
-	for the content object.
-
-	* camel/camel-data-wrapper.h: declare the 
-	set/get function on input/output stream.
-
-	* camel/camel-mime-part.c (_get_content_object): 
-	don't use a temporary mem stream.
-
-	* camel/camel-seekable-substream.c (_seek): 
-	(_eos): 
-	(_read): the substream can be unlimited in length
-
-	* camel/camel-data-wrapper.c (camel_data_wrapper_class_init): 
-	set the get/set_input/output_stream methods. 	
-
-	* camel/camel-multipart.c (_construct_from_stream): 
-	camel_stream_seek -> camel_seekable_stream_seek
-
-2000-02-14  Miguel de Icaza  
-
-	* camel/providers/mbox/Makefile.am (libcamelmbox_la_LIBADD): Add
-	the unicode libraries as well.
-
-	* camel/camel-provider.c (camel_provider_register_as_module): Add
-	error reporting here.  Desire to use Solaris increases.  Hair loss
-	in the last two hours: 5,400.
-
-	* camel/providers/mbox/camel-mbox-provider.c
-	(camel_mbox_get_provider): Renamed function.
-
-	* camel/camel.h: All include files use camel/ now here.
-
-	* camel/providers/mbox/Makefile.am: Drop all the dynamism from
-	Camel, and make this a standard library.
-
-2000-02-14  bertrand  
-
-	* camel/gmime-utils.c (get_header_array_from_stream): use the 
-	eos stream method. 
-	(gmime_read_line_from_stream): ditto.
-
-	* camel/camel-stream-fs.h (struct ): add the eof field
-	cosmetics changes. 
-
-	* camel/camel-stream-fs.c (camel_stream_fs_init): set eof.
-	(_read): set eof on end of file.
-	(_eos): implemented.
-
-	* camel/gmime-utils.c (get_header_array_from_stream): 
-	make a blocking version of the header parser. 
-	When the fs stream uses gnome-vfs, this should
-	be changed. 
-	(gmime_read_line_from_stream): ditto. 
-
-2000-02-11  bertrand  
-
-	* camel/camel-stream-fs.c: 
-	everywhere, when using the cur_pos field, do it
-	on the CamelSeekableStream object.
-	(_seek): small fix. 
-
-	* camel/camel-seekable-stream.c (camel_seekable_stream_seek): 
-	s/camel_stream_seek/camel_seekable_stream_seek/g
-
-	* camel/camel-seekable-stream.h: 
-	(struct ): added a field to store the
-	current position.
-
-	* camel/camel-seekable-stream.c (camel_seekable_stream_get_current_position): 
-	New function. Allows to get the current position 
-	of a seekable stream.
-	
-
-2000-02-13  NotZed  
-
-	* providers/mbox/camel-mbox-search.c: New file, implements the
-	search api for mbox folders.
-
-	* providers/mbox/Makefile.am: Link with ibex.
-
-	* camel-folder.c (camel_folder_has_search_capability): Api
-	additions.
-	(camel_folder_search_by_expression): Ditto.
-
-2000-02-12  NotZed  
-
-	* providers/mbox/camel-mbox-folder.c (_set_name): Setup index
-	filename as well.
-	(_init_with_store): Init index filename.  Hmm, none of these
-	names ever seem to get free'd (FIXME?)
-
-	* providers/mbox/camel-mbox-folder.h: Add index file name.
-
-2000-02-12  NotZed  
-
-	* camel-folder.h: Add folder search functions.
-
-	** Created ChangeLog just for camel **
-	 - refer to ../ChangeLog for changes prior to this date.
diff --git a/camel/Makefile.am b/camel/Makefile.am
deleted file mode 100644
index 3924e0cd80..0000000000
--- a/camel/Makefile.am
+++ /dev/null
@@ -1,296 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-SUBDIRS = . providers tests
-
-libcamelincludedir = $(privincludedir)/camel
-
-camellibexecdir = $(privlibexecdir)/camel
-camellibexec_PROGRAMS =	camel-lock-helper camel-index-control
-
-privlib_LTLIBRARIES = libcamel.la
-
-INCLUDES = -I.. -I$(srcdir)/.. 			 	\
-	-I$(top_srcdir)/intl			 	\
-	-I$(top_srcdir)/e-util			 	\
-	-DCAMEL_LIBEXECDIR=\""$(camellibexecdir)"\"	\
-	-DCAMEL_PROVIDERDIR=\""$(camel_providerdir)"\" 	\
-	-DG_LOG_DOMAIN=\"camel\"			\
-	$(CAMEL_CFLAGS)
-
-if ENABLE_SMIME
-SMIME_SOURCES_C = camel-smime-context.c
-SMIME_SOURCES_H = camel-smime-context.h
-else
-SMIME_SOURCES_C =
-SMIME_SOURCES_H =
-endif
-
-libcamel_la_SOURCES = 				\
-	broken-date-parser.c			\
-	camel-address.c				\
-	camel-arg.c				\
-	camel-block-file.c			\
-	camel-certdb.c				\
-	camel-charset-map.c			\
-	camel-cipher-context.c			\
-	camel-data-cache.c			\
-	camel-data-wrapper.c			\
-	camel-digest-folder.c			\
-	camel-digest-store.c			\
-	camel-digest-summary.c			\
-	camel-disco-diary.c			\
-	camel-disco-folder.c			\
-	camel-disco-store.c			\
-	camel-exception.c			\
-	camel-file-utils.c			\
-	camel-filter-driver.c			\
-	camel-filter-search.c			\
-	camel-folder-search.c			\
-	camel-folder-summary.c			\
-	camel-folder-thread.c			\
-	camel-folder.c				\
-	camel-gpg-context.c			\
-	camel-html-parser.c			\
-	camel-http-stream.c			\
-	camel-index.c				\
-	camel-internet-address.c		\
-	camel-junk-plugin.c			\
-	camel-lock.c				\
-	camel-lock-client.c			\
-	camel-medium.c				\
-	camel-mime-filter-bestenc.c		\
-	camel-mime-filter-basic.c		\
-	camel-mime-filter-charset.c		\
-	camel-mime-filter-canon.c		\
-	camel-mime-filter-crlf.c		\
-	camel-mime-filter-enriched.c		\
-	camel-mime-filter-from.c		\
-	camel-mime-filter-html.c		\
-	camel-mime-filter-tohtml.c		\
-	camel-mime-filter-index.c		\
-	camel-mime-filter-linewrap.c		\
-	camel-mime-filter-save.c		\
-	camel-mime-filter-windows.c		\
-	camel-mime-filter.c			\
-	camel-mime-message.c			\
-	camel-mime-parser.c			\
-	camel-mime-part-utils.c			\
-	camel-mime-part.c			\
-	camel-mime-utils.c			\
-	camel-movemail.c			\
-	camel-multipart.c			\
-	camel-multipart-encrypted.c		\
-	camel-multipart-signed.c		\
-	camel-object.c				\
-	camel-operation.c			\
-	camel-partition-table.c			\
-	camel-provider.c			\
-	camel-sasl.c				\
-	camel-sasl-anonymous.c			\
-	camel-sasl-cram-md5.c			\
-	camel-sasl-digest-md5.c			\
-	camel-sasl-gssapi.c			\
-	camel-sasl-kerberos4.c			\
-	camel-sasl-login.c			\
-	camel-sasl-ntlm.c			\
-	camel-sasl-plain.c			\
-	camel-sasl-popb4smtp.c			\
-	camel-search-private.c			\
-	camel-seekable-stream.c			\
-	camel-seekable-substream.c		\
-	camel-service.c				\
-	camel-session.c				\
-	$(SMIME_SOURCES_C)			\
-	camel-store.c				\
-	camel-store-summary.c			\
-	camel-stream-buffer.c			\
-	camel-stream-filter.c			\
-	camel-stream-fs.c			\
-	camel-stream-mem.c			\
-	camel-stream-null.c			\
-	camel-stream-process.c			\
-	camel-stream.c				\
-	camel-string-utils.c			\
-	camel-text-index.c			\
-	camel-tcp-stream-raw.c			\
-	camel-tcp-stream-ssl.c			\
-	camel-tcp-stream-openssl.c		\
-	camel-tcp-stream.c			\
-	camel-transport.c			\
-	camel-uid-cache.c			\
-	camel-url.c				\
-	camel-url-scanner.c			\
-	camel-utf8.c				\
-	camel-vee-folder.c			\
-	camel-vee-store.c			\
-	camel-vtrash-folder.c			\
-	camel.c
-
-libcamelinclude_HEADERS =			\
-	broken-date-parser.h			\
-	camel-address.h				\
-	camel-arg.h				\
-	camel-block-file.h			\
-	camel-certdb.h				\
-	camel-charset-map.h			\
-	camel-cipher-context.h			\
-	camel-data-cache.h			\
-	camel-data-wrapper.h			\
-	camel-digest-folder.h			\
-	camel-digest-store.h			\
-	camel-digest-summary.h			\
-	camel-disco-diary.h			\
-	camel-disco-folder.h			\
-	camel-disco-store.h			\
-	camel-exception-list.def		\
-	camel-exception.h			\
-	camel-file-utils.h			\
-	camel-filter-driver.h			\
-	camel-filter-search.h			\
-	camel-folder-search.h			\
-	camel-folder-summary.h			\
-	camel-folder-thread.h			\
-	camel-folder.h				\
-	camel-gpg-context.h			\
-	camel-http-stream.h			\
-	camel-index.h				\
-	camel-internet-address.h		\
-	camel-i18n.h				\
-	camel-junk-plugin.h			\
-	camel-lock.h				\
-	camel-lock-client.h			\
-	camel-medium.h				\
-	camel-mime-filter-bestenc.h		\
-	camel-mime-filter-basic.h		\
-	camel-mime-filter-charset.h		\
-	camel-mime-filter-canon.h		\
-	camel-mime-filter-crlf.h		\
-	camel-mime-filter-enriched.h		\
-	camel-mime-filter-from.h		\
-	camel-mime-filter-html.h		\
-	camel-mime-filter-tohtml.h		\
-	camel-mime-filter-index.h		\
-	camel-mime-filter-linewrap.h		\
-	camel-mime-filter-save.h		\
-	camel-mime-filter-windows.h		\
-	camel-mime-filter.h			\
-	camel-mime-message.h			\
-	camel-mime-parser.h			\
-	camel-mime-part-utils.h			\
-	camel-mime-part.h			\
-	camel-mime-utils.h			\
-	camel-movemail.h			\
-	camel-multipart.h			\
-	camel-multipart-encrypted.h		\
-	camel-multipart-signed.h		\
-	camel-object.h				\
-	camel-operation.h			\
-	camel-partition-table.h			\
-	camel-provider.h			\
-	camel-sasl.h				\
-	camel-sasl-anonymous.h			\
-	camel-sasl-cram-md5.h			\
-	camel-sasl-digest-md5.h			\
-	camel-sasl-gssapi.h			\
-	camel-sasl-kerberos4.h			\
-	camel-sasl-login.h			\
-	camel-sasl-ntlm.h			\
-	camel-sasl-plain.h			\
-	camel-sasl-popb4smtp.h			\
-	camel-seekable-stream.h			\
-	camel-seekable-substream.h		\
-	camel-service.h				\
-	camel-session.h				\
-	$(SMIME_SOURCES_H)			\
-	camel-store.h				\
-	camel-store-summary.h			\
-	camel-stream-buffer.h			\
-	camel-stream-filter.h			\
-	camel-stream-fs.h			\
-	camel-stream-mem.h			\
-	camel-stream-null.h			\
-	camel-stream-process.h			\
-	camel-stream.h				\
-	camel-string-utils.h			\
-	camel-text-index.h			\
-	camel-tcp-stream-raw.h			\
-	camel-tcp-stream-ssl.h			\
-	camel-tcp-stream.h			\
-	camel-transport.h			\
-	camel-types.h				\
-	camel-uid-cache.h			\
-	camel-url.h				\
-	camel-url-scanner.h			\
-	camel-utf8.h				\
-	camel-vee-folder.h			\
-	camel-vee-store.h			\
-	camel-vtrash-folder.h			\
-	camel.h
-
-libcamel_la_LDFLAGS = -version-info 0:0:0
-
-libcamel_la_LIBADD =				\
-	$(top_builddir)/e-util/libeutil.la 	\
-	$(CAMEL_LIBS)
-
-camel_lock_helper_SOURCES = 			\
-	camel-lock-helper.c 			\
-	camel-lock-helper.h
-
-# NOTE: This needs to be cleaned up, it shouldn't link with all this crap,
-# because it might be setuid.
-camel_lock_helper_LDADD =			\
-	camel-lock.o				\
-	$(libcamel_la_LIBADD)
-
-camel_index_control_SOURCES =			\
-	camel-index-control.c
-
-camel_index_control_LDADD =			\
-	$(libcamel_la_LIBADD)			\
-	libcamel.la
-#	$(EVOLUTION_MAIL_LIBS)
-
-install-exec-hook:
-	@if test -n "$(CAMEL_LOCK_HELPER_USER)"; then \
-	    if test `whoami` = root ; then \
-	 	chown $(CAMEL_LOCK_HELPER_USER) $(DESTDIR)$(camellibexecdir)/camel-lock-helper ; \
-		chmod u+s $(DESTDIR)$(camellibexecdir)/camel-lock-helper ; \
-	    else \
-	    	echo '*** WARNING ***' ; \
-		    echo "Camel will not be able to open mbox files until you perform the following steps:" ; \
-		    echo "    1. Become root" ; \
-		    echo "    2. chown $(CAMEL_LOCK_HELPER_USER) $(DESTDIR)$(sbindir)/camel-lock-helper" ; \
-		    echo "    3. chmod u+s $(DESTDIR)$(sbindir)/camel-lock-helper" ; \
-		    echo '*** WARNING ***' ; \
-	    fi \
-	else \
-	    echo "No user to chown to"; \
-	fi
-	@if test -n "$(CAMEL_LOCK_HELPER_GROUP)"; then \
-	    if test `whoami` = root ; then \
-	    	chgrp $(CAMEL_LOCK_HELPER_GROUP) $(DESTDIR)$(camellibexecdir)/camel-lock-helper ; \
-		    chmod g+s $(DESTDIR)$(camellibexecdir)/camel-lock-helper ; \
-	    else \
-	    	echo '*** WARNING ***' ; \
-		    echo "Camel will not be able to open mbox files until you perform the following steps:" ; \
-		    echo "    1. Become root" ; \
-		    echo "    2. chgrp $(CAMEL_LOCK_HELPER_GROUP) $(DESTDIR)$(camellibexecdir)/camel-lock-helper" ; \
-		    echo "    3. chmod g+s $(DESTDIR)$(camellibexecdir)/camel-lock-helper" ; \
-		    echo '*** WARNING ***' ; \
-	    fi \
-	else \
-	    echo "No user to chown to"; \
-	fi
-
-noinst_HEADERS =				\
-	camel-charset-map-private.h		\
-	camel-private.h				\
-	camel-search-private.h			\
-	camel-html-parser.h
-
-EXTRA_DIST =					\
-	ChangeLog.pre-1-4			\
-	camel-smime-context.h			\
-	camel-smime-context.c			\
-	README
diff --git a/camel/README b/camel/README
deleted file mode 100644
index 89b57ad3c7..0000000000
--- a/camel/README
+++ /dev/null
@@ -1,54 +0,0 @@
-
-                                   CAMEL
-     
-
-			A generic Messaging Library
-
-
-                                   ----
-				
-
-Introduction:
--------------
-
-Camel is a generic messaging library. It supports the standard 
-messaging system for receiving and sending messages. It is the 
-messaging backend for Evolution.
-
-The name "camel" stands for ... nothing. Open area of development there.
-You know, that "bazaar" thing. Maybe could we organize a big contest on
-gnome-list to find the best explanation :)
-
-Camel draws heavily from JavaMail and the IMAP4rev1 RFC. People
-wanting to hack on a provider should read the JavaMail API
-specification, but CMC and MAPI are of interest too.
-
- 
-Organization:
--------------
-
-The library is roughly a set of abstract classes, some kind of generic
-"interfaces" (IDL interfaces, not Java interfaces).
-
-Particular implementations are called providers.
-
-Here are the basic objects:
-
-* CamelService : An abstract class representing an access to a server.
-Handles the connection and authentication to any server.
-
-* CamelStore (CamelService): A hierarchy of folders on a server.
-
-* CamelFolder : An object containing messages. A folder is always
-associated with a store.
-
-* CamelMessage : An object contained in folders. Is defined by a set
-of attributes and a content. (Attributes include: the date it was
-received, the sender address, .....)
-
-* CamelTransport (CamelService): A way to send messages.
-
-....
-...
-
-
diff --git a/camel/README.COPYRIGHT b/camel/README.COPYRIGHT
deleted file mode 100644
index bad1b76eb8..0000000000
--- a/camel/README.COPYRIGHT
+++ /dev/null
@@ -1,46 +0,0 @@
-Important note for Camel hackers:
----------------------------------
-
-Camel has been a lot of work, and has been conceived to be general
-enough to be used outside the gnome-mailer. It is possible in the
-future that it is used in software with licenses incompatible with the
-GPL. For this reason, the copyright has to be owned by a unique
-entity.  Be sure, however, that Camel will always be available under
-the GPL.  Significant authors will always be consulted before any
-special use of Camel. Moreover, in special situations, they may be
-given the authorization to use Camel with a license different than the
-GPL.
-
-Thus, when adding code in Camel, always add the following lines at the
-begining of the file:
-
-/* 
- * Copyright 1999, 200x Ximian, Inc. (http://www.ximian.com)
- * 
- * Author: Your name 
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-You may also want to add your name to the author list inside this
-header.
-
-Please contact Ximian, Inc. (http://www.ximian.com) if you want to discuss 
-this copyright issue.
-
-Happy hacking,
-
-Ximian, Inc.
diff --git a/camel/README.HACKING b/camel/README.HACKING
deleted file mode 100644
index a4742ee7b8..0000000000
--- a/camel/README.HACKING
+++ /dev/null
@@ -1,14 +0,0 @@
-You want to hack on Camel ?
-
-Thanks. Camel aims at being the best messaging
-library for Linux and your help is welcome. 
-Please be sure to read the following files before
-commiting any change or sending any patch:
-
-CODING.STYLE
-README.COPYRIGHT
-
-
-Thanks.
-
-	Bertrand 
\ No newline at end of file
diff --git a/camel/README.mt b/camel/README.mt
deleted file mode 100644
index aeece1b0bb..0000000000
--- a/camel/README.mt
+++ /dev/null
@@ -1,171 +0,0 @@
-
-This version of camel is working towards being multi-thread safe
-(MT-SAFE).  At least, for the important api's.
-
-This code has now been merged into the main head, but this file
-will remain here as a log of how it was done, incase any issues
-arise.  The ChangeLog of course has a much more detailed list
-of changes.
-
-Intended method
-===============
-
-I intend working on it in several stages:
-
-1. Making the api multi-threadable.  Basically removing some const-returns,
-and copying some data where it wasn't before.  The api should
-still continue to work if not being used in a multithreaded
-application.  There is not a significant amount of work here since
-this was more or less the intention all along.
-
-Some functions where references to objects are returned may have to be
-changed slightly, so that refcounts are incremented before return.
-This doesn't affect much though.
-
-camel_folder::get_message_info				done
-camel_folder_summary::uid				done
-camel_folder_summary::index				done
-camel_folder::get_summary
-	Needs to ref each summary item it points to.	done
-camel_folder::free_summary
-	Needs to unref each summary item it points to.	done
-camel_folder_get_message_tag
-	needs to copy the tag return
-camel_maildir_summary filename string
-	should not be able to modify the string
-	array contents after it has been added to
-	the summary.
-camel_folder						done
-	Make every camel-folder use a camel-folder-summary.
-	This just reduces some of the code duplication,
-	since everything but vee-folder does this already.
-
-2. Adding high level locks for proof of concept.  The locks will
-be stored in private or global data, so the api should remain the same for
-non-threaded applications.
-
-A per-folder lock which governs access to the folder
-	summary, the folder file or
-	communications socket, etc.			done
-Locking for exceptions.					done
-Per store locks for internal stuff.			done
-Per-service locks for various internal lists and
-	caches						done
-
-3. Further fine-grained locking where it can be done/is worthwhile.
-
-A per-index lock for libibex				done
-Locking for the search object				half done
-Internal lock for the folder_summary itself
-	So that searching can be detatched from other
-	folder operations, etc.				done
-Possibly a lock for access to parts of a mime-part
-	or message
-
-4. A method to cancel operations.
-
-Individual outstanding operations must be cancellable, and not just
-'all current operations'.  This will probably not use pthread_cancel
-type of cancelling.
-
-This will however, probably use a method for starting a new thread,
-through camel, that can then be cancelled, and/or some method of
-registering that a thread can be cancelled.  Blocking states within
-camel, within that thread, will then act as checkpoints for if the
-operation, and if it is cancelled, the operation will abort
-(i.e. fail, with an appropriate exception code).
-
-Operation cancelling should also function when the application is not
-multi-threaded.  Not sure of the api for this yet, probably a callback
-system.  Hopefully the api for both scenarios can be made the same.
-
-Other thoughts
-==============
-
-Basically much of the code in camel that does the actual work does NOT
-need to be thread safe to make it safely usable in an mt context.
-
-camel-folder, camel-summary, camel-imap-search, and the camel-service
-classes (at least) are the important ones to be made multithreaded.
-
-For other things, they are either resources that are created
-one-off (for example, camel-mime-message, and its associated
-parts, like camel-internet-address), or multithreadedness
-doesn't make a lot of sense - e.g. camel-stream, or camel-mime-parser.
-
-So basically the approach is a low-risk one.  Adding the minimum
-number of locks to start with, and providing further fine-grained
-locks as required.  The locks should not need to be particularly
-fine-grained in order to get reasonable results.
-
-Log of changes
-==============
-
-Changed CamelFolder:get_message_info() to return a ref'd copy, requiring
-all get_message_info()'s to have a matching free_message_info().
-
-Moved the CamelFolder frozen changelog data to a private structure.
-
-Added a mutex for CamelFolder frozen changelog stuff (it was just easy
-to do, although it isn't needed yet).
-
-Added a single mutex around all other CamelFolder functions that need
-it, this is just the first cut at mt'edness.
-
-Fixed all camel-folder implementations that call any other
-camel-folder functions to call via virtual methods, to bypass the locks.
-
-Added camel-store private data.
-
-Added a single mutex lock for camel-store's folder functions.
-
-Added camel-service private data.
-
-Added a single mutex lock for camel-service's connect stuff.
-
-Added a mutex for remote-store stream io stuff.
-
-Added a mutex for imap, so it can bracket a compound command
-exclusively.  Pop doesn't need this since you can only have a single
-folder per store, and the folder interface is already forced
-single-threaded.
-
-Added mutex for camel-session, most operations.
-
-Running the tests finds at least 1 deadlock so far.  Need to
-work on that.
-
-Fixed get_summary to ref/unref its items.
-
-Removed the global folder lock from the toplevel
-camel_folder_search(), each implementation must now handle locking.
-
-Fixed the local-folder implementation of searching.  imap-folder
-searching should already be mt-safe through the command lock.
-
-Fixed imap summary to ref/unref too.
-
-Built some test cases, and expanded the test framework library to
-handle multiple threads.  It works!
-
-Next, added a recursive mutex class, so that locking inside imap had
-any chance of working.  Got imap working.
-
-Moved the camel folder summary into the base folder class, and fixed
-everything to use it that way.
-
-Made the vfolder use a real camel-folder-summary rather than a
-hashtable + array that it was using, and probably fixed some problems
-which caused evolution-mail not to always catch flag updates.  Oh, and
-made it sync/expunge all its subfolders when sync/expungeing.
-
-Made the camel-folder summary completely mt-safe.
-
-Removed all of the locks on the folder functions dealing directly with
-the summary, so now for example all summary lookups will not be
-interupted by long operations.
-
-Made the nntp newsrc thing mt-safe, because of some unfortunate
-sideeffect of it being called from the summary interaction code in
-nntp-folder.
-
diff --git a/camel/broken-date-parser.c b/camel/broken-date-parser.c
deleted file mode 100644
index 19fc0c2271..0000000000
--- a/camel/broken-date-parser.c
+++ /dev/null
@@ -1,532 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *
- *  Copyright 2000 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "broken-date-parser.h"
-#include "e-time-utils.h"
-
-#define d(x)
-
-#define NUMERIC_CHARS          "1234567890"
-#define WEEKDAY_CHARS          "SundayMondayTuesdayWednesdayThursdayFridaySaturday"
-#define MONTH_CHARS            "JanuaryFebruaryMarchAprilMayJuneJulyAugustSeptemberOctoberNovemberDecember"
-#define TIMEZONE_ALPHA_CHARS   "UTCGMTESTEDTCSTCDTMSTPSTPDTZAMNY()"
-#define TIMEZONE_NUMERIC_CHARS "-+1234567890"
-#define TIME_CHARS             "1234567890:"
-
-#define DATE_TOKEN_NON_NUMERIC          (1 << 0)
-#define DATE_TOKEN_NON_WEEKDAY          (1 << 1)
-#define DATE_TOKEN_NON_MONTH            (1 << 2)
-#define DATE_TOKEN_NON_TIME             (1 << 3)
-#define DATE_TOKEN_HAS_COLON            (1 << 4)
-#define DATE_TOKEN_NON_TIMEZONE_ALPHA   (1 << 5)
-#define DATE_TOKEN_NON_TIMEZONE_NUMERIC (1 << 6)
-#define DATE_TOKEN_HAS_SIGN             (1 << 7)
-
-static unsigned char datetok_table[256] = {
-        128,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-        111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-        111,111,111,111,111,111,111,111, 79, 79,111,175,111,175,111,111,
-         38, 38, 38, 38, 38, 38, 38, 38, 38, 38,119,111,111,111,111,111,
-        111, 75,111, 79, 75, 79,105, 79,111,111,107,111,111, 73, 75,107,
-         79,111,111, 73, 77, 79,111,109,111, 79, 79,111,111,111,111,111,
-        111,105,107,107,109,105,111,107,105,105,111,111,107,107,105,105,
-        107,111,105,105,105,105,107,111,111,105,111,111,111,111,111,111,
-        111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-        111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-        111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-        111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-        111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-        111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-        111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-        111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-};
-
-/* hrm, is there a library for this shit? */
-static struct {
-	char *name;
-	int offset;
-} tz_offsets [] = {
-	{ "UT", 0 },
-	{ "GMT", 0 },
-	{ "EST", -500 },	/* these are all US timezones.  bloody yanks */
-	{ "EDT", -400 },
-	{ "CST", -600 },
-	{ "CDT", -500 },
-	{ "MST", -700 },
-	{ "MDT", -600 },
-	{ "PST", -800 },
-	{ "PDT", -700 },
-	{ "Z", 0 },
-	{ "A", -100 },
-	{ "M", -1200 },
-	{ "N", 100 },
-	{ "Y", 1200 },
-};
-
-static char *tm_months[] = {
-	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-static char *tm_days[] = {
-	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-};
-
-
-struct _date_token {
-	struct _date_token *next;
-	const unsigned char *start;
-	unsigned int len;
-	unsigned int mask;
-};
-
-/* This is where it gets ugly... */
-static struct _date_token *
-datetok (const char *date)
-{
-	struct _date_token *tokens = NULL, *token, *tail = (struct _date_token *) &tokens;
-	const unsigned char *start, *end;
-	unsigned int mask;
-	
-	start = date;
-	while (*start) {
-		/* kill leading whitespace */
-		while (*start && isspace ((int) *start))
-			start++;
-		
-		if (*start == '\0')
-			break;
-		
-		mask = datetok_table[*start];
-		
-		/* find the end of this token */
-		end = start + 1;
-		while (*end && !strchr ("-/,\t\r\n ", *end))
-			mask |= datetok_table[*end++];
-		
-		if (end != start) {
-			token = g_malloc (sizeof (struct _date_token));
-			token->next = NULL;
-			token->start = start;
-			token->len = end - start;
-			token->mask = mask;
-			
-			tail->next = token;
-			tail = token;
-		}
-		
-		if (*end)
-			start = end + 1;
-		else
-			break;
-	}
-	
-	return tokens;
-}
-
-static int
-decode_int (const unsigned char *in, unsigned int inlen)
-{
-	register const unsigned char *inptr;
-	const unsigned char *inend;
-	int sign = 1, val = 0;
-	
-	inptr = in;
-	inend = in + inlen;
-	
-	if (*inptr == '-') {
-		sign = -1;
-		inptr++;
-	} else if (*inptr == '+')
-		inptr++;
-	
-	for ( ; inptr < inend; inptr++) {
-		if (!isdigit ((int) *inptr))
-			return  -1;
-		else
-			val = (val * 10) + (*inptr - '0');
-	}
-	
-	val *= sign;
-	
-	return val;
-}
-
-static int
-get_wday (const unsigned char *in, unsigned int inlen)
-{
-	int wday;
-	
-	if (inlen < 3)
-		return -1;
-	
-	for (wday = 0; wday < 7; wday++)
-		if (!strncasecmp (in, tm_days[wday], 3))
-			return wday;
-	
-	return -1;  /* unknown week day */
-}
-
-static int
-get_mday (const unsigned char *in, unsigned int inlen)
-{
-	int mday;
-	
-	mday = decode_int (in, inlen);
-	
-	if (mday < 0 || mday > 31)
-		mday = -1;
-	
-	return mday;
-}
-
-static int
-get_month (const unsigned char *in, unsigned int inlen)
-{
-	int i;
-	
-	if (inlen < 3)
-		return -1;
-	
-	for (i = 0; i < 12; i++)
-		if (!strncasecmp (in, tm_months[i], 3))
-			return i;
-	
-	return -1;  /* unknown month */
-}
-
-static int
-get_year (const unsigned char *in, unsigned int inlen)
-{
-	int year;
-	
-	year = decode_int (in, inlen);
-	if (year == -1)
-		return -1;
-	
-	if (year < 100)
-		year += (year < 70) ? 2000 : 1900;
-	
-	if (year < 1969)
-		return -1;
-	
-	return year;
-}
-
-static gboolean
-get_time (const unsigned char *in, unsigned int inlen, int *hour, int *min, int *sec)
-{
-	register const unsigned char *inptr;
-	const unsigned char *inend;
-	int *val, colons = 0;
-	
-	*hour = *min = *sec = 0;
-	
-	inend = in + inlen;
-	val = hour;
-	for (inptr = in; inptr < inend; inptr++) {
-		if (*inptr == ':') {
-			colons++;
-			switch (colons) {
-			case 1:
-				val = min;
-				break;
-			case 2:
-				val = sec;
-				break;
-			default:
-				return FALSE;
-			}
-		} else if (!isdigit ((int) *inptr))
-			return FALSE;
-		else
-			*val = (*val * 10) + (*inptr - '0');
-	}
-	
-	return TRUE;
-}
-
-static int
-get_tzone (struct _date_token **token)
-{
-	const unsigned char *inptr, *inend;
-	unsigned int inlen;
-	int i, t;
-	
-	for (i = 0; *token && i < 2; *token = (*token)->next, i++) {
-		inptr = (*token)->start;
-		inlen = (*token)->len;
-		inend = inptr + inlen;
-		
-		if (*inptr == '+' || *inptr == '-') {
-			t = decode_int (inptr, inlen);
-			if (t < -1200 || t > 1400)
-				return -1;
-			
-			return t;
-		} else {
-			if (*inptr == '(') {
-				inptr++;
-				if (*(inend - 1) == ')')
-					inlen -= 2;
-				else
-					inlen--;
-			}
-			
-			for (t = 0; t < 15; t++) {
-				unsigned int len = strlen (tz_offsets[t].name);
-				
-				if (len != inlen)
-					continue;
-				
-				if (!strncmp (inptr, tz_offsets[t].name, len))
-					return tz_offsets[t].offset;
-			}
-		}
-	}
-	
-	return -1;
-}
-
-/* This is where things get interesting... ;-) */
-
-#define date_token_mask(t)  (((struct _date_token *) t)->mask)
-#define is_numeric(t)       ((date_token_mask (t) & DATE_TOKEN_NON_NUMERIC) == 0)
-#define is_weekday(t)       ((date_token_mask (t) & DATE_TOKEN_NON_WEEKDAY) == 0)
-#define is_month(t)         ((date_token_mask (t) & DATE_TOKEN_NON_MONTH) == 0)
-#define is_time(t)          (((date_token_mask (t) & DATE_TOKEN_NON_TIME) == 0) && (date_token_mask (t) & DATE_TOKEN_HAS_COLON))
-#define is_tzone_alpha(t)   ((date_token_mask (t) & DATE_TOKEN_NON_TIMEZONE_ALPHA) == 0)
-#define is_tzone_numeric(t) (((date_token_mask (t) & DATE_TOKEN_NON_TIMEZONE_NUMERIC) == 0) && (date_token_mask (t) & DATE_TOKEN_HAS_SIGN))
-#define is_tzone(t)         (is_tzone_alpha (t) || is_tzone_numeric (t))
-
-static time_t
-decode_broken_date (struct _date_token *tokens, int *tzone)
-{
-	gboolean got_wday, got_month, got_tzone;
-	int hour, min, sec, offset, n;
-	struct _date_token *token;
-	struct tm tm;
-	time_t time;
-	
-	memset ((void *) &tm, 0, sizeof (struct tm));
-	got_wday = got_month = got_tzone = FALSE;
-	offset = 0;
-	
-	token = tokens;
-	while (token) {
-		if (is_weekday (token) && !got_wday) {
-			if ((n = get_wday (token->start, token->len)) != -1) {
-				d(printf ("weekday; "));
-				got_wday = TRUE;
-				tm.tm_wday = n;
-				goto next_token;
-			}
-		}
-		
-		if (is_month (token) && !got_month) {
-			if ((n = get_month (token->start, token->len)) != -1) {
-				d(printf ("month; "));
-				got_month = TRUE;
-				tm.tm_mon = n;
-				goto next_token;
-			}
-		}
-		
-		if (is_time (token) && !tm.tm_hour && !tm.tm_min && !tm.tm_sec) {
-			if (get_time (token->start, token->len, &hour, &min, &sec)) {
-				d(printf ("time; "));
-				tm.tm_hour = hour;
-				tm.tm_min = min;
-				tm.tm_sec = sec;
-				goto next_token;
-			}
-		}
-		
-		if (is_tzone (token) && !got_tzone) {
-			struct _date_token *t = token;
-			
-			if ((n = get_tzone (&t)) != -1) {
-				d(printf ("tzone; "));
-				got_tzone = TRUE;
-				offset = n;
-				goto next_token;
-			}
-		}
-		
-		if (is_numeric (token)) {
-			if (token->len == 4 && !tm.tm_year) {
-				if ((n = get_year (token->start, token->len)) != -1) {
-					d(printf ("year; "));
-					tm.tm_year = n - 1900;
-					goto next_token;
-				}
-			} else {
-				if (!got_month && !got_wday && token->next && is_numeric (token->next)) {
-					d(printf ("mon; "));
-					n = decode_int (token->start, token->len);
-					got_month = TRUE;
-					tm.tm_mon = n - 1;
-					goto next_token;
-				} else if (!tm.tm_mday && (n = get_mday (token->start, token->len)) != -1) {
-					d(printf ("mday; "));
-					tm.tm_mday = n;
-					goto next_token;
-				} else if (!tm.tm_year) {
-					d(printf ("2-digit year; "));
-					n = get_year (token->start, token->len);
-					tm.tm_year = n - 1900;
-					goto next_token;
-				}
-			}
-		}
-		
-		d(printf ("???; "));
-		
-	next_token:
-		
-		token = token->next;
-	}
-	
-	d(printf ("\n"));
-	
-	time = e_mktime_utc (&tm);
-	
-	/* time is now GMT of the time we want, but not offset by the timezone ... */
-	
-	/* this should convert the time to the GMT equiv time */
-	time -= ((offset / 100) * 60 * 60) + (offset % 100) * 60;
-	
-	if (tzone)
-		*tzone = offset;
-	
-	return time;
-}
-
-
-/**
- * parse_broken_date:
- * @datestr: input date string
- * @saveoffset:
- *
- * Decodes the rfc822/broken date string and saves the GMT offset into
- * @saveoffset if non-NULL.
- *
- * Returns the time_t representation of the date string specified by
- * @in. If 'saveoffset' is non-NULL, the value of the timezone offset
- * will be stored.
- **/
-time_t
-parse_broken_date (const char *datestr, int *saveoffset)
-{
-	struct _date_token *token, *tokens;
-	time_t date;
-	
-	tokens = datetok (datestr);
-	
-	date = decode_broken_date (tokens, saveoffset);
-	
-	/* cleanup */
-	while (tokens) {
-		token = tokens;
-		tokens = tokens->next;
-		g_free (token);
-	}
-	
-	return date;
-}
-
-
-
-
-
-#ifdef DATETOK_STANDALONE
-
-static void
-table_init ()
-{
-	int i;
-	
-	memset (datetok_table, 0, sizeof (datetok_table));
-	
-	for (i = 0; i < 256; i++) {
-		if (!strchr (NUMERIC_CHARS, i))
-			datetok_table[i] |= DATE_TOKEN_NON_NUMERIC;
-		
-		if (!strchr (WEEKDAY_CHARS, i))
-			datetok_table[i] |= DATE_TOKEN_NON_WEEKDAY;
-		
-		if (!strchr (MONTH_CHARS, i))
-			datetok_table[i] |= DATE_TOKEN_NON_MONTH;
-		
-		if (!strchr (TIME_CHARS, i))
-			datetok_table[i] |= DATE_TOKEN_NON_TIME;
-		
-		if (!strchr (TIMEZONE_ALPHA_CHARS, i))
-			datetok_table[i] |= DATE_TOKEN_NON_TIMEZONE_ALPHA;
-		
-		if (!strchr (TIMEZONE_NUMERIC_CHARS, i))
-			datetok_table[i] |= DATE_TOKEN_NON_TIMEZONE_NUMERIC;
-		
-		if (((char) i) == ':')
-			datetok_table[i] |= DATE_TOKEN_HAS_COLON;
-		
-		if (strchr ("+-", i))
-			datetok_table[i] |= DATE_TOKEN_HAS_SIGN;
-	}
-	
-	printf ("static unsigned int datetok_table[256] = {");
-	for (i = 0; i < 256; i++) {
-		if (i % 16 == 0)
-			printf ("\n\t");
-		printf ("%3d,", datetok_table[i]);
-	}
-	printf ("\n};\n");
-}
-
-
-int main (int argc, char **argv)
-{
-	time_t date;
-	int offset;
-	
-	/*table_init ();*/
-	
-	date = parse_broken_date (argv[1], &offset);
-	printf ("%d; %d\n", date, offset);
-	
-	return 0;
-}
-
-#endif /* DATETOK_STANDALONE */
diff --git a/camel/broken-date-parser.h b/camel/broken-date-parser.h
deleted file mode 100644
index b69d7636d7..0000000000
--- a/camel/broken-date-parser.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *
- *  Copyright 2000 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- */
-
-
-#include 
-
-/* prototypes for functions dealing with broken date formats */
-
-time_t parse_broken_date (const char *datestr, int *saveoffset);
-
-
-
-
-
diff --git a/camel/camel-address.c b/camel/camel-address.c
deleted file mode 100644
index a25e9ba791..0000000000
--- a/camel/camel-address.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- *  Copyright (C) 2000 Ximian Inc.
- *
- *  Authors: Michael Zucchi 
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "camel-address.h"
-
-
-static void camel_address_class_init (CamelAddressClass *klass);
-static void camel_address_init       (CamelAddress *obj);
-static void camel_address_finalize   (CamelObject *obj);
-
-static CamelObjectClass *camel_address_parent;
-
-static void
-camel_address_class_init (CamelAddressClass *klass)
-{
-	camel_address_parent = camel_type_get_global_classfuncs (camel_object_get_type ());
-}
-
-static void
-camel_address_init (CamelAddress *obj)
-{
-	obj->addresses = g_ptr_array_new();
-}
-
-static void
-camel_address_finalize (CamelObject *obj)
-{
-	camel_address_remove((CamelAddress *)obj, -1);
-	g_ptr_array_free(((CamelAddress *)obj)->addresses, TRUE);
-}
-
-CamelType
-camel_address_get_type (void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-	
-	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register (camel_object_get_type (), "CamelAddress",
-					    sizeof (CamelAddress),
-					    sizeof (CamelAddressClass),
-					    (CamelObjectClassInitFunc) camel_address_class_init,
-					    NULL,
-					    (CamelObjectInitFunc) camel_address_init,
-					    (CamelObjectFinalizeFunc) camel_address_finalize);
-	}
-	
-	return type;
-}
-
-/**
- * camel_address_new:
- *
- * Create a new CamelAddress object.
- * 
- * Return value: A new CamelAddress widget.
- **/
-CamelAddress *
-camel_address_new (void)
-{
-	CamelAddress *new = CAMEL_ADDRESS(camel_object_new(camel_address_get_type()));
-	return new;
-}
-
-/**
- * camel_address_new_clone:
- * @in: 
- * 
- * Clone an existing address type.
- * 
- * Return value: 
- **/
-CamelAddress *
-camel_address_new_clone(const CamelAddress *in)
-{
-	CamelAddress *new = CAMEL_ADDRESS(camel_object_new(CAMEL_OBJECT_GET_TYPE(in)));
-
-	camel_address_cat(new, in);
-	return new;
-}
-
-/**
- * camel_address_length:
- * @a: 
- * 
- * Return the number of addresses stored in the address @a.
- * 
- * Return value: 
- **/
-int
-camel_address_length(CamelAddress *a)
-{
-	return a->addresses->len;
-}
-
-/**
- * camel_address_decode:
- * @a: An address.
- * @raw: Raw address description.
- * 
- * Construct a new address from a raw address field.
- * 
- * Return value: Returns the number of addresses found,
- * or -1 if the addresses could not be parsed fully.
- **/
-int
-camel_address_decode	(CamelAddress *a, const char *raw)
-{
-	g_return_val_if_fail(CAMEL_IS_ADDRESS(a), -1);
-
-	return CAMEL_ADDRESS_CLASS (CAMEL_OBJECT_GET_CLASS (a))->decode(a, raw);
-}
-
-/**
- * camel_address_encode:
- * @a: 
- * 
- * Encode an address in a format suitable for a raw header.
- * 
- * Return value: The encoded address.
- **/
-char *
-camel_address_encode	(CamelAddress *a)
-{
-	g_return_val_if_fail(CAMEL_IS_ADDRESS(a), NULL);
-
-	return CAMEL_ADDRESS_CLASS (CAMEL_OBJECT_GET_CLASS (a))->encode(a);
-}
-
-/**
- * camel_address_unformat:
- * @a: 
- * @raw: 
- * 
- * Attempt to convert a previously formatted and/or edited
- * address back into internal form.
- * 
- * Return value: -1 if it could not be parsed, or the number
- * of valid addresses found.
- **/
-int
-camel_address_unformat(CamelAddress *a, const char *raw)
-{
-	g_return_val_if_fail(CAMEL_IS_ADDRESS(a), -1);
-
-	return CAMEL_ADDRESS_CLASS (CAMEL_OBJECT_GET_CLASS (a))->unformat(a, raw);
-}
-
-/**
- * camel_address_format:
- * @a: 
- * 
- * Format an address in a format suitable for display.
- * 
- * Return value: The formatted address.
- **/
-char *
-camel_address_format	(CamelAddress *a)
-{
-	if (a == NULL)
-		return NULL;
-
-	g_return_val_if_fail(CAMEL_IS_ADDRESS(a), NULL);
-
-	return CAMEL_ADDRESS_CLASS (CAMEL_OBJECT_GET_CLASS (a))->format(a);
-}
-
-/**
- * camel_address_cat:
- * @dest: 
- * @source: 
- * 
- * Concatenate one address onto another.  The addresses must
- * be of the same type.
- * 
- * Return value: 
- **/
-int
-camel_address_cat	(CamelAddress *dest, const CamelAddress *source)
-{
-	g_return_val_if_fail(CAMEL_IS_ADDRESS(dest), -1);
-	g_return_val_if_fail(CAMEL_IS_ADDRESS(source), -1);
-
-	return CAMEL_ADDRESS_CLASS(CAMEL_OBJECT_GET_CLASS(dest))->cat(dest, source);
-}
-
-/**
- * camel_address_copy:
- * @dest: 
- * @source: 
- * 
- * Copy an address contents.
- * 
- * Return value: 
- **/
-int
-camel_address_copy	(CamelAddress *dest, const CamelAddress *source)
-{
-	g_return_val_if_fail(CAMEL_IS_ADDRESS(dest), -1);
-	g_return_val_if_fail(CAMEL_IS_ADDRESS(source), -1);
-
-	camel_address_remove(dest, -1);
-	return camel_address_cat(dest, source);
-}
-
-/**
- * camel_address_remove:
- * @a: 
- * @index: The address to remove, use -1 to remove all address.
- * 
- * Remove an address by index, or all addresses.
- **/
-void
-camel_address_remove	(CamelAddress *a, int index)
-{
-	g_return_if_fail(CAMEL_IS_ADDRESS(a));
-
-	if (index == -1) {
-		for (index=a->addresses->len; index>-1; index--)
-			CAMEL_ADDRESS_CLASS (CAMEL_OBJECT_GET_CLASS (a))->remove(a, index);
-	} else {
-		CAMEL_ADDRESS_CLASS (CAMEL_OBJECT_GET_CLASS (a))->remove(a, index);
-	}
-}
diff --git a/camel/camel-address.h b/camel/camel-address.h
deleted file mode 100644
index caf7e97755..0000000000
--- a/camel/camel-address.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *  Copyright (C) 2000 Ximian Inc.
- *
- *  Authors: Michael Zucchi 
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef _CAMEL_ADDRESS_H
-#define _CAMEL_ADDRESS_H
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include 
-#include 
-
-#define CAMEL_ADDRESS(obj)         CAMEL_CHECK_CAST (obj, camel_address_get_type (), CamelAddress)
-#define CAMEL_ADDRESS_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_address_get_type (), CamelAddressClass)
-#define CAMEL_IS_ADDRESS(obj)      CAMEL_CHECK_TYPE (obj, camel_address_get_type ())
-
-typedef struct _CamelAddressClass CamelAddressClass;
-
-struct _CamelAddress {
-	CamelObject parent;
-
-	GPtrArray *addresses;
-
-	struct _CamelAddressPrivate *priv;
-};
-
-struct _CamelAddressClass {
-	CamelObjectClass parent_class;
-
-	int   (*decode)		(CamelAddress *, const char *raw);
-	char *(*encode)		(CamelAddress *);
-
-	int   (*unformat)	(CamelAddress *, const char *raw);
-	char *(*format)		(CamelAddress *);
-
-	int   (*cat)		(CamelAddress *, const CamelAddress *);
-
-	void  (*remove)		(CamelAddress *, int index);
-};
-
-CamelType	camel_address_get_type	(void);
-CamelAddress   *camel_address_new	(void);
-CamelAddress   *camel_address_new_clone	(const CamelAddress *);
-int		camel_address_length	(CamelAddress *);
-
-int	        camel_address_decode	(CamelAddress *, const char *);
-char	       *camel_address_encode	(CamelAddress *);
-int	        camel_address_unformat	(CamelAddress *, const char *);
-char	       *camel_address_format	(CamelAddress *);
-
-int		camel_address_cat	(CamelAddress *, const CamelAddress *);
-int		camel_address_copy	(CamelAddress *, const CamelAddress *);
-
-void		camel_address_remove	(CamelAddress *, int index);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* ! _CAMEL_ADDRESS_H */
diff --git a/camel/camel-arg.c b/camel/camel-arg.c
deleted file mode 100644
index bcd79bab59..0000000000
--- a/camel/camel-arg.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- *
- *
- * Author:
- *  Michael Zucchi 
- *
- * Copyright 2002 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-#include "camel-arg.h"
-
-int camel_argv_build(CamelArgV *tv)
-{
-	register guint32 tag;
-	register int i;
-	register CamelArg *a;
-	int more = TRUE;
-
-	for (i=0;iargv[i];
-
-		if ( (tag = va_arg(tv->ap, guint32)) == 0) {
-			more = FALSE;
-			break;
-		}
-
-		a->tag = tag;
-
-		switch((tag & CAMEL_ARG_TYPE)) {
-		case CAMEL_ARG_OBJ:
-			a->ca_object = va_arg(tv->ap, void *);
-			break;
-		case CAMEL_ARG_INT:
-			a->ca_int = va_arg(tv->ap, int);
-			break;
-		case CAMEL_ARG_DBL:
-			a->ca_double = va_arg(tv->ap, double);
-			break;
-		case CAMEL_ARG_STR:
-			a->ca_str = va_arg(tv->ap, char *);
-			break;
-		case CAMEL_ARG_PTR:
-			a->ca_ptr = va_arg(tv->ap, void *);
-			break;
-		case CAMEL_ARG_BOO:
-			a->ca_int = va_arg(tv->ap, int) != 0;
-			break;
-		default:
-			printf("Error, unknown type, truncating result\n");
-			more = FALSE;
-			goto fail;
-		}
-
-	}
-fail:
-	tv->argc = i;
-
-	return more;
-}
-
-int camel_arggetv_build(CamelArgGetV *tv)
-{
-	register guint32 tag;
-	register int i;
-	register CamelArgGet *a;
-	int more = TRUE;
-
-	for (i=0;iargv[i];
-
-		if ( (tag = va_arg(tv->ap, guint32)) == 0) {
-			more = FALSE;
-			break;
-		}
-
-		a->tag = tag;
-
-		switch((tag & CAMEL_ARG_TYPE)) {
-		case CAMEL_ARG_OBJ:
-			a->ca_object = va_arg(tv->ap, void **);
-			*a->ca_object = NULL;
-			break;
-		case CAMEL_ARG_INT:
-		case CAMEL_ARG_BOO:
-			a->ca_int = va_arg(tv->ap, int *);
-			*a->ca_int = 0;
-			break;
-		case CAMEL_ARG_DBL:
-			a->ca_double = va_arg(tv->ap, double *);
-			*a->ca_double = 0.0;
-			break;
-		case CAMEL_ARG_STR:
-			a->ca_str = va_arg(tv->ap, char **);
-			*a->ca_str = NULL;
-			break;
-		case CAMEL_ARG_PTR:
-			a->ca_ptr = va_arg(tv->ap, void **);
-			*a->ca_ptr = NULL;
-			break;
-		default:
-			printf("Error, unknown type, truncating result\n");
-			more = FALSE;
-			goto fail;
-		}
-
-	}
-fail:
-	tv->argc = i;
-
-	return more;
-}
-
diff --git a/camel/camel-arg.h b/camel/camel-arg.h
deleted file mode 100644
index ebecc0f217..0000000000
--- a/camel/camel-arg.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Author:
- *  Michael Zucchi 
- *
- * Copyright 2002 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-#ifndef CAMEL_ARG_H
-#define CAMEL_ARG_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif				/* __cplusplus } */
-
-#include 
-#include 
-
-enum camel_arg_t {
-	CAMEL_ARG_END = 0,
-	CAMEL_ARG_IGNORE = 1,	/* override/ignore an arg in-place */
-
-	CAMEL_ARG_FIRST = 1024,	/* 1024 args reserved for arg system */
-
-	CAMEL_ARG_TYPE = 0xf0000000, /* type field for tags */
-	CAMEL_ARG_TAG = 0x0fffffff, /* tag field for args */
-
-	CAMEL_ARG_OBJ = 0x00000000, /* object */
-	CAMEL_ARG_INT = 0x10000000, /* int */
-	CAMEL_ARG_DBL = 0x20000000, /* double */
-	CAMEL_ARG_STR = 0x30000000, /* c string */
-	CAMEL_ARG_PTR = 0x40000000, /* ptr */
-	CAMEL_ARG_BOO = 0x50000000, /* bool */
-};
-
-typedef struct _CamelArg CamelArg;
-typedef struct _CamelArgV CamelArgV;
-
-typedef struct _CamelArgGet CamelArgGet;
-typedef struct _CamelArgGetV CamelArgGetV;
-
-struct _CamelArg {
-	guint32 tag;
-	union {
-		void *ca_object;
-		int ca_int;
-		double ca_double;
-		char *ca_str;
-		void *ca_ptr;
-	} u;
-};
-struct _CamelArgGet {
-	guint32 tag;
-	union {
-		void **ca_object;
-		int *ca_int;
-		double *ca_double;
-		char **ca_str;
-		void **ca_ptr;
-	} u;
-};
-#define ca_object u.ca_object
-#define ca_int u.ca_int
-#define ca_double u.ca_double
-#define ca_str u.ca_str
-#define ca_ptr u.ca_ptr
-
-/* maximum no of args processed at any one time, not the max of all args */
-#define CAMEL_ARGV_MAX (20)
-
-struct _CamelArgV {
-	va_list ap;
-	int argc;
-	CamelArg argv[CAMEL_ARGV_MAX];
-};
-
-struct _CamelArgGetV {
-	va_list ap;
-	int argc;
-	CamelArgGet argv[CAMEL_ARGV_MAX];
-};
-
-#define camel_argv_start(tv, last) va_start((tv)->ap, last)
-#define camel_argv_end(tv) va_end((tv)->ap)
-int camel_argv_build(CamelArgV *tv);
-int camel_arggetv_build(CamelArgGetV *tv);
-
-/* set an arg ignored */
-#define camel_argv_ignore(tv, i) ((tv)->argv[i].tag = ((tv)->argv[i].tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE)
-
-/* 'self-describing' property list */
-typedef struct _CamelProperty CamelProperty;
-
-struct _CamelProperty {
-	guint32 tag;
-	char *name;
-	char *description;
-};
-
-#ifdef __cplusplus
-}
-#endif				/* __cplusplus */
-
-#endif				/* CAMEL_ARG_H */
diff --git a/camel/camel-block-file.c b/camel/camel-block-file.c
deleted file mode 100644
index 68008502b4..0000000000
--- a/camel/camel-block-file.c
+++ /dev/null
@@ -1,1181 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2001-2003 Ximian Inc.
- *
- * Authors: Michael Zucchi 
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "e-util/e-msgport.h"
-
-#include "camel-block-file.h"
-#include "camel-file-utils.h"
-
-#define d(x) /*(printf("%s(%d):%s: ",  __FILE__, __LINE__, __PRETTY_FUNCTION__),(x))*/
-
-/* Locks must be obtained in the order defined */
-
-struct _CamelBlockFilePrivate {
-	/* We use the private structure to form our lru list from */
-	struct _CamelBlockFilePrivate *next;
-	struct _CamelBlockFilePrivate *prev;
-
-	struct _CamelBlockFile *base;
-	
-	pthread_mutex_t root_lock; /* for modifying the root block */
-	pthread_mutex_t cache_lock; /* for refcounting, flag manip, cache manip */
-	pthread_mutex_t io_lock; /* for all io ops */
-	
-	unsigned int deleted:1;
-};
-
-
-#define CAMEL_BLOCK_FILE_LOCK(kf, lock) (pthread_mutex_lock(&(kf)->priv->lock))
-#define CAMEL_BLOCK_FILE_TRYLOCK(kf, lock) (pthread_mutex_trylock(&(kf)->priv->lock))
-#define CAMEL_BLOCK_FILE_UNLOCK(kf, lock) (pthread_mutex_unlock(&(kf)->priv->lock))
-
-#define LOCK(x) pthread_mutex_lock(&x)
-#define UNLOCK(x) pthread_mutex_unlock(&x)
-
-static pthread_mutex_t block_file_lock = PTHREAD_MUTEX_INITIALIZER;
-
-/* lru cache of block files */
-static EDList block_file_list = E_DLIST_INITIALISER(block_file_list);
-/* list to store block files that are actually intialised */
-static EDList block_file_active_list = E_DLIST_INITIALISER(block_file_active_list);
-static int block_file_count = 0;
-static int block_file_threshhold = 10;
-
-#define CBF_CLASS(o) ((CamelBlockFileClass *)(((CamelObject *)o)->klass))
-
-static int sync_nolock(CamelBlockFile *bs);
-static int sync_block_nolock(CamelBlockFile *bs, CamelBlock *bl);
-
-static int
-block_file_validate_root(CamelBlockFile *bs)
-{
-	struct stat st;
-	CamelBlockRoot *br;
-	int s;
-
-	br = bs->root;
-
-	s = fstat(bs->fd, &st);
-
-	d(printf("Validate root: '%s'\n", bs->path));
-	d(printf("version: %.8s (%.8s)\n", bs->root->version, bs->version));
-	d(printf("block size: %d (%d)%s\n", br->block_size, bs->block_size,
-		br->block_size != bs->block_size ? " BAD":" OK"));
-	d(printf("free: %ld (%d add size < %ld)%s\n", (long)br->free, br->free / bs->block_size * bs->block_size, (long)st.st_size,
-		(br->free > st.st_size) || (br->free % bs->block_size) != 0 ? " BAD":" OK"));
-	d(printf("last: %ld (%d and size: %ld)%s\n", (long)br->last, br->last / bs->block_size * bs->block_size, (long)st.st_size,
-		(br->last != st.st_size) || ((br->last % bs->block_size) != 0) ? " BAD": " OK"));
-	d(printf("flags: %s\n", (br->flags & CAMEL_BLOCK_FILE_SYNC)?"SYNC":"unSYNC"));
-
-	if (br->last == 0
-	    || memcmp(bs->root->version, bs->version, 8) != 0
-	    || br->block_size != bs->block_size
-	    || (br->free % bs->block_size) != 0
-	    || (br->last % bs->block_size) != 0
-	    || fstat(bs->fd, &st) == -1
-	    || st.st_size != br->last
-	    || br->free > st.st_size
-	    || (br->flags & CAMEL_BLOCK_FILE_SYNC) == 0) {
-		if (s != -1 && st.st_size > 0) {
-			g_warning("Invalid root: '%s'", bs->path);
-			g_warning("version: %.8s (%.8s)", bs->root->version, bs->version);
-			g_warning("block size: %d (%d)%s", br->block_size, bs->block_size,
-				  br->block_size != bs->block_size ? " BAD":" OK");
-			g_warning("free: %ld (%d add size < %ld)%s", (long)br->free, br->free / bs->block_size * bs->block_size, (long)st.st_size,
-				  (br->free > st.st_size) || (br->free % bs->block_size) != 0 ? " BAD":" OK");
-			g_warning("last: %ld (%d and size: %ld)%s", (long)br->last, br->last / bs->block_size * bs->block_size, (long)st.st_size,
-				  (br->last != st.st_size) || ((br->last % bs->block_size) != 0) ? " BAD": " OK");
-			g_warning("flags: %s", (br->flags & CAMEL_BLOCK_FILE_SYNC)?"SYNC":"unSYNC");
-		}
-		return -1;
-	}
-
-	return 0;
-}
-
-static int
-block_file_init_root(CamelBlockFile *bs)
-{
-	CamelBlockRoot *br = bs->root;
-
-	memset(br, 0, bs->block_size);
-	memcpy(br->version, bs->version, 8);
-	br->last = bs->block_size;
-	br->flags = CAMEL_BLOCK_FILE_SYNC;
-	br->free = 0;
-	br->block_size = bs->block_size;
-
-	return 0;
-}
-
-static void
-camel_block_file_class_init(CamelBlockFileClass *klass)
-{
-	klass->validate_root = block_file_validate_root;
-	klass->init_root = block_file_init_root;
-}
-
-static guint
-block_hash_func(const void *v)
-{
-	return ((camel_block_t) GPOINTER_TO_UINT(v)) >> CAMEL_BLOCK_SIZE_BITS;
-}
-
-static void
-camel_block_file_init(CamelBlockFile *bs)
-{
-	struct _CamelBlockFilePrivate *p;
-
-	bs->fd = -1;
-	bs->block_size = CAMEL_BLOCK_SIZE;
-	e_dlist_init(&bs->block_cache);
-	bs->blocks = g_hash_table_new((GHashFunc)block_hash_func, NULL);
-	/* this cache size and the text index size have been tuned for about the best
-	   with moderate memory usage.  Doubling the memory usage barely affects performance. */
-	bs->block_cache_limit = 256;
-
-	p = bs->priv = g_malloc0(sizeof(*bs->priv));
-	p->base = bs;
-	
-	pthread_mutex_init(&p->root_lock, NULL);
-	pthread_mutex_init(&p->cache_lock, NULL);
-	pthread_mutex_init(&p->io_lock, NULL);
-	
-	/* link into lru list */
-	LOCK(block_file_lock);
-	e_dlist_addhead(&block_file_list, (EDListNode *)p);
-
-#if 0
-	{
-		printf("dumping block list\n");
-		printf(" head = %p p = %p\n", block_file_list.head, p);
-		p = block_file_list.head;
-		while (p->next) {
-			printf(" '%s'\n", p->base->path);
-			p = p->next;
-		}
-	}
-#endif
-
-	UNLOCK(block_file_lock);
-}
-
-static void
-camel_block_file_finalise(CamelBlockFile *bs)
-{
-	CamelBlock *bl, *bn;
-	struct _CamelBlockFilePrivate *p;
-
-	p = bs->priv;
-
-	if (bs->root_block)
-		camel_block_file_sync(bs);
-
-	/* remove from lru list */
-	LOCK(block_file_lock);
-	if (bs->fd != -1)
-		block_file_count--;
-	e_dlist_remove((EDListNode *)p);
-	UNLOCK(block_file_lock);
-
-	bl = (CamelBlock *)bs->block_cache.head;
-	bn = bl->next;
-	while (bn) {
-		if (bl->refcount != 0)
-			g_warning("Block '%d' still referenced", bl->id);
-		g_free(bl);
-		bl = bn;
-		bn = bn->next;
-	}
-	
-	g_hash_table_destroy (bs->blocks);
-	
-	if (bs->root_block)
-		camel_block_file_unref_block(bs, bs->root_block);
-	g_free(bs->path);
-	if (bs->fd != -1)
-		close(bs->fd);
-	
-	pthread_mutex_destroy(&p->io_lock);
-	pthread_mutex_destroy(&p->cache_lock);
-	pthread_mutex_destroy(&p->root_lock);
-	
-	g_free(p);
-}
-
-CamelType
-camel_block_file_get_type(void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-	
-	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register(camel_object_get_type(), "CamelBlockFile",
-					   sizeof (CamelBlockFile),
-					   sizeof (CamelBlockFileClass),
-					   (CamelObjectClassInitFunc) camel_block_file_class_init,
-					   NULL,
-					   (CamelObjectInitFunc) camel_block_file_init,
-					   (CamelObjectFinalizeFunc) camel_block_file_finalise);
-	}
-	
-	return type;
-}
-
-/* 'use' a block file for io */
-static int
-block_file_use(CamelBlockFile *bs)
-{
-	struct _CamelBlockFilePrivate *nw, *nn, *p = bs->priv;
-	CamelBlockFile *bf;
-	int err;
-
-	/* We want to:
-	    remove file from active list
-	    lock it
-
-	   Then when done:
-	    unlock it
-	    add it back to end of active list
-	*/
-
-	CAMEL_BLOCK_FILE_LOCK(bs, io_lock);
-
-	if (bs->fd != -1)
-		return 0;
-	else if (p->deleted) {
-		CAMEL_BLOCK_FILE_UNLOCK(bs, io_lock);
-		errno = ENOENT;
-		return -1;
-	} else
-		d(printf("Turning block file online: %s\n", bs->path));
-
-	if ((bs->fd = open(bs->path, bs->flags, 0600)) == -1) {
-		err = errno;
-		CAMEL_BLOCK_FILE_UNLOCK(bs, io_lock);
-		errno = err;
-		return -1;
-	}
-
-	LOCK(block_file_lock);
-	e_dlist_remove((EDListNode *)p);
-	e_dlist_addtail(&block_file_active_list, (EDListNode *)p);
-
-	block_file_count++;
-
-	nw = (struct _CamelBlockFilePrivate *)block_file_list.head;
-	nn = nw->next;
-	while (block_file_count > block_file_threshhold && nn) {
-		/* We never hit the current blockfile here, as its removed from the list first */
-		bf = nw->base;
-		if (bf->fd != -1) {
-			/* Need to trylock, as any of these lock levels might be trying
-			   to lock the block_file_lock, so we need to check and abort if so */
-			if (CAMEL_BLOCK_FILE_TRYLOCK(bf, root_lock) == 0) {
-				if (CAMEL_BLOCK_FILE_TRYLOCK(bf, cache_lock) == 0) {
-					if (CAMEL_BLOCK_FILE_TRYLOCK(bf, io_lock) == 0) {
-						d(printf("[%d] Turning block file offline: %s\n", block_file_count-1, bf->path));
-						sync_nolock(bf);
-						close(bf->fd);
-						bf->fd = -1;
-						block_file_count--;
-						CAMEL_BLOCK_FILE_UNLOCK(bf, io_lock);
-					}
-					CAMEL_BLOCK_FILE_UNLOCK(bf, cache_lock);
-				}
-				CAMEL_BLOCK_FILE_UNLOCK(bf, root_lock);
-			}
-		}
-		nw = nn;
-		nn = nw->next;
-	}
-
-	UNLOCK(block_file_lock);
-
-	return 0;
-}
-
-static void
-block_file_unuse(CamelBlockFile *bs)
-{
-	LOCK(block_file_lock);
-	e_dlist_remove((EDListNode *)bs->priv);
-	e_dlist_addtail(&block_file_list, (EDListNode *)bs->priv);
-	UNLOCK(block_file_lock);
-
-	CAMEL_BLOCK_FILE_UNLOCK(bs, io_lock);
-}
-
-/*
-o = camel_cache_get(c, key);
-camel_cache_unref(c, key);
-camel_cache_add(c, key, o);
-camel_cache_remove(c, key);
-*/
-
-/**
- * camel_block_file_new:
- * @path: 
- * @: 
- * @block_size: 
- * 
- * Allocate a new block file, stored at @path.  @version contains an 8 character
- * version string which must match the head of the file, or the file will be
- * intitialised.
- * 
- * @block_size is currently ignored and is set to CAMEL_BLOCK_SIZE.
- *
- * Return value: The new block file, or NULL if it could not be created.
- **/
-CamelBlockFile *camel_block_file_new(const char *path, int flags, const char version[8], size_t block_size)
-{
-	CamelBlockFile *bs;
-
-	bs = (CamelBlockFile *)camel_object_new(camel_block_file_get_type());
-	memcpy(bs->version, version, 8);
-	bs->path = g_strdup(path);
-	bs->flags = flags;
-
-	bs->root_block = camel_block_file_get_block(bs, 0);
-	if (bs->root_block == NULL) {
-		camel_object_unref((CamelObject *)bs);
-		return NULL;
-	}
-	camel_block_file_detach_block(bs, bs->root_block);
-	bs->root = (CamelBlockRoot *)&bs->root_block->data;
-
-	/* we only need these flags on first open */
-	bs->flags &= ~(O_CREAT|O_EXCL|O_TRUNC);
-
-	/* Do we need to init the root block? */
-	if (CBF_CLASS(bs)->validate_root(bs) == -1) {
-		d(printf("Initialise root block: %.8s\n", version));
-
-		CBF_CLASS(bs)->init_root(bs);
-		camel_block_file_touch_block(bs, bs->root_block);
-		if (block_file_use(bs) == -1) {
-			camel_object_unref((CamelObject *)bs);
-			return NULL;
-		}
-		if (sync_block_nolock(bs, bs->root_block) == -1
-		    || ftruncate(bs->fd, bs->root->last) == -1) {
-			block_file_unuse(bs);
-			camel_object_unref((CamelObject *)bs);
-			return NULL;
-		}
-		block_file_unuse(bs);
-	}
-
-	return bs;
-}
-
-int
-camel_block_file_rename(CamelBlockFile *bs, const char *path)
-{
-	int ret;
-	struct stat st;
-	int err;
-
-	CAMEL_BLOCK_FILE_LOCK(bs, io_lock);
-
-	ret = rename(bs->path, path);
-	if (ret == -1) {
-		/* Maybe the rename actually worked */
-		err = errno;
-		if (stat(path, &st) == 0
-		    && stat(bs->path, &st) == -1
-		    && errno == ENOENT)
-			ret = 0;
-		errno = err;
-	}
-
-	if (ret != -1) {
-		g_free(bs->path);
-		bs->path = g_strdup(path);
-	}
-
-	CAMEL_BLOCK_FILE_UNLOCK(bs, io_lock);
-
-	return ret;
-}
-
-int
-camel_block_file_delete(CamelBlockFile *bs)
-{
-	int ret;
-	struct _CamelBlockFilePrivate *p = bs->priv;
-
-	CAMEL_BLOCK_FILE_LOCK(bs, io_lock);
-
-	if (bs->fd != -1) {
-		LOCK(block_file_lock);
-		block_file_count--;
-		UNLOCK(block_file_lock);
-		close(bs->fd);
-		bs->fd = -1;
-	}
-
-	p->deleted = TRUE;
-	ret = unlink(bs->path);
-
-	CAMEL_BLOCK_FILE_UNLOCK(bs, io_lock);
-
-	return ret;
-	
-}
-
-/**
- * camel_block_file_new_block:
- * @bs: 
- * 
- * Allocate a new block, return a pointer to it.  Old blocks
- * may be flushed to disk during this call.
- * 
- * Return value: The block, or NULL if an error occured.
- **/
-CamelBlock *camel_block_file_new_block(CamelBlockFile *bs)
-{
-	CamelBlock *bl;
-
-	CAMEL_BLOCK_FILE_LOCK(bs, root_lock);
-
-	if (bs->root->free) {
-		bl = camel_block_file_get_block(bs, bs->root->free);
-		if (bl == NULL)
-			goto fail;
-		bs->root->free = ((camel_block_t *)bl->data)[0];
-	} else {
-		bl = camel_block_file_get_block(bs, bs->root->last);
-		if (bl == NULL)
-			goto fail;
-		bs->root->last += CAMEL_BLOCK_SIZE;
-	}
-
-	bs->root_block->flags |= CAMEL_BLOCK_DIRTY;
-
-	bl->flags |= CAMEL_BLOCK_DIRTY;
-	memset(bl->data, 0, CAMEL_BLOCK_SIZE);
-fail:
-	CAMEL_BLOCK_FILE_UNLOCK(bs, root_lock);
-
-	return bl;
-}
-
-/**
- * camel_block_file_free_block:
- * @bs: 
- * @id: 
- * 
- * 
- **/
-int camel_block_file_free_block(CamelBlockFile *bs, camel_block_t id)
-{
-	CamelBlock *bl;
-
-	bl = camel_block_file_get_block(bs, id);
-	if (bl == NULL)
-		return -1;
-
-	CAMEL_BLOCK_FILE_LOCK(bs, root_lock);
-
-	((camel_block_t *)bl->data)[0] = bs->root->free;
-	bs->root->free = bl->id;
-	bs->root_block->flags |= CAMEL_BLOCK_DIRTY;
-	bl->flags |= CAMEL_BLOCK_DIRTY;
-	camel_block_file_unref_block(bs, bl);
-
-	CAMEL_BLOCK_FILE_UNLOCK(bs, root_lock);
-
-	return 0;
-}
-
-/**
- * camel_block_file_get_block:
- * @bs: 
- * @id: 
- * 
- * Retreive a block @id.
- * 
- * Return value: The block, or NULL if blockid is invalid or a file error
- * occured.
- **/
-CamelBlock *camel_block_file_get_block(CamelBlockFile *bs, camel_block_t id)
-{
-	CamelBlock *bl, *flush, *prev;
-
-	/* Sanity check: Dont allow reading of root block (except before its been read)
-	   or blocks with invalid block id's */
-	if ((bs->root == NULL && id != 0)
-	    || (bs->root != NULL && (id > bs->root->last || id == 0))
-	    || (id % bs->block_size) != 0) {
-		errno = EINVAL;
-		return NULL;
-	}
-
-	CAMEL_BLOCK_FILE_LOCK(bs, cache_lock);
-
-	bl = g_hash_table_lookup(bs->blocks, GUINT_TO_POINTER(id));
-
-	d(printf("Get  block %08x: %s\n", id, bl?"cached":"must read"));
-
-	if (bl == NULL) {
-		/* LOCK io_lock */
-		if (block_file_use(bs) == -1) {
-			CAMEL_BLOCK_FILE_UNLOCK(bs, cache_lock);
-			return NULL;
-		}
-
-		bl = g_malloc0(sizeof(*bl));
-		bl->id = id;
-		if (lseek(bs->fd, id, SEEK_SET) == -1 ||
-		    camel_read (bs->fd, bl->data, CAMEL_BLOCK_SIZE) == -1) {
-			block_file_unuse(bs);
-			CAMEL_BLOCK_FILE_UNLOCK(bs, cache_lock);
-			g_free(bl);
-			return NULL;
-		}
-
-		bs->block_cache_count++;
-		g_hash_table_insert(bs->blocks, GUINT_TO_POINTER(bl->id), bl);
-
-		/* flush old blocks */
-		flush = (CamelBlock *)bs->block_cache.tailpred;
-		prev = flush->prev;
-		while (bs->block_cache_count > bs->block_cache_limit && prev) {
-			if (flush->refcount == 0) {
-				if (sync_block_nolock(bs, flush) != -1) {
-					g_hash_table_remove(bs->blocks, GUINT_TO_POINTER(flush->id));
-					e_dlist_remove((EDListNode *)flush);
-					g_free(flush);
-					bs->block_cache_count--;
-				}
-			}
-			flush = prev;
-			prev = prev->prev;
-		}
-		/* UNLOCK io_lock */
-		block_file_unuse(bs);
-	} else {
-		e_dlist_remove((EDListNode *)bl);
-	}
-
-	e_dlist_addhead(&bs->block_cache, (EDListNode *)bl);
-	bl->refcount++;
-
-	CAMEL_BLOCK_FILE_UNLOCK(bs, cache_lock);
-
-	d(printf("Got  block %08x\n", id));
-
-	return bl;
-}
-
-/**
- * camel_block_file_detach_block:
- * @bs: 
- * @bl: 
- * 
- * Detatch a block from the block file's cache.  The block should
- * be unref'd or attached when finished with.  The block file will
- * perform no writes of this block or flushing of it if the cache
- * fills.
- **/
-void camel_block_file_detach_block(CamelBlockFile *bs, CamelBlock *bl)
-{
-	CAMEL_BLOCK_FILE_LOCK(bs, cache_lock);
-
-	g_hash_table_remove(bs->blocks, GUINT_TO_POINTER(bl->id));
-	e_dlist_remove((EDListNode *)bl);
-	bl->flags |= CAMEL_BLOCK_DETACHED;
-
-	CAMEL_BLOCK_FILE_UNLOCK(bs, cache_lock);
-}
-
-/**
- * camel_block_file_attach_block:
- * @bs: 
- * @bl: 
- * 
- * Reattach a block that has been detached.
- **/
-void camel_block_file_attach_block(CamelBlockFile *bs, CamelBlock *bl)
-{
-	CAMEL_BLOCK_FILE_LOCK(bs, cache_lock);
-
-	g_hash_table_insert(bs->blocks, GUINT_TO_POINTER(bl->id), bl);
-	e_dlist_addtail(&bs->block_cache, (EDListNode *)bl);
-	bl->flags &= ~CAMEL_BLOCK_DETACHED;
-
-	CAMEL_BLOCK_FILE_UNLOCK(bs, cache_lock);
-}
-
-/**
- * camel_block_file_touch_block:
- * @bs: 
- * @bl: 
- * 
- * Mark a block as dirty.  The block will be written to disk if
- * it ever expires from the cache.
- **/
-void camel_block_file_touch_block(CamelBlockFile *bs, CamelBlock *bl)
-{
-	CAMEL_BLOCK_FILE_LOCK(bs, root_lock);
-	CAMEL_BLOCK_FILE_LOCK(bs, cache_lock);
-
-	bl->flags |= CAMEL_BLOCK_DIRTY;
-
-	if ((bs->root->flags & CAMEL_BLOCK_FILE_SYNC) && bl != bs->root_block) {
-		d(printf("turning off sync flag\n"));
-		bs->root->flags &= ~CAMEL_BLOCK_FILE_SYNC;
-		bs->root_block->flags |= CAMEL_BLOCK_DIRTY;
-		camel_block_file_sync_block(bs, bs->root_block);
-	}
-
-	CAMEL_BLOCK_FILE_UNLOCK(bs, cache_lock);
-	CAMEL_BLOCK_FILE_UNLOCK(bs, root_lock);
-}
-
-/**
- * camel_block_file_unref_block:
- * @bs: 
- * @bl: 
- * 
- * Mark a block as unused.  If a block is used it will not be
- * written to disk, or flushed from memory.
- *
- * If a block is detatched and this is the last reference, the
- * block will be freed.
- **/
-void camel_block_file_unref_block(CamelBlockFile *bs, CamelBlock *bl)
-{
-	CAMEL_BLOCK_FILE_LOCK(bs, cache_lock);
-
-	if (bl->refcount == 1 && (bl->flags & CAMEL_BLOCK_DETACHED))
-		g_free(bl);
-	else
-		bl->refcount--;
-
-	CAMEL_BLOCK_FILE_UNLOCK(bs, cache_lock);
-}
-
-static int
-sync_block_nolock(CamelBlockFile *bs, CamelBlock *bl)
-{
-	d(printf("Sync block %08x: %s\n", bl->id, (bl->flags & CAMEL_BLOCK_DIRTY)?"dirty":"clean"));
-
-	if (bl->flags & CAMEL_BLOCK_DIRTY) {
-		if (lseek(bs->fd, bl->id, SEEK_SET) == -1
-		    || write(bs->fd, bl->data, CAMEL_BLOCK_SIZE) != CAMEL_BLOCK_SIZE) {
-			return -1;
-		}
-		bl->flags &= ~CAMEL_BLOCK_DIRTY;
-	}
-
-	return 0;
-}
-
-static int
-sync_nolock(CamelBlockFile *bs)
-{
-	CamelBlock *bl, *bn;
-	int work = FALSE;
-
-	bl = (CamelBlock *)bs->block_cache.head;
-	bn = bl->next;
-	while (bn) {
-		if (bl->flags & CAMEL_BLOCK_DIRTY) {
-			work = TRUE;
-			if (sync_block_nolock(bs, bl) == -1)
-				return -1;
-		}
-		bl = bn;
-		bn = bn->next;
-	}
-
-	if (!work
-	    && (bs->root_block->flags & CAMEL_BLOCK_DIRTY) == 0
-	    && (bs->root->flags & CAMEL_BLOCK_FILE_SYNC) != 0)
-		return 0;
-
-	d(printf("turning on sync flag\n"));
-
-	bs->root->flags |= CAMEL_BLOCK_FILE_SYNC;
-	bs->root_block->flags |= CAMEL_BLOCK_DIRTY;
-
-	return sync_block_nolock(bs, bs->root_block);
-}
-
-/**
- * camel_block_file_sync_block:
- * @bs: 
- * @bl: 
- * 
- * Flush a block to disk immediately.  The block will only
- * be flushed to disk if it is marked as dirty (touched).
- * 
- * Return value: -1 on io error.
- **/
-int camel_block_file_sync_block(CamelBlockFile *bs, CamelBlock *bl)
-{
-	int ret;
-
-	/* LOCK io_lock */
-	if (block_file_use(bs) == -1)
-		return -1;
-
-	ret = sync_block_nolock(bs, bl);
-
-	block_file_unuse(bs);
-
-	return ret;
-}
-
-/**
- * camel_block_file_sync:
- * @bs: 
- * 
- * Sync all dirty blocks to disk, including the root block.
- * 
- * Return value: -1 on io error.
- **/
-int camel_block_file_sync(CamelBlockFile *bs)
-{
-	int ret;
-
-	CAMEL_BLOCK_FILE_LOCK(bs, root_lock);
-	CAMEL_BLOCK_FILE_LOCK(bs, cache_lock);
-
-	/* LOCK io_lock */
-	if (block_file_use(bs) == -1)
-		ret = -1;
-	else {
-		ret = sync_nolock(bs);
-		block_file_unuse(bs);
-	}
-
-	CAMEL_BLOCK_FILE_UNLOCK(bs, cache_lock);
-	CAMEL_BLOCK_FILE_UNLOCK(bs, root_lock);
-
-	return ret;
-}
-
-/* ********************************************************************** */
-
-struct _CamelKeyFilePrivate {
-	struct _CamelKeyFilePrivate *next;
-	struct _CamelKeyFilePrivate *prev;
-
-	struct _CamelKeyFile *base;
-	pthread_mutex_t lock;
-	unsigned int deleted:1;
-};
-
-#define CAMEL_KEY_FILE_LOCK(kf, lock) (pthread_mutex_lock(&(kf)->priv->lock))
-#define CAMEL_KEY_FILE_TRYLOCK(kf, lock) (pthread_mutex_trylock(&(kf)->priv->lock))
-#define CAMEL_KEY_FILE_UNLOCK(kf, lock) (pthread_mutex_unlock(&(kf)->priv->lock))
-
-static pthread_mutex_t key_file_lock = PTHREAD_MUTEX_INITIALIZER;
-
-/* lru cache of block files */
-static EDList key_file_list = E_DLIST_INITIALISER(key_file_list);
-static EDList key_file_active_list = E_DLIST_INITIALISER(key_file_active_list);
-static int key_file_count = 0;
-static int key_file_threshhold = 10;
-
-static void
-camel_key_file_class_init(CamelKeyFileClass *klass)
-{
-}
-
-static void
-camel_key_file_init(CamelKeyFile *bs)
-{
-	struct _CamelKeyFilePrivate *p;
-
-	p = bs->priv = g_malloc0(sizeof(*bs->priv));
-	p->base = bs;
-	
-	pthread_mutex_init(&p->lock, NULL);
-	
-	LOCK(key_file_lock);
-	e_dlist_addhead(&key_file_list, (EDListNode *)p);
-	UNLOCK(key_file_lock);
-}
-
-static void
-camel_key_file_finalise(CamelKeyFile *bs)
-{
-	struct _CamelKeyFilePrivate *p = bs->priv;
-
-	LOCK(key_file_lock);
-	e_dlist_remove((EDListNode *)p);
-
-	if (bs-> fp) {
-		key_file_count--;
-		fclose(bs->fp);
-	}
-
-	UNLOCK(key_file_lock);
-
-	g_free(bs->path);
-	
-	pthread_mutex_destroy(&p->lock);
-	
-	g_free(p);
-}
-
-CamelType
-camel_key_file_get_type(void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-	
-	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register(camel_object_get_type(), "CamelKeyFile",
-					   sizeof (CamelKeyFile),
-					   sizeof (CamelKeyFileClass),
-					   (CamelObjectClassInitFunc) camel_key_file_class_init,
-					   NULL,
-					   (CamelObjectInitFunc) camel_key_file_init,
-					   (CamelObjectFinalizeFunc) camel_key_file_finalise);
-	}
-	
-	return type;
-}
-
-/* 'use' a key file for io */
-static int
-key_file_use(CamelKeyFile *bs)
-{
-	struct _CamelKeyFilePrivate *nw, *nn, *p = bs->priv;
-	CamelKeyFile *bf;
-	int err, fd;
-	char *flag;
-
-	/* We want to:
-	    remove file from active list
-	    lock it
-
-	   Then when done:
-	    unlock it
-	    add it back to end of active list
-	*/
-
-	/* TODO: Check header on reset? */
-
-	CAMEL_KEY_FILE_LOCK(bs, lock);
-
-	if (bs->fp != NULL)
-		return 0;
-	else if (p->deleted) {
-		CAMEL_KEY_FILE_UNLOCK(bs, lock);
-		errno = ENOENT;
-		return -1;
-	} else
-		d(printf("Turning key file online: '%s'\n", bs->path));
-
-	if ((bs->flags & O_ACCMODE) == O_RDONLY)
-		flag = "r";
-	else
-		flag = "a+";
-
-	if ((fd = open(bs->path, bs->flags, 0600)) == -1
-	    || (bs->fp = fdopen(fd, flag)) == NULL) {
-		err = errno;
-		close(fd);
-		CAMEL_KEY_FILE_UNLOCK(bs, lock);
-		errno = err;
-		return -1;
-	}
-
-	LOCK(key_file_lock);
-	e_dlist_remove((EDListNode *)p);
-	e_dlist_addtail(&key_file_active_list, (EDListNode *)p);
-
-	key_file_count++;
-
-	nw = (struct _CamelKeyFilePrivate *)key_file_list.head;
-	nn = nw->next;
-	while (key_file_count > key_file_threshhold && nn) {
-		/* We never hit the current keyfile here, as its removed from the list first */
-		bf = nw->base;
-		if (bf->fp != NULL) {
-			/* Need to trylock, as any of these lock levels might be trying
-			   to lock the key_file_lock, so we need to check and abort if so */
-			if (CAMEL_BLOCK_FILE_TRYLOCK(bf, lock) == 0) {
-				d(printf("Turning key file offline: %s\n", bf->path));
-				fclose(bf->fp);
-				bf->fp = NULL;
-				key_file_count--;
-				CAMEL_BLOCK_FILE_UNLOCK(bf, lock);
-			}
-		}
-		nw = nn;
-		nn = nw->next;
-	}
-
-	UNLOCK(key_file_lock);
-
-	return 0;
-}
-
-static void
-key_file_unuse(CamelKeyFile *bs)
-{
-	LOCK(key_file_lock);
-	e_dlist_remove((EDListNode *)bs->priv);
-	e_dlist_addtail(&key_file_list, (EDListNode *)bs->priv);
-	UNLOCK(key_file_lock);
-
-	CAMEL_KEY_FILE_UNLOCK(bs, lock);
-}
-
-/**
- * camel_key_file_new:
- * @path: 
- * @flags: open flags
- * @version[]: Version string (header) of file.  Currently
- * written but not checked.
- * 
- * Create a new key file.  A linked list of record blocks.
- * 
- * Return value: A new key file, or NULL if the file could not
- * be opened/created/initialised.
- **/
-CamelKeyFile *
-camel_key_file_new(const char *path, int flags, const char version[8])
-{
-	CamelKeyFile *kf;
-	off_t last;
-	int err;
-
-	d(printf("New key file '%s'\n", path));
-
-	kf = (CamelKeyFile *)camel_object_new(camel_key_file_get_type());
-	kf->path = g_strdup(path);
-	kf->fp = NULL;
-	kf->flags = flags;
-	kf->last = 8;
-
-	if (key_file_use(kf) == -1) {
-		camel_object_unref((CamelObject *)kf);
-		kf = NULL;
-	} else {
-		fseek(kf->fp, 0, SEEK_END);
-		last = ftell(kf->fp);
-		if (last == 0) {
-			fwrite(version, 8, 1, kf->fp);
-			last += 8;
-		}
-		kf->last = last;
-
-		err = ferror(kf->fp);
-		key_file_unuse(kf);
-
-		/* we only need these flags on first open */
-		kf->flags &= ~(O_CREAT|O_EXCL|O_TRUNC);
-
-		if (err) {
-			camel_object_unref((CamelObject *)kf);
-			kf = NULL;
-		}
-	}
-
-	return kf;
-}
-
-int
-camel_key_file_rename(CamelKeyFile *kf, const char *path)
-{
-	int ret;
-	struct stat st;
-	int err;
-
-	CAMEL_KEY_FILE_LOCK(kf, lock);
-
-	ret = rename(kf->path, path);
-	if (ret == -1) {
-		/* Maybe the rename actually worked */
-		err = errno;
-		if (stat(path, &st) == 0
-		    && stat(kf->path, &st) == -1
-		    && errno == ENOENT)
-			ret = 0;
-		errno = err;
-	}
-
-	if (ret != -1) {
-		g_free(kf->path);
-		kf->path = g_strdup(path);
-	}
-
-	CAMEL_KEY_FILE_UNLOCK(kf, lock);
-
-	return ret;
-}
-
-int
-camel_key_file_delete(CamelKeyFile *kf)
-{
-	int ret;
-	struct _CamelKeyFilePrivate *p = kf->priv;
-
-	CAMEL_KEY_FILE_LOCK(kf, lock);
-
-	if (kf->fp) {
-		LOCK(key_file_lock);
-		key_file_count--;
-		UNLOCK(key_file_lock);
-		fclose(kf->fp);
-		kf->fp = NULL;
-	}
-
-	p->deleted = TRUE;
-	ret = unlink(kf->path);
-
-	CAMEL_KEY_FILE_UNLOCK(kf, lock);
-
-	return ret;
-	
-}
-
-/**
- * camel_key_file_write:
- * @kf: 
- * @parent: 
- * @len: 
- * @records: 
- * 
- * Write a new list of records to the key file.
- * 
- * Return value: -1 on io error.  The key file will remain unchanged.
- **/
-int
-camel_key_file_write(CamelKeyFile *kf, camel_block_t *parent, size_t len, camel_key_t *records)
-{
-	camel_block_t next;
-	guint32 size;
-	int ret = -1;
-
-	d(printf("write key %08x len = %d\n", *parent, len));
-
-	if (len == 0) {
-		d(printf(" new parent = %08x\n", *parent));
-		return 0;
-	}
-
-	/* LOCK */
-	if (key_file_use(kf) == -1)
-		return -1;
-
-	size = len;
-
-	/* FIXME: Use io util functions? */
-	next = kf->last;
-	fseek(kf->fp, kf->last, SEEK_SET);
-	fwrite(parent, sizeof(*parent), 1, kf->fp);
-	fwrite(&size, sizeof(size), 1, kf->fp);
-	fwrite(records, sizeof(records[0]), len, kf->fp);
-
-	if (ferror(kf->fp)) {
-		clearerr(kf->fp);
-	} else {
-		kf->last = ftell(kf->fp);
-		*parent = next;
-		ret = len;
-	}
-
-	/* UNLOCK */
-	key_file_unuse(kf);
-
-	d(printf(" new parent = %08x\n", *parent));
-
-	return ret;
-}
-
-/**
- * camel_key_file_read:
- * @kf: 
- * @start: The record pointer.  This will be set to the next record pointer on success.
- * @len: Number of records read, if != NULL.
- * @records: Records, allocated, must be freed with g_free, if != NULL.
- * 
- * Read the next block of data from the key file.  Returns the number of
- * records.
- * 
- * Return value: -1 on io error.
- **/
-int
-camel_key_file_read(CamelKeyFile *kf, camel_block_t *start, size_t *len, camel_key_t **records)
-{
-	guint32 size;
-	long pos = *start;
-	camel_block_t next;
-	int ret = -1;
-
-	if (pos == 0)
-		return 0;
-
-	/* LOCK */
-	if (key_file_use(kf) == -1)
-		return -1;
-
-	if (fseek(kf->fp, pos, SEEK_SET) == -1
-	    || fread(&next, sizeof(next), 1, kf->fp) != 1
-	    || fread(&size, sizeof(size), 1, kf->fp) != 1
-	    || size > 1024) {
-		clearerr(kf->fp);
-		goto fail;
-	}
-
-	if (len)
-		*len = size;
-
-	if (records) {
-		camel_key_t *keys = g_malloc(size * sizeof(camel_key_t));
-
-		if (fread(keys, sizeof(camel_key_t), size, kf->fp) != size) {
-			g_free(keys);
-			goto fail;
-		}
-		*records = keys;
-	}
-
-	*start = next;
-
-	ret = 0;
-fail:
-	/* UNLOCK */
-	key_file_unuse(kf);
-
-	return ret;
-}
diff --git a/camel/camel-block-file.h b/camel/camel-block-file.h
deleted file mode 100644
index eec0ee26f9..0000000000
--- a/camel/camel-block-file.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2001 Ximian Inc.
- *
- * Authors: Michael Zucchi 
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef _CAMEL_BLOCK_FILE_H
-#define _CAMEL_BLOCK_FILE_H
-
-#include 
-#include 
-#include 
-#include 
-
-typedef guint32 camel_block_t;	/* block offset, absolute, bottom BLOCK_SIZE_BITS always 0 */
-typedef guint32 camel_key_t;	/* this is a bitfield of (block offset:BLOCK_SIZE_BITS) */
-
-typedef struct _CamelBlockRoot CamelBlockRoot;
-typedef struct _CamelBlock CamelBlock;
-typedef struct _CamelBlockFile CamelBlockFile;
-typedef struct _CamelBlockFileClass CamelBlockFileClass;
-
-#define CAMEL_BLOCK_FILE_SYNC (1<<0)
-
-#define CAMEL_BLOCK_SIZE (1024)
-#define CAMEL_BLOCK_SIZE_BITS (10) /* # bits to contain block_size bytes */
-
-#define CAMEL_BLOCK_DIRTY (1<<0)
-#define CAMEL_BLOCK_DETACHED (1<<1)
-
-struct _CamelBlockRoot {
-	char version[8];	/* version number */
-
-	guint32 flags;		/* flags for file */
-	guint32 block_size;	/* block size of this file */
-	camel_block_t free;	/* free block list */
-	camel_block_t last;	/* pointer to end of blocks */
-
-	/* subclasses tack on, but no more than CAMEL_BLOCK_SIZE! */
-};
-
-/* LRU cache of blocks */
-struct _CamelBlock {
-	struct _CamelBlock *next;
-	struct _CamelBlock *prev;
-
-	camel_block_t id;
-	guint32 flags;
-	guint32 refcount;
-	guint32 align00;
-
-	unsigned char data[CAMEL_BLOCK_SIZE];
-};
-
-struct _CamelBlockFile {
-	CamelObject parent;
-
-	struct _CamelBlockFilePrivate *priv;
-
-	char version[8];
-	char *path;
-	int flags;
-
-	int fd;
-	size_t block_size;
-
-	CamelBlockRoot *root;
-	CamelBlock *root_block;
-
-	/* make private? */
-	int block_cache_limit;
-	int block_cache_count;
-	EDList block_cache;
-	GHashTable *blocks;
-};
-
-struct _CamelBlockFileClass {
-	CamelObjectClass parent;
-
-	int (*validate_root)(CamelBlockFile *);
-	int (*init_root)(CamelBlockFile *);
-};
-
-CamelType camel_block_file_get_type(void);
-
-CamelBlockFile *camel_block_file_new(const char *path, int flags, const char version[8], size_t block_size);
-int camel_block_file_rename(CamelBlockFile *bs, const char *path);
-int camel_block_file_delete(CamelBlockFile *kf);
-
-CamelBlock *camel_block_file_new_block(CamelBlockFile *bs);
-int camel_block_file_free_block(CamelBlockFile *bs, camel_block_t id);
-CamelBlock *camel_block_file_get_block(CamelBlockFile *bs, camel_block_t id);
-void camel_block_file_detach_block(CamelBlockFile *bs, CamelBlock *bl);
-void camel_block_file_attach_block(CamelBlockFile *bs, CamelBlock *bl);
-void camel_block_file_touch_block(CamelBlockFile *bs, CamelBlock *bl);
-void camel_block_file_unref_block(CamelBlockFile *bs, CamelBlock *bl);
-int camel_block_file_sync_block(CamelBlockFile *bs, CamelBlock *bl);
-int camel_block_file_sync(CamelBlockFile *bs);
-
-/* ********************************************************************** */
-
-typedef struct _CamelKeyFile CamelKeyFile;
-typedef struct _CamelKeyFileClass CamelKeyFileClass;
-
-struct _CamelKeyFile {
-	CamelObject parent;
-
-	struct _CamelKeyFilePrivate *priv;
-
-	FILE *fp;
-	char *path;
-	int flags;
-	off_t last;
-};
-
-struct _CamelKeyFileClass {
-	CamelObjectClass parent;
-};
-
-CamelType      camel_key_file_get_type(void);
-
-CamelKeyFile * camel_key_file_new(const char *path, int flags, const char version[8]);
-int	       camel_key_file_rename(CamelKeyFile *kf, const char *path);
-int	       camel_key_file_delete(CamelKeyFile *kf);
-
-int            camel_key_file_write(CamelKeyFile *kf, camel_block_t *parent, size_t len, camel_key_t *records);
-int            camel_key_file_read(CamelKeyFile *kf, camel_block_t *start, size_t *len, camel_key_t **records);
-
-
-#endif /* ! _CAMEL_BLOCK_FILE_H */
diff --git a/camel/camel-certdb.c b/camel/camel-certdb.c
deleted file mode 100644
index 8df6f2e578..0000000000
--- a/camel/camel-certdb.c
+++ /dev/null
@@ -1,665 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *
- *  Copyright 2002-2003 Ximian, Inc. (www.ximian.com)
- *
- *  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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "camel-certdb.h"
-#include "camel-private.h"
-
-#include 
-
-#include 
-
-
-#define CAMEL_CERTDB_GET_CLASS(db)  ((CamelCertDBClass *) CAMEL_OBJECT_GET_CLASS (db))
-
-#define CAMEL_CERTDB_VERSION  0x100
-
-static void camel_certdb_class_init (CamelCertDBClass *klass);
-static void camel_certdb_init       (CamelCertDB *certdb);
-static void camel_certdb_finalize   (CamelObject *obj);
-
-static int certdb_header_load (CamelCertDB *certdb, FILE *istream);
-static int certdb_header_save (CamelCertDB *certdb, FILE *ostream);
-static CamelCert *certdb_cert_load (CamelCertDB *certdb, FILE *istream);
-static int certdb_cert_save (CamelCertDB *certdb, CamelCert *cert, FILE *ostream);
-static CamelCert *certdb_cert_new (CamelCertDB *certdb);
-static void certdb_cert_free (CamelCertDB *certdb, CamelCert *cert);
-
-static const char *cert_get_string (CamelCertDB *certdb, CamelCert *cert, int string);
-static void cert_set_string (CamelCertDB *certdb, CamelCert *cert, int string, const char *value);
-
-
-static CamelObjectClass *parent_class = NULL;
-
-
-CamelType
-camel_certdb_get_type (void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-	
-	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register (camel_object_get_type (),
-					    "CamelCertDB",
-					    sizeof (CamelCertDB),
-					    sizeof (CamelCertDBClass),
-					    (CamelObjectClassInitFunc) camel_certdb_class_init,
-					    NULL,
-					    (CamelObjectInitFunc) camel_certdb_init,
-					    (CamelObjectFinalizeFunc) camel_certdb_finalize);
-	}
-	
-	return type;
-}
-
-
-static void
-camel_certdb_class_init (CamelCertDBClass *klass)
-{
-	parent_class = camel_type_get_global_classfuncs (camel_object_get_type ());
-	
-	klass->header_load = certdb_header_load;
-	klass->header_save = certdb_header_save;
-	
-	klass->cert_new  = certdb_cert_new;
-	klass->cert_load = certdb_cert_load;
-	klass->cert_save = certdb_cert_save;
-	klass->cert_free = certdb_cert_free;
-	klass->cert_get_string = cert_get_string;
-	klass->cert_set_string = cert_set_string;
-}
-
-static void
-camel_certdb_init (CamelCertDB *certdb)
-{
-	certdb->priv = g_malloc (sizeof (struct _CamelCertDBPrivate));
-	
-	certdb->filename = NULL;
-	certdb->version = CAMEL_CERTDB_VERSION;
-	certdb->saved_certs = 0;
-	
-	certdb->cert_size = sizeof (CamelCert);
-	
-	certdb->cert_chunks = NULL;
-	
-	certdb->certs = g_ptr_array_new ();
-	certdb->cert_hash = g_hash_table_new (g_str_hash, g_str_equal);
-	
-	certdb->priv->db_lock = g_mutex_new ();
-	certdb->priv->io_lock = g_mutex_new ();
-	certdb->priv->alloc_lock = g_mutex_new ();
-	certdb->priv->ref_lock = g_mutex_new ();
-}
-
-static void
-camel_certdb_finalize (CamelObject *obj)
-{
-	CamelCertDB *certdb = (CamelCertDB *) obj;
-	struct _CamelCertDBPrivate *p;
-	
-	p = certdb->priv;
-	
-	if (certdb->flags & CAMEL_CERTDB_DIRTY)
-		camel_certdb_save (certdb);
-	
-	camel_certdb_clear (certdb);
-	g_ptr_array_free (certdb->certs, TRUE);
-	g_hash_table_destroy (certdb->cert_hash);
-	
-	g_free (certdb->filename);
-	
-	if (certdb->cert_chunks)
-		e_memchunk_destroy (certdb->cert_chunks);
-	
-	g_mutex_free (p->db_lock);
-	g_mutex_free (p->io_lock);
-	g_mutex_free (p->alloc_lock);
-	g_mutex_free (p->ref_lock);
-	
-	g_free (p);
-}
-
-
-CamelCertDB *
-camel_certdb_new (void)
-{
-	return (CamelCertDB *) camel_object_new (camel_certdb_get_type ());
-}
-
-
-static CamelCertDB *default_certdb = NULL;
-static pthread_mutex_t default_certdb_lock = PTHREAD_MUTEX_INITIALIZER;
-
-
-void
-camel_certdb_set_default (CamelCertDB *certdb)
-{
-	pthread_mutex_lock (&default_certdb_lock);
-	
-	if (default_certdb)
-		camel_object_unref (default_certdb);
-	
-	if (certdb)
-		camel_object_ref (certdb);
-	
-	default_certdb = certdb;
-	
-	pthread_mutex_unlock (&default_certdb_lock);
-}
-
-
-CamelCertDB *
-camel_certdb_get_default (void)
-{
-	CamelCertDB *certdb;
-	
-	pthread_mutex_lock (&default_certdb_lock);
-	
-	if (default_certdb)
-		camel_object_ref (default_certdb);
-	
-	certdb = default_certdb;
-	
-	pthread_mutex_unlock (&default_certdb_lock);
-	
-	return certdb;
-}
-
-
-void
-camel_certdb_set_filename (CamelCertDB *certdb, const char *filename)
-{
-	g_return_if_fail (CAMEL_IS_CERTDB (certdb));
-	g_return_if_fail (filename != NULL);
-	
-	CAMEL_CERTDB_LOCK (certdb, db_lock);
-	
-	g_free (certdb->filename);
-	certdb->filename = g_strdup (filename);
-	
-	CAMEL_CERTDB_UNLOCK (certdb, db_lock);
-}
-
-
-static int
-certdb_header_load (CamelCertDB *certdb, FILE *istream)
-{
-	if (camel_file_util_decode_uint32 (istream, &certdb->version) == -1)
-		return -1;
-	if (camel_file_util_decode_uint32 (istream, &certdb->saved_certs) == -1)
-		return -1;
-	
-	return 0;
-}
-
-static CamelCert *
-certdb_cert_load (CamelCertDB *certdb, FILE *istream)
-{
-	CamelCert *cert;
-	
-	cert = camel_certdb_cert_new (certdb);
-
-	if (camel_file_util_decode_string (istream, &cert->issuer) == -1)
-		goto error;
-	if (camel_file_util_decode_string (istream, &cert->subject) == -1)
-		goto error;
-	if (camel_file_util_decode_string (istream, &cert->hostname) == -1)
-		goto error;
-	if (camel_file_util_decode_string (istream, &cert->fingerprint) == -1)
-		goto error;
-	if (camel_file_util_decode_uint32 (istream, &cert->trust) == -1)
-		goto error;
-	
-	return cert;
-	
- error:
-	
-	camel_certdb_cert_unref (certdb, cert);
-	
-	return NULL;
-}
-
-int
-camel_certdb_load (CamelCertDB *certdb)
-{
-	CamelCert *cert;
-	FILE *in;
-	int i;
-	
-	g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), -1);
-	g_return_val_if_fail (certdb->filename, -1);
-
-	in = fopen (certdb->filename, "r");
-	if (in == NULL)
-		return -1;
-	
-	CAMEL_CERTDB_LOCK (certdb, io_lock);
-	if (CAMEL_CERTDB_GET_CLASS (certdb)->header_load (certdb, in) == -1)
-		goto error;
-	
-	for (i = 0; i < certdb->saved_certs; i++) {
-		cert = CAMEL_CERTDB_GET_CLASS (certdb)->cert_load (certdb, in);
-		
-		if (cert == NULL)
-			goto error;
-		
-		camel_certdb_add (certdb, cert);
-	}
-	
-	CAMEL_CERTDB_UNLOCK (certdb, io_lock);
-	
-	if (fclose (in) != 0)
-		return -1;
-	
-	certdb->flags &= ~CAMEL_CERTDB_DIRTY;
-	
-	return 0;
-	
- error:
-	
-	g_warning ("Cannot load certificate database: %s", strerror (ferror (in)));
-	
-	CAMEL_CERTDB_UNLOCK (certdb, io_lock);
-	
-	fclose (in);
-	
-	return -1;
-}
-
-static int
-certdb_header_save (CamelCertDB *certdb, FILE *ostream)
-{
-	if (camel_file_util_encode_uint32 (ostream, certdb->version) == -1)
-		return -1;
-	if (camel_file_util_encode_uint32 (ostream, certdb->saved_certs) == -1)
-		return -1;
-	
-	return 0;
-}
-
-static int
-certdb_cert_save (CamelCertDB *certdb, CamelCert *cert, FILE *ostream)
-{
-	if (camel_file_util_encode_string (ostream, cert->issuer) == -1)
-		return -1;
-	if (camel_file_util_encode_string (ostream, cert->subject) == -1)
-		return -1;
-	if (camel_file_util_encode_string (ostream, cert->hostname) == -1)
-		return -1;
-	if (camel_file_util_encode_string (ostream, cert->fingerprint) == -1)
-		return -1;
-	if (camel_file_util_encode_uint32 (ostream, cert->trust) == -1)
-		return -1;
-	
-	return 0;
-}
-
-int
-camel_certdb_save (CamelCertDB *certdb)
-{
-	CamelCert *cert;
-	char *filename;
-	int fd, i;
-	FILE *out;
-	
-	g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), -1);
-	g_return_val_if_fail (certdb->filename, -1);
-	
-	filename = alloca (strlen (certdb->filename) + 4);
-	sprintf (filename, "%s~", certdb->filename);
-	
-	fd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
-	if (fd == -1)
-		return -1;
-	
-	out = fdopen (fd, "w");
-	if (out == NULL) {
-		i = errno;
-		close (fd);
-		unlink (filename);
-		errno = i;
-		return -1;
-	}
-	
-	CAMEL_CERTDB_LOCK (certdb, io_lock);
-	
-	certdb->saved_certs = certdb->certs->len;
-	if (CAMEL_CERTDB_GET_CLASS (certdb)->header_save (certdb, out) == -1)
-		goto error;
-	
-	for (i = 0; i < certdb->saved_certs; i++) {
-		cert = (CamelCert *) certdb->certs->pdata[i];
-		
-		if (CAMEL_CERTDB_GET_CLASS (certdb)->cert_save (certdb, cert, out) == -1)
-			goto error;
-	}
-	
-	CAMEL_CERTDB_UNLOCK (certdb, io_lock);
-	
-	if (fflush (out) != 0 || fsync (fileno (out)) == -1) {
-		i = errno;
-		fclose (out);
-		unlink (filename);
-		errno = i;
-		return -1;
-	}
-	
-	if (fclose (out) != 0) {
-		i = errno;
-		unlink (filename);
-		errno = i;
-		return -1;
-	}
-	
-	if (rename (filename, certdb->filename) == -1) {
-		i = errno;
-		unlink (filename);
-		errno = i;
-		return -1;
-	}
-	
-	certdb->flags &= ~CAMEL_CERTDB_DIRTY;
-	
-	return 0;
-	
- error:
-	
-	g_warning ("Cannot save certificate database: %s", strerror (ferror (out)));
-	
-	CAMEL_CERTDB_UNLOCK (certdb, io_lock);
-	
-	i = errno;
-	fclose (out);
-	unlink (filename);
-	errno = i;
-	
-	return -1;
-}
-
-void
-camel_certdb_touch (CamelCertDB *certdb)
-{
-	g_return_if_fail (CAMEL_IS_CERTDB (certdb));
-	
-	certdb->flags |= CAMEL_CERTDB_DIRTY;
-}
-
-CamelCert *
-camel_certdb_get_cert (CamelCertDB *certdb, const char *fingerprint)
-{
-	CamelCert *cert;
-	
-	g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), NULL);
-	
-	CAMEL_CERTDB_LOCK (certdb, db_lock);
-	
-	cert = g_hash_table_lookup (certdb->cert_hash, fingerprint);
-	if (cert)
-		camel_certdb_cert_ref (certdb, cert);
-	
-	CAMEL_CERTDB_UNLOCK (certdb, db_lock);
-	
-	return cert;
-}
-
-void
-camel_certdb_add (CamelCertDB *certdb, CamelCert *cert)
-{
-	g_return_if_fail (CAMEL_IS_CERTDB (certdb));
-	
-	CAMEL_CERTDB_LOCK (certdb, db_lock);
-	
-	if (g_hash_table_lookup (certdb->cert_hash, cert->fingerprint)) {
-		CAMEL_CERTDB_UNLOCK (certdb, db_lock);
-		return;
-	}
-	
-	camel_certdb_cert_ref (certdb, cert);
-	g_ptr_array_add (certdb->certs, cert);
-	g_hash_table_insert (certdb->cert_hash, cert->fingerprint, cert);
-	
-	certdb->flags |= CAMEL_CERTDB_DIRTY;
-	
-	CAMEL_CERTDB_UNLOCK (certdb, db_lock);
-}
-
-void
-camel_certdb_remove (CamelCertDB *certdb, CamelCert *cert)
-{
-	g_return_if_fail (CAMEL_IS_CERTDB (certdb));
-	
-	CAMEL_CERTDB_LOCK (certdb, db_lock);
-	
-	if (g_hash_table_lookup (certdb->cert_hash, cert->fingerprint)) {
-		g_hash_table_remove (certdb->cert_hash, cert->fingerprint);
-		g_ptr_array_remove (certdb->certs, cert);
-		camel_certdb_cert_unref (certdb, cert);
-		
-		certdb->flags |= CAMEL_CERTDB_DIRTY;
-	}
-	
-	CAMEL_CERTDB_UNLOCK (certdb, db_lock);
-}
-
-static CamelCert *
-certdb_cert_new (CamelCertDB *certdb)
-{
-	CamelCert *cert;
-	
-	if (certdb->cert_chunks)
-		cert = e_memchunk_alloc0 (certdb->cert_chunks);
-	else
-		cert = g_malloc0 (certdb->cert_size);
-	
-	cert->refcount = 1;
-	
-	return cert;
-}
-
-CamelCert *
-camel_certdb_cert_new (CamelCertDB *certdb)
-{
-	CamelCert *cert;
-	
-	g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), NULL);
-	
-	CAMEL_CERTDB_LOCK (certdb, alloc_lock);
-	
-	cert = CAMEL_CERTDB_GET_CLASS (certdb)->cert_new (certdb);
-	
-	CAMEL_CERTDB_UNLOCK (certdb, alloc_lock);
-	
-	return cert;
-}
-
-void
-camel_certdb_cert_ref (CamelCertDB *certdb, CamelCert *cert)
-{
-	g_return_if_fail (CAMEL_IS_CERTDB (certdb));
-	g_return_if_fail (cert != NULL);
-	
-	CAMEL_CERTDB_LOCK (certdb, ref_lock);
-	cert->refcount++;
-	CAMEL_CERTDB_UNLOCK (certdb, ref_lock);
-}
-
-static void
-certdb_cert_free (CamelCertDB *certdb, CamelCert *cert)
-{
-	g_free (cert->issuer);
-	g_free (cert->subject);
-	g_free (cert->hostname);
-	g_free (cert->fingerprint);
-	if (cert->rawcert)
-		g_byte_array_free(cert->rawcert, TRUE);
-}
-
-void
-camel_certdb_cert_unref (CamelCertDB *certdb, CamelCert *cert)
-{
-	g_return_if_fail (CAMEL_IS_CERTDB (certdb));
-	g_return_if_fail (cert != NULL);
-	
-	CAMEL_CERTDB_LOCK (certdb, ref_lock);
-	
-	if (cert->refcount <= 1) {
-		CAMEL_CERTDB_GET_CLASS (certdb)->cert_free (certdb, cert);
-		if (certdb->cert_chunks)
-			e_memchunk_free (certdb->cert_chunks, cert);
-		else
-			g_free (cert);
-	} else {
-		cert->refcount--;
-	}
-	
-	CAMEL_CERTDB_UNLOCK (certdb, ref_lock);
-}
-
-
-static gboolean
-cert_remove (gpointer key, gpointer value, gpointer user_data)
-{
-	return TRUE;
-}
-
-void
-camel_certdb_clear (CamelCertDB *certdb)
-{
-	CamelCert *cert;
-	int i;
-	
-	g_return_if_fail (CAMEL_IS_CERTDB (certdb));
-	
-	CAMEL_CERTDB_LOCK (certdb, db_lock);
-	
-	g_hash_table_foreach_remove (certdb->cert_hash, cert_remove, NULL);
-	for (i = 0; i < certdb->certs->len; i++) {
-		cert = (CamelCert *) certdb->certs->pdata[i];
-		camel_certdb_cert_unref (certdb, cert);
-	}
-	
-	certdb->saved_certs = 0;
-	g_ptr_array_set_size (certdb->certs, 0);
-	certdb->flags |= CAMEL_CERTDB_DIRTY;
-	
-	CAMEL_CERTDB_UNLOCK (certdb, db_lock);
-}
-
-
-static const char *
-cert_get_string (CamelCertDB *certdb, CamelCert *cert, int string)
-{
-	switch (string) {
-	case CAMEL_CERT_STRING_ISSUER:
-		return cert->issuer;
-	case CAMEL_CERT_STRING_SUBJECT:
-		return cert->subject;
-	case CAMEL_CERT_STRING_HOSTNAME:
-		return cert->hostname;
-	case CAMEL_CERT_STRING_FINGERPRINT:
-		return cert->fingerprint;
-	default:
-		return NULL;
-	}
-}
-
-
-const char *
-camel_cert_get_string (CamelCertDB *certdb, CamelCert *cert, int string)
-{
-	g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), NULL);
-	g_return_val_if_fail (cert != NULL, NULL);
-	
-	/* FIXME: do locking? */
-	
-	return CAMEL_CERTDB_GET_CLASS (certdb)->cert_get_string (certdb, cert, string);
-}
-
-static void
-cert_set_string (CamelCertDB *certdb, CamelCert *cert, int string, const char *value)
-{
-	switch (string) {
-	case CAMEL_CERT_STRING_ISSUER:
-		g_free (cert->issuer);
-		cert->issuer = g_strdup (value);
-		break;
-	case CAMEL_CERT_STRING_SUBJECT:
-		g_free (cert->subject);
-		cert->subject = g_strdup (value);
-		break;
-	case CAMEL_CERT_STRING_HOSTNAME:
-		g_free (cert->hostname);
-		cert->hostname = g_strdup (value);
-		break;
-	case CAMEL_CERT_STRING_FINGERPRINT:
-		g_free (cert->fingerprint);
-		cert->fingerprint = g_strdup (value);
-		break;
-	default:
-		break;
-	}
-}
-
-
-void
-camel_cert_set_string (CamelCertDB *certdb, CamelCert *cert, int string, const char *value)
-{
-	g_return_if_fail (CAMEL_IS_CERTDB (certdb));
-	g_return_if_fail (cert != NULL);
-	
-	/* FIXME: do locking? */
-	
-	CAMEL_CERTDB_GET_CLASS (certdb)->cert_set_string (certdb, cert, string, value);
-}
-
-
-CamelCertTrust
-camel_cert_get_trust (CamelCertDB *certdb, CamelCert *cert)
-{
-	g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), CAMEL_CERT_TRUST_UNKNOWN);
-	g_return_val_if_fail (cert != NULL, CAMEL_CERT_TRUST_UNKNOWN);
-	
-	return cert->trust;
-}
-
-
-void
-camel_cert_set_trust (CamelCertDB *certdb, CamelCert *cert, CamelCertTrust trust)
-{
-	g_return_if_fail (CAMEL_IS_CERTDB (certdb));
-	g_return_if_fail (cert != NULL);
-	
-	cert->trust = trust;
-}
diff --git a/camel/camel-certdb.h b/camel/camel-certdb.h
deleted file mode 100644
index 60429edcd1..0000000000
--- a/camel/camel-certdb.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *
- *  Copyright 2002 Ximian, Inc. (www.ximian.com)
- *
- *  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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-
-#ifndef __CAMEL_CERTDB_H__
-#define __CAMEL_CERTDB_H__
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include 
-#include 
-
-#define CAMEL_CERTDB_TYPE         (camel_certdb_get_type ())
-#define CAMEL_CERTDB(obj)         (CAMEL_CHECK_CAST (obj, camel_certdb_get_type (), CamelCertDB))
-#define CAMEL_CERTDB_CLASS(klass) (CAMEL_CHECK_CLASS_CAST (klass, camel_certdb_get_type (), CamelCertDBClass))
-#define CAMEL_IS_CERTDB(obj)      (CAMEL_CHECK_TYPE (obj, camel_certdb_get_type ()))
-
-typedef struct _CamelCertDB CamelCertDB;
-typedef struct _CamelCertDBClass CamelCertDBClass;
-
-enum {
-	CAMEL_CERTDB_DIRTY  = (1 << 0),
-};
-
-enum {
-	CAMEL_CERT_STRING_ISSUER,
-	CAMEL_CERT_STRING_SUBJECT,
-	CAMEL_CERT_STRING_HOSTNAME,
-	CAMEL_CERT_STRING_FINGERPRINT,
-};
-
-typedef enum {
-	CAMEL_CERT_TRUST_UNKNOWN,
-	CAMEL_CERT_TRUST_NEVER,
-	CAMEL_CERT_TRUST_MARGINAL,
-	CAMEL_CERT_TRUST_FULLY,
-	CAMEL_CERT_TRUST_ULTIMATE,
-} CamelCertTrust;
-
-typedef struct {
-	guint32 refcount;
-	
-	char *issuer;
-	char *subject;
-	char *hostname;
-	char *fingerprint;
-	
-	CamelCertTrust trust;
-	GByteArray *rawcert;
-} CamelCert;
-
-struct _CamelCertDB {
-	CamelObject parent_object;
-	struct _CamelCertDBPrivate *priv;
-	
-	char *filename;
-	guint32 version;
-	guint32 saved_certs;
-	guint32 flags;
-	
-	guint32 cert_size;
-	
-	struct _EMemChunk *cert_chunks;
-	
-	GPtrArray *certs;
-	GHashTable *cert_hash;
-};
-
-struct _CamelCertDBClass {
-	CamelObjectClass parent_class;
-	
-	int (*header_load) (CamelCertDB *certdb, FILE *istream);
-	int (*header_save) (CamelCertDB *certdb, FILE *ostream);
-	
-	CamelCert * (*cert_load) (CamelCertDB *certdb, FILE *istream);
-	int (*cert_save) (CamelCertDB *certdb, CamelCert *cert, FILE *ostream);
-	
-	CamelCert *  (*cert_new) (CamelCertDB *certdb);
-	void        (*cert_free) (CamelCertDB *certdb, CamelCert *cert);
-	
-	const char * (*cert_get_string) (CamelCertDB *certdb, CamelCert *cert, int string);
-	void (*cert_set_string) (CamelCertDB *certdb, CamelCert *cert, int string, const char *value);
-};
-
-
-CamelType camel_certdb_get_type (void);
-
-CamelCertDB *camel_certdb_new (void);
-
-void camel_certdb_set_default (CamelCertDB *certdb);
-CamelCertDB *camel_certdb_get_default (void);
-
-void camel_certdb_set_filename (CamelCertDB *certdb, const char *filename);
-
-int camel_certdb_load (CamelCertDB *certdb);
-int camel_certdb_save (CamelCertDB *certdb);
-
-void camel_certdb_touch (CamelCertDB *certdb);
-
-CamelCert *camel_certdb_get_cert (CamelCertDB *certdb, const char *fingerprint);
-
-void camel_certdb_add (CamelCertDB *certdb, CamelCert *cert);
-void camel_certdb_remove (CamelCertDB *certdb, CamelCert *cert);
-
-CamelCert *camel_certdb_cert_new (CamelCertDB *certdb);
-void camel_certdb_cert_ref (CamelCertDB *certdb, CamelCert *cert);
-void camel_certdb_cert_unref (CamelCertDB *certdb, CamelCert *cert);
-
-void camel_certdb_clear (CamelCertDB *certdb);
-
-
-const char *camel_cert_get_string (CamelCertDB *certdb, CamelCert *cert, int string);
-void camel_cert_set_string (CamelCertDB *certdb, CamelCert *cert, int string, const char *value);
-
-#define camel_cert_get_issuer(certdb,cert) camel_cert_get_string (certdb, cert, CAMEL_CERT_STRING_ISSUER)
-#define camel_cert_get_subject(certdb,cert) camel_cert_get_string (certdb, cert, CAMEL_CERT_STRING_SUBJECT)
-#define camel_cert_get_hostname(certdb,cert) camel_cert_get_string (certdb, cert, CAMEL_CERT_STRING_HOSTNAME)
-#define camel_cert_get_fingerprint(certdb,cert) camel_cert_get_string (certdb, cert, CAMEL_CERT_STRING_FINGERPRINT)
-
-#define camel_cert_set_issuer(certdb,cert,issuer) camel_cert_set_string (certdb, cert, CAMEL_CERT_STRING_ISSUER, issuer)
-#define camel_cert_set_subject(certdb,cert,subject) camel_cert_set_string (certdb, cert, CAMEL_CERT_STRING_SUBJECT, subject)
-#define camel_cert_set_hostname(certdb,cert,hostname) camel_cert_set_string (certdb, cert, CAMEL_CERT_STRING_HOSTNAME, hostname)
-#define camel_cert_set_fingerprint(certdb,cert,fingerprint) camel_cert_set_string (certdb, cert, CAMEL_CERT_STRING_FINGERPRINT, fingerprint)
-
-CamelCertTrust camel_cert_get_trust (CamelCertDB *certdb, CamelCert *cert);
-void camel_cert_set_trust (CamelCertDB *certdb, CamelCert *cert, CamelCertTrust trust);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __CAMEL_CERTDB_H__ */
diff --git a/camel/camel-charset-map-private.h b/camel/camel-charset-map-private.h
deleted file mode 100644
index 35556db87e..0000000000
--- a/camel/camel-charset-map-private.h
+++ /dev/null
@@ -1,621 +0,0 @@
-/* This file is automatically generated: DO NOT EDIT */
-
-static unsigned char m000[256] = {
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-	0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, 0xbf, 0xbf, 
-	0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 
-	0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 
-	0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 
-	0xbf, 0xbf, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 
-	0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 
-	0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 
-	0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 
-	0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 
-	0xff, 0x80, 0xc0, 0xe0, 0xc3, 0xc0, 0xe0, 0xf3, 
-	0xe3, 0xec, 0x80, 0xe0, 0xe0, 0xf3, 0xc0, 0xc2, 
-	0xef, 0xe0, 0xec, 0xe0, 0xc3, 0xc0, 0xc0, 0xec, 
-	0xc3, 0xc0, 0x80, 0xe0, 0xc0, 0xe0, 0xc0, 0x80, 
-	0x80, 0x83, 0x83, 0x82, 0x83, 0x82, 0x82, 0x81, 
-	0x80, 0x83, 0x80, 0x83, 0x80, 0x83, 0x83, 0x80, 
-	0x00, 0x80, 0x80, 0x81, 0x83, 0x82, 0x83, 0xc3, 
-	0x82, 0x80, 0x83, 0x82, 0x83, 0x01, 0x00, 0x83, 
-	0x80, 0x83, 0x83, 0x82, 0x83, 0x82, 0x82, 0x81, 
-	0x80, 0x83, 0x80, 0x83, 0x80, 0x83, 0x83, 0x80, 
-	0x00, 0x80, 0x80, 0x81, 0x83, 0x82, 0x83, 0xcf, 
-	0x82, 0x80, 0x83, 0x82, 0x83, 0x01, 0x00, 0x80, 
-};
-
-static unsigned char m001[256] = {
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
-	0x07, 0x02, 0x03, 0x03, 0x05, 0x02, 0x05, 0x07, 
-	0x00, 0x07, 0x02, 0x07, 0x07, 0x07, 0x07, 0x02, 
-	0x07, 0x07, 0x03, 0x03, 0x00, 0x07, 0x07, 0x07, 
-	0x00, 0x03, 0x02, 0x07, 0x01, 0x01, 0x01, 0x02, 
-	0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 
-	0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
-	0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 
-	0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x03, 
-	0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 
-	0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
-	0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 
-	0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 
-};
-
-static unsigned char m010[256] = {
-	0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 
-	0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x01, 0x01, 
-	0x03, 0x03, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 
-	0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x80, 0x80, 
-	0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 
-	0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 
-	0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 
-	0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x00, 
-	0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 
-	0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 
-	0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 
-	0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x81, 0x81, 
-	0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 
-	0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 
-	0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-};
-
-static unsigned char m011[256] = {
-	0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 
-	0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 
-	0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 
-	0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 
-	0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 
-	0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 
-	0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 
-	0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 
-	0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 
-	0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-};
-
-static unsigned char m020[256] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x01, 0x03, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-};
-
-static unsigned char m030[256] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x00, 
-	0x20, 0x20, 0x20, 0x00, 0x20, 0x00, 0x20, 0x20, 
-	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
-	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
-	0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 
-	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
-	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
-	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
-	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
-	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-};
-
-static unsigned char m040[256] = {
-	0x00, 0x1c, 0x10, 0x10, 0x18, 0x10, 0x18, 0x18, 
-	0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 
-	0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 
-	0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 
-	0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 
-	0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 
-	0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 
-	0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 
-	0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 
-	0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 
-	0x00, 0x1c, 0x10, 0x10, 0x18, 0x10, 0x18, 0x18, 
-	0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-};
-
-static unsigned char m041[256] = {
-	0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04, 0x04, 
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
-	0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04, 0x04, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-};
-
-static unsigned char m050[256] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 
-	0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 
-	0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 
-	0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-};
-
-static unsigned char m200[256] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x40, 
-	0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-};
-
-static unsigned char m201[256] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 
-	0x04, 0x05, 0x04, 0x00, 0x05, 0x05, 0x05, 0x00, 
-	0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-};
-
-static unsigned char m210[256] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-};
-
-static unsigned char m211[256] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-};
-
-static unsigned char m220[256] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-};
-
-static unsigned char m230[256] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-};
-
-static unsigned char m250[256] = {
-	0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 
-	0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 
-	0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x0c, 0x0c, 0x0c, 0x04, 0x0c, 0x04, 0x04, 0x0c, 
-	0x0c, 0x0c, 0x0c, 0x0c, 0x04, 0x0c, 0x0c, 0x0c, 
-	0x0c, 0x0c, 0x04, 0x0c, 0x04, 0x04, 0x0c, 0x0c, 
-	0x0c, 0x0c, 0x0c, 0x04, 0x0c, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 
-	0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 
-	0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-};
-
-struct {
-	unsigned char *bits0;
-	unsigned char *bits1;
-} camel_charmap[256] = {
-	{ m000, m001, }, { m010, m011, }, { m020, 0, }, { m030, 0, }, { m040, m041, }, { m050, 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, }, 
-	{ m200, m201, }, { m210, m211, }, { m220, 0, }, { m230, 0, }, { 0, 0, }, { m250, 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, }, { 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, 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, }, { 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, 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, }, { 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, 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, }, 
-};
-
-struct {
-	const char *name;
-	unsigned int bit;
-} camel_charinfo[] = {
-	{ "iso-8859-2", 0x0001 },
-	{ "iso-8859-4", 0x0002 },
-	{ "koi8-r", 0x0004 },
-	{ "koi8-u", 0x0008 },
-	{ "iso-8859-5", 0x0010 },
-	{ "iso-8859-7", 0x0020 },
-	{ "iso-8859-8", 0x0040 },
-	{ "iso-8859-9", 0x0080 },
-	{ "iso-8859-13", 0x0100 },
-	{ "iso-8859-15", 0x0200 },
-	{ "windows-1251", 0x0400 },
-};
-
-#define charset_mask(x) \
-	(camel_charmap[(x)>>8].bits0?camel_charmap[(x)>>8].bits0[(x)&0xff]<<0:0)	\
-	| (camel_charmap[(x)>>8].bits1?camel_charmap[(x)>>8].bits1[(x)&0xff]<<8:0)
-
diff --git a/camel/camel-charset-map.c b/camel/camel-charset-map.c
deleted file mode 100644
index 9bd4f4e253..0000000000
--- a/camel/camel-charset-map.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; -*- */
-/* 
- * Authors:
- *   Michael Zucchi 
- *   Jeffrey Stedfast 
- *   Dan Winship 
- *
- * Copyright 2000-2003 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of version 2 of the GNU General Public 
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-
-/*
-  if you want to build the charset map, compile this with something like:
-    gcc -DBUILD_MAP camel-charset-map.c `glib-config --cflags`
-  (plus any -I/-L/-l flags you need for iconv), then run it as 
-    ./a.out > camel-charset-map-private.h
-
-  Note that the big-endian variant isn't tested...
-
-  The tables genereated work like this:
-
-   An indirect array for each page of unicode character
-   Each array element has an indirect pointer to one of the bytes of
-   the generated bitmask.
-*/
-
-#ifdef BUILD_MAP
-#include 
-#include 
-
-static struct {
-	char *name;
-	unsigned int bit;	/* assigned bit */
-} tables[] = {
-	/* These are the 8bit character sets (other than iso-8859-1,
-	 * which is special-cased) which are supported by both other
-	 * mailers and the GNOME environment. Note that the order
-	 * they're listed in is the order they'll be tried in, so put
-	 * the more-popular ones first.
-	 */
-	{ "iso-8859-2", 0 },	/* Central/Eastern European */
-	{ "iso-8859-4", 0 },	/* Baltic */
-	{ "koi8-r", 0 },	/* Russian */
-	{ "koi8-u", 0 },	/* Ukranian */
-	{ "iso-8859-5", 0 },	/* Least-popular Russian encoding */
-	{ "iso-8859-7", 0 },	/* Greek */
-	{ "iso-8859-8", 0 },    /* Hebrew; Visual */
-	{ "iso-8859-9", 0 },	/* Turkish */
-	{ "iso-8859-13", 0 },	/* Baltic again */
-	{ "iso-8859-15", 0 },	/* New-and-improved iso-8859-1, but most
-				 * programs that support this support UTF8
-				 */
-	{ "windows-1251", 0 },	/* Russian */
-	{ 0, 0 }
-};
-
-unsigned int encoding_map[256 * 256];
-
-#if G_BYTE_ORDER == G_BIG_ENDIAN
-#define UCS "UCS-4BE"
-#else
-#define UCS "UCS-4LE"
-#endif
-
-int main (void)
-{
-	int i, j;
-	int max, min;
-	int bit = 0x01;
-	int k;
-	int bytes;
-	iconv_t cd;
-	char in[128];
-	guint32 out[128];
-	char *inptr, *outptr;
-	size_t inlen, outlen;
-
-	/* dont count the terminator */
-	bytes = ((sizeof(tables)/sizeof(tables[0]))+7-1)/8;
-
-	for (i = 0; i < 128; i++)
-		in[i] = i + 128;
-
-	for (j = 0; tables[j].name; j++) {
-		cd = iconv_open (UCS, tables[j].name);
-		inptr = in;
-		outptr = (char *)(out);
-		inlen = sizeof (in);
-		outlen = sizeof (out);
-		while (iconv (cd, &inptr, &inlen, &outptr, &outlen) == -1) {
-			if (errno == EILSEQ) {
-				inptr++;
-				inlen--;
-			} else {
-				printf ("%s\n", strerror (errno));
-				exit (1);
-			}
-		}
-		iconv_close (cd);
-
-		for (i = 0; i < 128 - outlen / 4; i++) {
-			encoding_map[i] |= bit;
-			encoding_map[out[i]] |= bit;
-		}
-
-		tables[j].bit = bit;
-		bit <<= 1;
-	}
-
-	printf("/* This file is automatically generated: DO NOT EDIT */\n\n");
-
-	for (i=0;i<256;i++) {
-		/* first, do we need this block? */
-		for (k=0;k> (k*8)) & 0xff );
-					if (((j+1)&7) == 0 && j<255)
-						printf("\n\t");
-				}
-				printf("\n};\n\n");
-			}
-		}
-	}
-
-	printf("struct {\n");
-	for (k=0;k>8].bits%d?camel_charmap[(x)>>8].bits%d[(x)&0xff]<<%d:0)", k, k, k*8);
-		if (k
-#include 
-#include 
-#include 
-#ifdef HAVE_CODESET
-#include 
-#endif
-
-void
-camel_charset_init (CamelCharset *c)
-{
-	c->mask = (unsigned int) ~0;
-	c->level = 0;
-}
-
-void
-camel_charset_step (CamelCharset *c, const char *in, int len)
-{
-	register unsigned int mask;
-	register int level;
-	const char *inptr = in, *inend = in+len;
-
-	mask = c->mask;
-	level = c->level;
-
-	/* check what charset a given string will fit in */
-	while (inptr < inend) {
-		gunichar c;
-		const char *newinptr;
-		newinptr = g_utf8_next_char(inptr);
-		c = g_utf8_get_char(inptr);
-		if (newinptr == NULL || !g_unichar_validate (c)) {
-			inptr++;
-			continue;
-		}
-
-		inptr = newinptr;
-		if (c<=0xffff) {
-			mask &= charset_mask(c);
-		
-			if (c>=128 && c<256)
-				level = MAX(level, 1);
-			else if (c>=256)
-				level = MAX(level, 2);
-		} else {
-			mask = 0;
-			level = MAX(level, 2);
-		}
-	}
-
-	c->mask = mask;
-	c->level = level;
-}
-
-/* gets the best charset from the mask of chars in it */
-static const char *
-camel_charset_best_mask(unsigned int mask)
-{
-	int i;
-
-	for (i=0;ilevel == 1)
-		return "ISO-8859-1";
-	else if (charset->level == 2)
-		return camel_charset_best_mask (charset->mask);
-	else
-		return NULL;
-
-}
-
-/* finds the minimum charset for this string NULL means US-ASCII */
-const char *
-camel_charset_best (const char *in, int len)
-{
-	CamelCharset charset;
-
-	camel_charset_init (&charset);
-	camel_charset_step (&charset, in, len);
-	return camel_charset_best_name (&charset);
-}
-
-
-/**
- * camel_charset_iso_to_windows:
- * @isocharset: a canonicalised ISO charset
- *
- * Returns the equivalent Windows charset.
- **/
-const char *
-camel_charset_iso_to_windows (const char *isocharset)
-{
-	/* According to http://czyborra.com/charsets/codepages.html,
-	 * the charset mapping is as follows:
-	 *
-	 * us-ascii    maps to windows-cp1252
-	 * iso-8859-1  maps to windows-cp1252
-	 * iso-8859-2  maps to windows-cp1250
-	 * iso-8859-3  maps to windows-cp????
-	 * iso-8859-4  maps to windows-cp????
-	 * iso-8859-5  maps to windows-cp1251
-	 * iso-8859-6  maps to windows-cp1256
-	 * iso-8859-7  maps to windows-cp1253
-	 * iso-8859-8  maps to windows-cp1255
-	 * iso-8859-9  maps to windows-cp1254
-	 * iso-8859-10 maps to windows-cp????
-	 * iso-8859-11 maps to windows-cp????
-	 * iso-8859-12 maps to windows-cp????
-	 * iso-8859-13 maps to windows-cp1257
-	 *
-	 * Assumptions:
-	 *  - I'm going to assume that since iso-8859-4 and
-	 *    iso-8859-13 are Baltic that it also maps to
-	 *    windows-cp1257.
-	 */
-	
-	if (!strcasecmp (isocharset, "iso-8859-1") || !strcasecmp (isocharset, "us-ascii"))
-		return "windows-cp1252";
-	else if (!strcasecmp (isocharset, "iso-8859-2"))
-		return "windows-cp1250";
-	else if (!strcasecmp (isocharset, "iso-8859-4"))
-		return "windows-cp1257";
-	else if (!strcasecmp (isocharset, "iso-8859-5"))
-		return "windows-cp1251";
-	else if (!strcasecmp (isocharset, "iso-8859-6"))
-		return "windows-cp1256";
-	else if (!strcasecmp (isocharset, "iso-8859-7"))
-		return "windows-cp1253";
-	else if (!strcasecmp (isocharset, "iso-8859-8"))
-		return "windows-cp1255";
-	else if (!strcasecmp (isocharset, "iso-8859-9"))
-		return "windows-cp1254";
-	else if (!strcasecmp (isocharset, "iso-8859-13"))
-		return "windows-cp1257";
-	
-	return isocharset;
-}
-
-#endif /* !BUILD_MAP */
diff --git a/camel/camel-charset-map.h b/camel/camel-charset-map.h
deleted file mode 100644
index cd627ee488..0000000000
--- a/camel/camel-charset-map.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Copyright (C) 2000-2003 Ximian Inc.
- *
- *  Authors: Michael Zucchi 
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef _CAMEL_CHARSET_MAP_H
-#define _CAMEL_CHARSET_MAP_H
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-typedef struct _CamelCharset CamelCharset;
-
-struct _CamelCharset {
-	unsigned int mask;
-	int level;
-};
-
-void camel_charset_init(CamelCharset *);
-void camel_charset_step(CamelCharset *, const char *in, int len);
-
-const char *camel_charset_best_name (CamelCharset *);
-
-/* helper function */
-const char *camel_charset_best(const char *in, int len);
-
-const char *camel_charset_iso_to_windows (const char *isocharset);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* ! _CAMEL_CHARSET_MAP_H */
diff --git a/camel/camel-cipher-context.c b/camel/camel-cipher-context.c
deleted file mode 100644
index b730d927c8..0000000000
--- a/camel/camel-cipher-context.c
+++ /dev/null
@@ -1,585 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *
- *  Copyright 2001-2003 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-#include 
-
-#include 
-
-#include "camel-cipher-context.h"
-#include "camel-stream.h"
-
-#include "camel-mime-utils.h"
-#include "camel-medium.h"
-#include "camel-multipart.h"
-#include "camel-mime-message.h"
-#include "camel-mime-filter-canon.h"
-#include "camel-stream-filter.h"
-
-#define CIPHER_LOCK(ctx)   g_mutex_lock (((CamelCipherContext *) ctx)->priv->lock)
-#define CIPHER_UNLOCK(ctx) g_mutex_unlock (((CamelCipherContext *) ctx)->priv->lock);
-
-#define d(x)
-
-#define CCC_CLASS(o) CAMEL_CIPHER_CONTEXT_CLASS(CAMEL_OBJECT_GET_CLASS(o))
-
-struct _CamelCipherContextPrivate {
-	GMutex *lock;
-};
-
-static CamelObjectClass *parent_class = NULL;
-
-/**
- * camel_cipher_context_new:
- * @session: CamelSession
- *
- * This creates a new CamelCipherContext object which is used to sign,
- * verify, encrypt and decrypt streams.
- *
- * Return value: the new CamelCipherContext
- **/
-CamelCipherContext *
-camel_cipher_context_new (CamelSession *session)
-{
-	CamelCipherContext *context;
-	
-	g_return_val_if_fail (session != NULL, NULL);
-	
-	context = CAMEL_CIPHER_CONTEXT (camel_object_new (CAMEL_CIPHER_CONTEXT_TYPE));
-	
-	camel_object_ref (session);
-	context->session = session;
-	
-	return context;
-}
-
-/**
- * camel_cipher_context_construct:
- * @context: CamelCipherContext
- * @session: CamelSession
- *
- * Constucts the CamelCipherContext
- **/
-void
-camel_cipher_context_construct (CamelCipherContext *context, CamelSession *session)
-{
-	g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
-	g_return_if_fail (CAMEL_IS_SESSION (session));
-	
-	camel_object_ref (session);
-	context->session = session;
-}
-
-static int
-cipher_sign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash,
-	     struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex)
-{
-	camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-			     _("Signing is not supported by this cipher"));
-	return -1;
-}
-
-/**
- * camel_cipher_sign:
- * @context: Cipher Context
- * @userid: private key to use to sign the stream
- * @hash: preferred Message-Integrity-Check hash algorithm
- * @ipart: Input part.
- * @opart: output part.
- * @ex: exception
- *
- * Converts the (unsigned) part @ipart into a new self-contained mime part @opart.
- * This may be a multipart/signed part, or a simple part for enveloped types.
- *
- * Return value: 0 for success or -1 for failure.
- **/
-int
-camel_cipher_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
-		   struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex)
-{
-	int retval;
-	
-	g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
-	
-	CIPHER_LOCK(context);
-	
-	retval = CCC_CLASS (context)->sign (context, userid, hash, ipart, opart, ex);
-	
-	CIPHER_UNLOCK(context);
-	
-	return retval;
-}
-
-static CamelCipherValidity *
-cipher_verify (CamelCipherContext *context, struct _CamelMimePart *sigpart, CamelException *ex)
-{
-	camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-			     _("Verifying is not supported by this cipher"));
-	return NULL;
-}
-
-/**
- * camel_cipher_verify:
- * @context: Cipher Context
- * @ipart: part to verify
- * @ex: exception
- *
- * Verifies the signature. If @istream is a clearsigned stream,
- * you should pass %NULL as the sigstream parameter. Otherwise
- * @sigstream is assumed to be the signature stream and is used to
- * verify the integirity of the @istream.
- *
- * Return value: a CamelCipherValidity structure containing information
- * about the integrity of the input stream or %NULL on failure to
- * execute at all.
- **/
-CamelCipherValidity *
-camel_cipher_verify (CamelCipherContext *context, struct _CamelMimePart *ipart, CamelException *ex)
-{
-	CamelCipherValidity *valid;
-	
-	g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
-	
-	CIPHER_LOCK(context);
-	
-	valid = CCC_CLASS (context)->verify (context, ipart, ex);
-	
-	CIPHER_UNLOCK(context);
-	
-	return valid;
-}
-
-static int
-cipher_encrypt (CamelCipherContext *context, const char *userid, GPtrArray *recipients,
-		struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex)
-{
-	camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-			     _("Encryption is not supported by this cipher"));
-	return -1;
-}
-
-/**
- * camel_cipher_encrypt:
- * @context: Cipher Context
- * @userid: key id (or email address) to use when signing, or NULL to not sign.
- * @recipients: an array of recipient key ids and/or email addresses
- * @istream: cleartext input stream
- * @ostream: ciphertext output stream
- * @ex: exception
- *
- * Encrypts (and optionally signs) the cleartext input stream and
- * writes the resulting ciphertext to the output stream.
- *
- * Return value: 0 for success or -1 for failure.
- **/
-int
-camel_cipher_encrypt (CamelCipherContext *context, const char *userid, GPtrArray *recipients,
-		      struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex)
-{
-	int retval;
-	
-	g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
-	
-	CIPHER_LOCK(context);
-	
-	retval = CCC_CLASS (context)->encrypt (context, userid, recipients, ipart, opart, ex);
-	
-	CIPHER_UNLOCK(context);
-	
-	return retval;
-}
-
-static CamelCipherValidity *
-cipher_decrypt(CamelCipherContext *context, struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex)
-{
-	camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-			     _("Decryption is not supported by this cipher"));
-	return NULL;
-}
-
-/**
- * camel_cipher_decrypt:
- * @context: 
- * @ipart: 
- * @opart: 
- * @ex: 
- * 
- * Decrypts @ipart into @opart.
- * 
- * Return value: A validity/encryption status.
- **/
-CamelCipherValidity *
-camel_cipher_decrypt(CamelCipherContext *context, struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex)
-{
-	CamelCipherValidity *valid;
-
-	g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
-	
-	CIPHER_LOCK(context);
-	
-	valid = CCC_CLASS (context)->decrypt (context, ipart, opart, ex);
-	
-	CIPHER_UNLOCK(context);
-	
-	return valid;
-}
-
-static int
-cipher_import_keys (CamelCipherContext *context, struct _CamelStream *istream, CamelException *ex)
-{
-	camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-			     _("You may not import keys with this cipher"));
-	
-	return -1;
-}
-
-/**
- * camel_cipher_import_keys:
- * @ctx: Cipher Context
- * @istream: input stream (containing keys)
- * @ex: exception
- *
- * Imports a stream of keys/certificates contained within @istream
- * into the key/certificate database controlled by @ctx.
- *
- * Returns 0 on success or -1 on fail.
- **/
-int
-camel_cipher_import_keys (CamelCipherContext *context, struct _CamelStream *istream, CamelException *ex)
-{
-	g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
-	g_return_val_if_fail (CAMEL_IS_STREAM (istream), -1);
-	
-	return CCC_CLASS (context)->import_keys (context, istream, ex);
-}
-
-static int
-cipher_export_keys (CamelCipherContext *context, GPtrArray *keys,
-		    struct _CamelStream *ostream, CamelException *ex)
-{
-	camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-			     _("You may not export keys with this cipher"));
-	
-	return -1;
-}
-
-/**
- * camel_cipher_export_keys:
- * @ctx: Cipher Context
- * @keys: an array of key ids
- * @ostream: output stream
- * @ex: exception
- *
- * Exports the keys/certificates in @keys to the stream @ostream from
- * the key/certificate database controlled by @ctx.
- *
- * Returns 0 on success or -1 on fail.
- **/
-int
-camel_cipher_export_keys (CamelCipherContext *context, GPtrArray *keys,
-			  struct _CamelStream *ostream, CamelException *ex)
-{
-	g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
-	g_return_val_if_fail (CAMEL_IS_STREAM (ostream), -1);
-	g_return_val_if_fail (keys != NULL, -1);
-	
-	return CCC_CLASS (context)->export_keys (context, keys, ostream, ex);
-}
-
-static CamelCipherHash
-cipher_id_to_hash(CamelCipherContext *context, const char *id)
-{
-	return CAMEL_CIPHER_HASH_DEFAULT;
-}
-
-/* a couple of util functions */
-CamelCipherHash
-camel_cipher_id_to_hash(CamelCipherContext *context, const char *id)
-{
-	g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), CAMEL_CIPHER_HASH_DEFAULT);
-	
-	return CCC_CLASS (context)->id_to_hash (context, id);
-}
-
-static const char *
-cipher_hash_to_id(CamelCipherContext *context, CamelCipherHash hash)
-{
-	return NULL;
-}
-
-const char *
-camel_cipher_hash_to_id(CamelCipherContext *context, CamelCipherHash hash)
-{
-	g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
-	
-	return CCC_CLASS (context)->hash_to_id (context, hash);
-}
-
-/* Cipher Validity stuff */
-
-CamelCipherValidity *
-camel_cipher_validity_new (void)
-{
-	CamelCipherValidity *validity;
-	
-	validity = g_malloc(sizeof(*validity));
-	camel_cipher_validity_init(validity);
-
-	return validity;
-}
-
-void
-camel_cipher_validity_init (CamelCipherValidity *validity)
-{
-	g_assert (validity != NULL);
-
-	memset(validity, 0, sizeof(*validity));
-	e_dlist_init(&validity->children);
-}
-
-gboolean
-camel_cipher_validity_get_valid (CamelCipherValidity *validity)
-{
-	return validity != NULL
-		&& validity->sign.status == CAMEL_CIPHER_VALIDITY_SIGN_GOOD;
-}
-
-void
-camel_cipher_validity_set_valid (CamelCipherValidity *validity, gboolean valid)
-{
-	g_assert (validity != NULL);
-	
-	validity->sign.status = valid?CAMEL_CIPHER_VALIDITY_SIGN_GOOD:CAMEL_CIPHER_VALIDITY_SIGN_BAD;
-}
-
-gchar *
-camel_cipher_validity_get_description (CamelCipherValidity *validity)
-{
-	if (validity == NULL)
-		return NULL;
-	
-	return validity->sign.description;
-}
-
-void
-camel_cipher_validity_set_description (CamelCipherValidity *validity, const gchar *description)
-{
-	g_assert (validity != NULL);
-	
-	g_free(validity->sign.description);
-	validity->sign.description = g_strdup(description);
-}
-
-void
-camel_cipher_validity_clear (CamelCipherValidity *validity)
-{
-	g_assert (validity != NULL);
-
-	g_free(validity->sign.description);
-	g_free(validity->encrypt.description);
-	camel_cipher_validity_init(validity);
-}
-
-CamelCipherValidity *
-camel_cipher_validity_clone(CamelCipherValidity *vin)
-{
-	CamelCipherValidity *vo;
-
-	vo = camel_cipher_validity_new();
-	vo->sign.status = vin->sign.status;
-	vo->sign.description = g_strdup(vin->sign.description);
-	vo->encrypt.status = vin->encrypt.status;
-	vo->encrypt.description = g_strdup(vin->encrypt.description);
-
-	return vo;
-}
-
-/**
- * camel_cipher_validity_envelope:
- * @validity: 
- * @outer: 
- * 
- * Calculate a conglomerate validity based on wrapping one secure part inside
- * another one.
- **/
-void
-camel_cipher_validity_envelope(CamelCipherValidity *parent, CamelCipherValidity *valid)
-{
-	if (parent->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE
-	    && parent->encrypt.status == CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE
-	    && valid->sign.status == CAMEL_CIPHER_VALIDITY_SIGN_NONE
-	    && valid->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE) {
-		/* case 1: only signed inside only encrypted -> merge both */
-		parent->encrypt.status = valid->encrypt.status;
-		parent->encrypt.description = g_strdup(valid->encrypt.description);
-	} else if (parent->sign.status == CAMEL_CIPHER_VALIDITY_SIGN_NONE
-		   && parent->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE
-		   && valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE
-		   && valid->encrypt.status == CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE) {
-		/* case 2: only encrypted inside only signed */
-		parent->sign.status = valid->sign.status;
-		parent->sign.description = g_strdup(valid->sign.description);
-	}
-	/* Otherwise, I dunno - what do you do? */
-}
-
-void
-camel_cipher_validity_free (CamelCipherValidity *validity)
-{
-	CamelCipherValidity *child;
-
-	if (validity == NULL)
-		return;
-
-	while ((child = (CamelCipherValidity *)e_dlist_remhead(&validity->children)))
-		camel_cipher_validity_free(child);
-
-	camel_cipher_validity_clear(validity);
-	g_free(validity);
-}
-
-/* ********************************************************************** */
-
-static void
-camel_cipher_context_init (CamelCipherContext *context)
-{
-	context->priv = g_new0 (struct _CamelCipherContextPrivate, 1);
-	context->priv->lock = g_mutex_new ();
-}
-
-static void
-camel_cipher_context_finalise (CamelObject *o)
-{
-	CamelCipherContext *context = (CamelCipherContext *)o;
-	
-	camel_object_unref (CAMEL_OBJECT (context->session));
-	
-	g_mutex_free (context->priv->lock);
-	
-	g_free (context->priv);
-}
-
-static void
-camel_cipher_context_class_init (CamelCipherContextClass *camel_cipher_context_class)
-{
-	parent_class = camel_type_get_global_classfuncs (camel_object_get_type ());
-	
-	camel_cipher_context_class->hash_to_id = cipher_hash_to_id;
-	camel_cipher_context_class->id_to_hash = cipher_id_to_hash;
-	camel_cipher_context_class->sign = cipher_sign;
-	camel_cipher_context_class->verify = cipher_verify;
-	camel_cipher_context_class->encrypt = cipher_encrypt;
-	camel_cipher_context_class->decrypt = cipher_decrypt;
-	camel_cipher_context_class->import_keys = cipher_import_keys;
-	camel_cipher_context_class->export_keys = cipher_export_keys;
-}
-
-CamelType
-camel_cipher_context_get_type (void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-	
-	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register (camel_object_get_type (),
-					    "CamelCipherContext",
-					    sizeof (CamelCipherContext),
-					    sizeof (CamelCipherContextClass),
-					    (CamelObjectClassInitFunc) camel_cipher_context_class_init,
-					    NULL,
-					    (CamelObjectInitFunc) camel_cipher_context_init,
-					    (CamelObjectFinalizeFunc) camel_cipher_context_finalise);
-	}
-	
-	return type;
-}
-
-/* See rfc3156, section 2 and others */
-/* We do this simply: Anything not base64 must be qp
-   This is so that we can safely translate any occurance of "From "
-   into the quoted-printable escaped version safely. */
-static void
-cc_prepare_sign(CamelMimePart *part)
-{
-	CamelDataWrapper *dw;
-	CamelTransferEncoding encoding;
-	int parts, i;
-	
-	dw = camel_medium_get_content_object((CamelMedium *)part);
-	if (!dw)
-		return;
-	
-	if (CAMEL_IS_MULTIPART (dw)) {
-		parts = camel_multipart_get_number((CamelMultipart *)dw);
-		for (i = 0; i < parts; i++)
-			cc_prepare_sign(camel_multipart_get_part((CamelMultipart *)dw, i));
-	} else if (CAMEL_IS_MIME_MESSAGE (dw)) {
-		cc_prepare_sign((CamelMimePart *)dw);
-	} else {
-		encoding = camel_mime_part_get_encoding(part);
-
-		if (encoding != CAMEL_TRANSFER_ENCODING_BASE64
-		    && encoding != CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE) {
-			camel_mime_part_set_encoding(part, CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE);
-		}
-	}
-}
-
-/**
- * camel_cipher_canonical_to_stream:
- * @part: Part to write.
- * @flags: flags for the canonicalisation filter (CamelMimeFilterCanon)
- * @ostream: stream to write canonicalised output to.
- * 
- * Writes a part to a stream in a canonicalised format, suitable for signing/encrypting.
- *
- * The transfer encoding paramaters for the part may be changed by this function.
- * 
- * Return value: -1 on error;
- **/
-int
-camel_cipher_canonical_to_stream(CamelMimePart *part, guint32 flags, CamelStream *ostream)
-{
-	CamelStreamFilter *filter;
-	CamelMimeFilter *canon;
-	int res = -1;
-
-	if (flags & (CAMEL_MIME_FILTER_CANON_FROM|CAMEL_MIME_FILTER_CANON_STRIP))
-		cc_prepare_sign(part);
-
-	filter = camel_stream_filter_new_with_stream(ostream);
-	canon = camel_mime_filter_canon_new(flags);
-	camel_stream_filter_add(filter, canon);
-	camel_object_unref(canon);
-
-	if (camel_data_wrapper_write_to_stream((CamelDataWrapper *)part, (CamelStream *)filter) != -1
-	    && camel_stream_flush((CamelStream *)filter) != -1)
-		res = 0;
-
-	camel_object_unref(filter);
-	camel_stream_reset(ostream);
-
-	return res;
-}
diff --git a/camel/camel-cipher-context.h b/camel/camel-cipher-context.h
deleted file mode 100644
index 1a7387ac2c..0000000000
--- a/camel/camel-cipher-context.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *
- *  Copyright 2001 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef CAMEL_CIPHER_CONTEXT_H
-#define CAMEL_CIPHER_CONTEXT_H
-
-#include 
-#include 
-
-/* FIXME: camelise */
-#include "e-util/e-msgport.h"
-
-struct _CamelStream;
-struct _CamelMimePart;
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#define CAMEL_CIPHER_CONTEXT_TYPE     (camel_cipher_context_get_type ())
-#define CAMEL_CIPHER_CONTEXT(obj)     (CAMEL_CHECK_CAST((obj), CAMEL_CIPHER_CONTEXT_TYPE, CamelCipherContext))
-#define CAMEL_CIPHER_CONTEXT_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_CIPHER_CONTEXT_TYPE, CamelCipherContextClass))
-#define CAMEL_IS_CIPHER_CONTEXT(o)    (CAMEL_CHECK_TYPE((o), CAMEL_CIPHER_CONTEXT_TYPE))
-
-typedef struct _CamelCipherValidity CamelCipherValidity;
-
-typedef enum {
-	CAMEL_CIPHER_HASH_DEFAULT,
-	CAMEL_CIPHER_HASH_MD2,
-	CAMEL_CIPHER_HASH_MD5,
-	CAMEL_CIPHER_HASH_SHA1,
-	CAMEL_CIPHER_HASH_RIPEMD160,
-	CAMEL_CIPHER_HASH_TIGER192,
-	CAMEL_CIPHER_HASH_HAVAL5160
-} CamelCipherHash;
-
-enum _camel_cipher_validity_sign_t {
-	CAMEL_CIPHER_VALIDITY_SIGN_NONE,
-	CAMEL_CIPHER_VALIDITY_SIGN_GOOD,
-	CAMEL_CIPHER_VALIDITY_SIGN_BAD,
-	CAMEL_CIPHER_VALIDITY_SIGN_UNKNOWN,
-};
-
-enum _camel_cipher_validity_encrypt_t {
-	CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE,
-	CAMEL_CIPHER_VALIDITY_ENCRYPT_WEAK,
-	CAMEL_CIPHER_VALIDITY_ENCRYPT_ENCRYPTED, /* encrypted, unknown strenght */
-	CAMEL_CIPHER_VALIDITY_ENCRYPT_STRONG,
-};
-
-struct _CamelCipherValidity {
-	struct _CamelCipherValidity *next;
-	struct _CamelCipherValidity *prev;
-	EDList children;
-
-	struct {
-		enum _camel_cipher_validity_sign_t status;
-		char *description;
-	} sign;
-	struct {
-		enum _camel_cipher_validity_encrypt_t status;
-		char *description;
-	} encrypt;
-};
-
-typedef struct _CamelCipherContext {
-	CamelObject parent_object;
-	
-	struct _CamelCipherContextPrivate *priv;
-	
-	CamelSession *session;
-	
-	/* these MUST be set by implementors */
-	const char *sign_protocol;
-	const char *encrypt_protocol;
-	const char *key_protocol;
-} CamelCipherContext;
-
-typedef struct _CamelCipherContextClass {
-	CamelObjectClass parent_class;
-	
-	CamelCipherHash	      (*id_to_hash)(CamelCipherContext *context, const char *id);
-	const char *	      (*hash_to_id)(CamelCipherContext *context, CamelCipherHash hash);
-	
-	int                   (*sign)      (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
-					    struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex);
-	
-	CamelCipherValidity * (*verify)    (CamelCipherContext *context, struct _CamelMimePart *ipart, CamelException *ex);
-	
-	int                   (*encrypt)   (CamelCipherContext *context, const char *userid,
-					    GPtrArray *recipients, struct _CamelMimePart *ipart, struct _CamelMimePart *opart,
-					    CamelException *ex);
-	
-	CamelCipherValidity  *(*decrypt)  (CamelCipherContext *context, struct _CamelMimePart *ipart, struct _CamelMimePart *opart,
-					   CamelException *ex);
-	
-	int                   (*import_keys) (CamelCipherContext *context, struct _CamelStream *istream,
-					      CamelException *ex);
-	
-	int                   (*export_keys) (CamelCipherContext *context, GPtrArray *keys,
-					      struct _CamelStream *ostream, CamelException *ex);
-} CamelCipherContextClass;
-
-CamelType            camel_cipher_context_get_type (void);
-
-CamelCipherContext  *camel_cipher_context_new (CamelSession *session);
-
-void                 camel_cipher_context_construct (CamelCipherContext *context, CamelSession *session);
-
-/* cipher context util routines */
-CamelCipherHash	     camel_cipher_id_to_hash (CamelCipherContext *context, const char *id);
-const char *	     camel_cipher_hash_to_id (CamelCipherContext *context, CamelCipherHash hash);
-
-/* FIXME:
-   There are some inconsistencies here, the api's should probably handle CamelMimePart's as input/outputs,
-   Something that might generate a multipart/signed should do it as part of that processing, internally
-   to the cipher, etc etc. */
-
-/* cipher routines */
-int                  camel_cipher_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
-					struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex);
-CamelCipherValidity *camel_cipher_verify (CamelCipherContext *context, struct _CamelMimePart *ipart, CamelException *ex);
-int                  camel_cipher_encrypt (CamelCipherContext *context, const char *userid,
-					   GPtrArray *recipients, struct _CamelMimePart *ipart, struct _CamelMimePart *opart,
-					   CamelException *ex);
-CamelCipherValidity *camel_cipher_decrypt (CamelCipherContext *context, struct _CamelMimePart *ipart, struct _CamelMimePart *opart,
-					   CamelException *ex);
-
-/* key/certificate routines */
-int                  camel_cipher_import_keys (CamelCipherContext *context, struct _CamelStream *istream,
-					       CamelException *ex);
-int                  camel_cipher_export_keys (CamelCipherContext *context, GPtrArray *keys,
-					       struct _CamelStream *ostream, CamelException *ex);
-
-/* CamelCipherValidity utility functions */
-CamelCipherValidity *camel_cipher_validity_new (void);
-void                 camel_cipher_validity_init (CamelCipherValidity *validity);
-gboolean             camel_cipher_validity_get_valid (CamelCipherValidity *validity);
-void                 camel_cipher_validity_set_valid (CamelCipherValidity *validity, gboolean valid);
-char                *camel_cipher_validity_get_description (CamelCipherValidity *validity);
-void                 camel_cipher_validity_set_description (CamelCipherValidity *validity, const char *description);
-void                 camel_cipher_validity_clear (CamelCipherValidity *validity);
-CamelCipherValidity *camel_cipher_validity_clone(CamelCipherValidity *vin);
-void		     camel_cipher_validity_envelope(CamelCipherValidity *valid, CamelCipherValidity *outer);
-void                 camel_cipher_validity_free (CamelCipherValidity *validity);
-
-/* utility functions */
-int		     camel_cipher_canonical_to_stream(CamelMimePart *part, guint32 flags, CamelStream *ostream);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_CIPHER_CONTEXT_H */
diff --git a/camel/camel-data-cache.c b/camel/camel-data-cache.c
deleted file mode 100644
index a585f59a9d..0000000000
--- a/camel/camel-data-cache.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-message-cache.c: Class for a Camel cache.
- *
- * Authors: Michael Zucchi 
- *
- * Copyright (C) 2001 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of version 2 of the GNU General Public 
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#ifdef HAVE_ALLOCA_H
-#include 
-#endif
-
-#include "camel-data-cache.h"
-#include "camel-exception.h"
-#include "camel-stream-fs.h"
-#include "camel-stream-mem.h"
-#include "camel-file-utils.h"
-
-extern int camel_verbose_debug;
-#define dd(x) (camel_verbose_debug?(x):0)
-#define d(x)
-
-/* how many 'bits' of hash are used to key the toplevel directory */
-#define CAMEL_DATA_CACHE_BITS (6)
-#define CAMEL_DATA_CACHE_MASK ((1<add = data_cache_add;
-	klass->get = data_cache_get;
-	klass->close = data_cache_close;
-	klass->remove = data_cache_remove;
-	klass->clear = data_cache_clear;
-#endif
-}
-
-static void data_cache_init(CamelDataCache *cdc, CamelDataCacheClass *klass)
-{
-	struct _CamelDataCachePrivate *p;
-
-	p = cdc->priv = g_malloc0(sizeof(*cdc->priv));
-	p->busy_bag = camel_object_bag_new(g_str_hash, g_str_equal, (CamelCopyFunc)g_strdup, g_free);
-}
-
-static void data_cache_finalise(CamelDataCache *cdc)
-{
-	struct _CamelDataCachePrivate *p;
-
-	p = cdc->priv;
-	camel_object_bag_destroy(p->busy_bag);
-	g_free(p);
-	
-	g_free (cdc->path);
-}
-
-CamelType
-camel_data_cache_get_type(void)
-{
-	static CamelType camel_data_cache_type = CAMEL_INVALID_TYPE;
-	
-	if (camel_data_cache_type == CAMEL_INVALID_TYPE) {
-		camel_data_cache_type = camel_type_register(
-			CAMEL_OBJECT_TYPE, "CamelDataCache",
-			sizeof (CamelDataCache),
-			sizeof (CamelDataCacheClass),
-			(CamelObjectClassInitFunc) data_cache_class_init,
-			NULL,
-			(CamelObjectInitFunc) data_cache_init,
-			(CamelObjectFinalizeFunc) data_cache_finalise);
-	}
-
-	return camel_data_cache_type;
-}
-
-/**
- * camel_data_cache_new:
- * @path: Base path of cache, subdirectories will be created here.
- * @flags: Open flags, none defined.
- * @ex: 
- * 
- * Create a new data cache.
- * 
- * Return value: A new cache object, or NULL if the base path cannot
- * be written to.
- **/
-CamelDataCache *
-camel_data_cache_new(const char *path, guint32 flags, CamelException *ex)
-{
-	CamelDataCache *cdc;
-
-	if (camel_mkdir (path, 0700) == -1) {
-		camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
-				     _("Unable to create cache path"));
-		return NULL;
-	}
-
-	cdc = (CamelDataCache *)camel_object_new(CAMEL_DATA_CACHE_TYPE);
-
-	cdc->path = g_strdup(path);
-	cdc->flags = flags;
-	cdc->expire_age = -1;
-	cdc->expire_access = -1;
-
-	return cdc;
-}
-
-/**
- * camel_data_cache_set_expire_age:
- * @cdc: 
- * @when: Timeout for age expiry, or -1 to disable.
- * 
- * Set the cache expiration policy for aged entries.
- * 
- * Items in the cache older than @when seconds may be
- * flushed at any time.  Items are expired in a lazy
- * manner, so it is indeterminate when the items will
- * physically be removed.
- *
- * Note you can set both an age and an access limit.  The
- * age acts as a hard limit on cache entries.
- **/
-void
-camel_data_cache_set_expire_age(CamelDataCache *cdc, time_t when)
-{
-	cdc->expire_age = when;
-}
-
-/**
- * camel_data_cache_set_expire_access:
- * @cdc: 
- * @when: Timeout for access, or -1 to disable access expiry.
- * 
- * Set the cache expiration policy for access times.
- *
- * Items in the cache which haven't been accessed for @when
- * seconds may be expired at any time.  Items are expired in a lazy
- * manner, so it is indeterminate when the items will
- * physically be removed.
- *
- * Note you can set both an age and an access limit.  The
- * age acts as a hard limit on cache entries.
- **/
-void
-camel_data_cache_set_expire_access(CamelDataCache *cdc, time_t when)
-{
-	cdc->expire_access = when;
-}
-
-static void
-data_cache_expire(CamelDataCache *cdc, const char *path, const char *keep, time_t now)
-{
-	DIR *dir;
-	struct dirent *d;
-	GString *s;
-	struct stat st;
-	CamelStream *stream;
-
-	dir = opendir(path);
-	if (dir == NULL)
-		return;
-
-	s = g_string_new("");
-	while ( (d = readdir(dir)) ) {
-		if (strcmp(d->d_name, keep) == 0)
-			continue;
-		
-		g_string_printf (s, "%s/%s", path, d->d_name);
-		dd(printf("Checking '%s' for expiry\n", s->str));
-		if (stat(s->str, &st) == 0
-		    && S_ISREG(st.st_mode)
-		    && ((cdc->expire_age != -1 && st.st_mtime + cdc->expire_age < now)
-			|| (cdc->expire_access != -1 && st.st_atime + cdc->expire_access < now))) {
-			dd(printf("Has expired!  Removing!\n"));
-			unlink(s->str);
-			stream = camel_object_bag_get(cdc->priv->busy_bag, s->str);
-			if (stream) {
-				camel_object_bag_remove(cdc->priv->busy_bag, stream);
-				camel_object_unref(stream);
-			}
-		}
-	}
-	g_string_free(s, TRUE);
-	closedir(dir);
-}
-
-/* Since we have to stat the directory anyway, we use this opportunity to
-   lazily expire old data.
-   If it is this directories 'turn', and we haven't done it for CYCLE_TIME seconds,
-   then we perform an expiry run */
-static char *
-data_cache_path(CamelDataCache *cdc, int create, const char *path, const char *key)
-{
-	char *dir, *real, *tmp;
-	guint32 hash;
-
-	hash = g_str_hash(key);
-	hash = (hash>>5)&CAMEL_DATA_CACHE_MASK;
-	dir = alloca(strlen(cdc->path) + strlen(path) + 8);
-	sprintf(dir, "%s/%s/%02x", cdc->path, path, hash);
-	if (access(dir, F_OK) == -1) {
-		if (create)
-			camel_mkdir (dir, 0700);
-	} else if (cdc->priv->expire_inc == hash
-		   && (cdc->expire_age != -1 || cdc->expire_access != -1)) {
-		time_t now;
-
-		dd(printf("Checking expire cycle time on dir '%s'\n", dir));
-
-		/* This has a race, but at worst we re-run an expire cycle which is safe */
-		now = time(0);
-		if (cdc->priv->expire_last[hash] + CAMEL_DATA_CACHE_CYCLE_TIME < now) {
-			cdc->priv->expire_last[hash] = now;
-			data_cache_expire(cdc, dir, key, now);
-		}
-		cdc->priv->expire_inc = (cdc->priv->expire_inc + 1) & CAMEL_DATA_CACHE_MASK;
-	}
-
-	tmp = camel_file_util_safe_filename(key);
-	real = g_strdup_printf("%s/%s", dir, tmp);
-	g_free(tmp);
-
-	return real;
-}
-
-/**
- * camel_data_cache_add:
- * @cdc: 
- * @path: Relative path of item to add.
- * @key: Key of item to add.
- * @ex: 
- * 
- * Add a new item to the cache.
- *
- * The key and the path combine to form a unique key used to store
- * the item.
- * 
- * Potentially, expiry processing will be performed while this call
- * is executing.
- *
- * Return value: A CamelStream (file) opened in read-write mode.
- * The caller must unref this when finished.
- **/
-CamelStream *
-camel_data_cache_add(CamelDataCache *cdc, const char *path, const char *key, CamelException *ex)
-{
-	char *real;
-	CamelStream *stream;
-
-	real = data_cache_path(cdc, TRUE, path, key);
-	stream = camel_object_bag_reserve(cdc->priv->busy_bag, real);
-	if (stream) {
-		unlink(real);
-		camel_object_bag_remove(cdc->priv->busy_bag, stream);
-		camel_object_unref(stream);
-	}
-
-	stream = camel_stream_fs_new_with_name(real, O_RDWR|O_CREAT|O_TRUNC, 0600);
-	if (stream)
-		camel_object_bag_add(cdc->priv->busy_bag, real, stream);
-	else
-		camel_object_bag_abort(cdc->priv->busy_bag, real);
-
-	g_free(real);
-
-	return stream;
-}
-
-/**
- * camel_data_cache_get:
- * @cdc: 
- * @path: Path to the (sub) cache the item exists in.
- * @key: Key for the cache item.
- * @ex: 
- * 
- * Lookup an item in the cache.  If the item exists, a stream
- * is returned for the item.  The stream may be shared by
- * multiple callers, so ensure the stream is in a valid state
- * through external locking.
- * 
- * Return value: A cache item, or NULL if the cache item does not exist.
- **/
-CamelStream *
-camel_data_cache_get(CamelDataCache *cdc, const char *path, const char *key, CamelException *ex)
-{
-	char *real;
-	CamelStream *stream;
-
-	real = data_cache_path(cdc, FALSE, path, key);
-	stream = camel_object_bag_reserve(cdc->priv->busy_bag, real);
-	if (!stream) {
-		stream = camel_stream_fs_new_with_name(real, O_RDWR, 0600);
-		if (stream)
-			camel_object_bag_add(cdc->priv->busy_bag, real, stream);
-		else
-			camel_object_bag_abort(cdc->priv->busy_bag, real);
-	}
-	g_free(real);
-
-	return stream;
-}
-
-/**
- * camel_data_cache_remove:
- * @cdc: 
- * @path: 
- * @key: 
- * @ex: 
- * 
- * Remove/expire a cache item.
- * 
- * Return value: 
- **/
-int
-camel_data_cache_remove(CamelDataCache *cdc, const char *path, const char *key, CamelException *ex)
-{
-	CamelStream *stream;
-	char *real;
-	int ret;
-
-	real = data_cache_path(cdc, FALSE, path, key);
-	stream = camel_object_bag_get(cdc->priv->busy_bag, real);
-	if (stream) {
-		camel_object_bag_remove(cdc->priv->busy_bag, stream);
-		camel_object_unref(stream);
-	}
-
-	/* maybe we were a mem stream */
-	if (unlink (real) == -1 && errno != ENOENT) {
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Could not remove cache entry: %s: %s"),
-				      real, g_strerror (errno));
-		ret = -1;
-	} else {
-		ret = 0;
-	}
-
-	g_free(real);
-
-	return ret;
-}
-
-/**
- * camel_data_cache_rename:
- * @cache: 
- * @old: 
- * @new: 
- * @ex: 
- * 
- * Rename a cache path.  All cache items accessed from the old path
- * are accessible using the new path.
- *
- * CURRENTLY UNIMPLEMENTED
- * 
- * Return value: -1 on error.
- **/
-int camel_data_cache_rename(CamelDataCache *cache,
-			    const char *old, const char *new, CamelException *ex)
-{
-	/* blah dont care yet */
-	return -1;
-}
-
-/**
- * camel_data_cache_clear:
- * @cache: 
- * @path: Path to clear, or NULL to clear all items in
- * all paths.
- * @ex: 
- * 
- * Clear all items in a given cache path or all items in the cache.
- * 
- * CURRENTLY_UNIMPLEMENTED
- *
- * Return value: -1 on error.
- **/
-int
-camel_data_cache_clear(CamelDataCache *cache, const char *path, CamelException *ex)
-{
-	/* nor for this? */
-	return -1;
-}
diff --git a/camel/camel-data-cache.h b/camel/camel-data-cache.h
deleted file mode 100644
index ab6c29a622..0000000000
--- a/camel/camel-data-cache.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-data-cache.h: Class for a Camel filesystem cache
- *
- * Authors: Michael Zucchi 
- *
- * Copyright (C) 2001 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of version 2 of the GNU General Public 
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-
-#ifndef CAMEL_DATA_CACHE_H
-#define CAMEL_DATA_CACHE_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus }*/
-
-#include 
-
-#include 
-#include 
-
-#define CAMEL_DATA_CACHE_TYPE     (camel_data_cache_get_type ())
-#define CAMEL_DATA_CACHE(obj)     (CAMEL_CHECK_CAST((obj), CAMEL_DATA_CACHE_TYPE, CamelFolder))
-#define CAMEL_DATA_CACHE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_DATA_CACHE_TYPE, CamelFolderClass))
-#define CAMEL_IS_DATA_CACHE(o)    (CAMEL_CHECK_TYPE((o), CAMEL_DATA_CACHE_TYPE))
-
-typedef struct _CamelDataCache CamelDataCache;
-typedef struct _CamelDataCacheClass CamelDataCacheClass;
-
-struct _CamelDataCache {
-	CamelObject parent_object;
-
-	struct _CamelDataCachePrivate *priv;
-
-	char *path;
-	guint32 flags;
-
-	time_t expire_age;
-	time_t expire_access;
-};
-
-struct _CamelDataCacheClass {
-	CamelObjectClass parent_class;
-
-	/* None are virtual yet */
-#if 0
-	/* Virtual methods */
-	CamelStream *(*add)(CamelDataCache *cmc, const char *path, const char *key, CamelException *ex);
-	CamelStream *(*get)(CamelDataCache *cmc, const char *path, const char *key, CamelException *ex);
-	int (*close)(CamelDataCache *cmc, CamelStream *stream, CamelException *ex);
-	int (*remove)(CamelDataCache *cmc, const char *path, const char *key, CamelException *ex);
-
-	int (*clear)(CamelDataCache *cmc, const char *path, CamelException *ex);
-#endif
-};
-
-/* public methods */
-CamelDataCache *camel_data_cache_new(const char *path, guint32 flags, CamelException *ex);
-
-void camel_data_cache_set_expire_age(CamelDataCache *cache, time_t when);
-void camel_data_cache_set_expire_access(CamelDataCache *cdc, time_t when);
-
-int             camel_data_cache_rename(CamelDataCache *cache,
-					const char *old, const char *new, CamelException *ex);
-
-CamelStream    *camel_data_cache_add(CamelDataCache *cache,
-				     const char *path, const char *key, CamelException *ex);
-CamelStream    *camel_data_cache_get(CamelDataCache *cache,
-				     const char *path, const char *key, CamelException *ex);
-int             camel_data_cache_remove(CamelDataCache *cache,
-					const char *path, const char *key, CamelException *ex);
-
-int             camel_data_cache_clear(CamelDataCache *cache,
-				       const char *path, CamelException *ex);
-
-/* Standard Camel function */
-CamelType camel_data_cache_get_type (void);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_DATA_CACHE_H */
diff --git a/camel/camel-data-wrapper.c b/camel/camel-data-wrapper.c
deleted file mode 100644
index e30cd10927..0000000000
--- a/camel/camel-data-wrapper.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; -*- */
-/*
- *
- * Authors: Bertrand Guiheneuf 
- *
- * Copyright 1999-2003 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-
-#include "camel-data-wrapper.h"
-#include "camel-stream.h"
-#include "camel-stream-filter.h"
-#include "camel-mime-filter-basic.h"
-#include "camel-mime-filter-crlf.h"
-#include "camel-exception.h"
-#include "camel-private.h"
-
-#define d(x)
-
-static CamelObjectClass *parent_class = NULL;
-
-/* Returns the class for a CamelDataWrapper */
-#define CDW_CLASS(so) CAMEL_DATA_WRAPPER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
-
-static int construct_from_stream(CamelDataWrapper *, CamelStream *);
-static ssize_t write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
-static ssize_t decode_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
-static void set_mime_type (CamelDataWrapper *data_wrapper, const char *mime_type);
-static gchar *get_mime_type (CamelDataWrapper *data_wrapper);
-static CamelContentType *get_mime_type_field (CamelDataWrapper *data_wrapper);
-static void set_mime_type_field (CamelDataWrapper *data_wrapper, CamelContentType *mime_type);
-static gboolean is_offline (CamelDataWrapper *data_wrapper);
-
-static void
-camel_data_wrapper_class_init (CamelDataWrapperClass *camel_data_wrapper_class)
-{
-	parent_class = camel_type_get_global_classfuncs (camel_object_get_type ());
-
-	/* virtual method definition */
-	camel_data_wrapper_class->write_to_stream = write_to_stream;
-	camel_data_wrapper_class->decode_to_stream = decode_to_stream;
-	camel_data_wrapper_class->set_mime_type = set_mime_type;
-	camel_data_wrapper_class->get_mime_type = get_mime_type;
-	camel_data_wrapper_class->get_mime_type_field = get_mime_type_field;
-	camel_data_wrapper_class->set_mime_type_field = set_mime_type_field;
-	camel_data_wrapper_class->construct_from_stream = construct_from_stream;
-	camel_data_wrapper_class->is_offline = is_offline;
-}
-
-static void
-camel_data_wrapper_init (gpointer object, gpointer klass)
-{
-	CamelDataWrapper *camel_data_wrapper = CAMEL_DATA_WRAPPER (object);
-	
-	camel_data_wrapper->priv = g_malloc (sizeof (struct _CamelDataWrapperPrivate));
-	pthread_mutex_init (&camel_data_wrapper->priv->stream_lock, NULL);
-	
-	camel_data_wrapper->mime_type = camel_content_type_new ("application", "octet-stream");
-	camel_data_wrapper->encoding = CAMEL_TRANSFER_ENCODING_DEFAULT;
-	camel_data_wrapper->offline = FALSE;
-}
-
-static void
-camel_data_wrapper_finalize (CamelObject *object)
-{
-	CamelDataWrapper *camel_data_wrapper = CAMEL_DATA_WRAPPER (object);
-	
-	pthread_mutex_destroy (&camel_data_wrapper->priv->stream_lock);
-	
-	g_free (camel_data_wrapper->priv);
-	
-	if (camel_data_wrapper->mime_type)
-		camel_content_type_unref (camel_data_wrapper->mime_type);
-	
-	if (camel_data_wrapper->stream)
-		camel_object_unref (camel_data_wrapper->stream);
-}
-
-CamelType
-camel_data_wrapper_get_type (void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-	
-	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register (CAMEL_OBJECT_TYPE,
-					    "CamelDataWrapper",
-					    sizeof (CamelDataWrapper),
-					    sizeof (CamelDataWrapperClass),
-					    (CamelObjectClassInitFunc) camel_data_wrapper_class_init,
-					    NULL,
-					    (CamelObjectInitFunc) camel_data_wrapper_init,
-					    (CamelObjectFinalizeFunc) camel_data_wrapper_finalize);
-	}
-	
-	return type;
-}
-
-
-CamelDataWrapper *
-camel_data_wrapper_new (void)
-{
-	return (CamelDataWrapper *) camel_object_new (CAMEL_DATA_WRAPPER_TYPE);
-}
-
-static ssize_t
-write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
-{
-	ssize_t ret;
-	
-	if (data_wrapper->stream == NULL) {
-		return -1;
-	}
-	
-	CAMEL_DATA_WRAPPER_LOCK (data_wrapper, stream_lock);
-	if (camel_stream_reset (data_wrapper->stream) == -1) {
-		CAMEL_DATA_WRAPPER_UNLOCK (data_wrapper, stream_lock);
-		return -1;
-	}
-	
-	ret = camel_stream_write_to_stream (data_wrapper->stream, stream);
-	
-	CAMEL_DATA_WRAPPER_UNLOCK (data_wrapper, stream_lock);
-	
-	return ret;
-}
-
-/**
- * camel_data_wrapper_write_to_stream:
- * @data_wrapper: a data wrapper
- * @stream: stream for data to be written to
- * @ex: a CamelException
- *
- * Writes the data content to @stream in a machine-independent format
- * appropriate for the data. It should be possible to construct an
- * equivalent data wrapper object later by passing this stream to
- * camel_data_wrapper_construct_from_stream().
- *
- * Return value: the number of bytes written, or -1 if an error
- * occurs.
- **/
-ssize_t
-camel_data_wrapper_write_to_stream (CamelDataWrapper *data_wrapper,
-				    CamelStream *stream)
-{
-	g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
-	g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
-
-	return CDW_CLASS (data_wrapper)->write_to_stream (data_wrapper, stream);
-}
-
-
-static ssize_t
-decode_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
-{
-	CamelMimeFilter *filter;
-	CamelStream *fstream;
-	ssize_t ret;
-	
-	fstream = (CamelStream *) camel_stream_filter_new_with_stream (stream);
-	
-	switch (data_wrapper->encoding) {
-	case CAMEL_TRANSFER_ENCODING_BASE64:
-		filter = (CamelMimeFilter *) camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_BASE64_DEC);
-		camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
-		camel_object_unref (filter);
-		break;
-	case CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE:
-		filter = (CamelMimeFilter *) camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_QP_DEC);
-		camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
-		camel_object_unref (filter);
-		break;
-	case CAMEL_TRANSFER_ENCODING_UUENCODE:
-		filter = (CamelMimeFilter *) camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_UU_DEC);
-		camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
-		camel_object_unref (filter);
-		break;
-	default:
-		break;
-	}
-	
-	if (camel_content_type_is (data_wrapper->mime_type, "text", "*")) {
-		filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE,
-						     CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
-		camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
-		camel_object_unref (filter);
-	}
-	
-	ret = camel_data_wrapper_write_to_stream (data_wrapper, fstream);
-	camel_stream_flush (fstream);
-	camel_object_unref (fstream);
-	
-	return ret;
-}
-
-/**
- * camel_data_wrapper_decode_to_stream:
- * @data_wrapper: a data wrapper
- * @stream: stream for decoded data to be written to
- * @ex: a CamelException
- *
- * Writes the decoded data content to @stream.
- *
- * Return value: the number of bytes written, or -1 if an error
- * occurs.
- **/
-ssize_t
-camel_data_wrapper_decode_to_stream (CamelDataWrapper *data_wrapper,
-				     CamelStream *stream)
-{
-	g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
-	g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
-	
-	return CDW_CLASS (data_wrapper)->decode_to_stream (data_wrapper, stream);
-}
-
-
-static int
-construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
-{
-	if (data_wrapper->stream)
-		camel_object_unref (data_wrapper->stream);
-	
-	data_wrapper->stream = stream;
-	camel_object_ref (stream);
-	return 0;
-}
-
-/**
- * camel_data_wrapper_construct_from_stream:
- * @data_wrapper: a data wrapper
- * @stream: A stream that can be read from.
- *
- * Constructs the content of the data wrapper from the
- * supplied @stream.
- *
- * Return value: -1 on error.
- **/
-int
-camel_data_wrapper_construct_from_stream (CamelDataWrapper *data_wrapper,
-					  CamelStream *stream)
-{
-	g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
-	g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
-	
-	return CDW_CLASS (data_wrapper)->construct_from_stream (data_wrapper, stream);
-}
-
-
-static void
-set_mime_type (CamelDataWrapper *data_wrapper, const char *mime_type)
-{
-	if (data_wrapper->mime_type)
-		camel_content_type_unref (data_wrapper->mime_type);
-	data_wrapper->mime_type = camel_content_type_decode (mime_type);
-}
-
-/**
- * camel_data_wrapper_set_mime_type:
- * @data_wrapper: a data wrapper
- * @mime_type: the text representation of a MIME type
- *
- * This sets the data wrapper's MIME type.
- * It might fail, but you won't know. It will allow you to set
- * Content-Type parameters on the data wrapper, which are meaningless.
- * You should not be allowed to change the MIME type of a data wrapper
- * that contains data, or at least, if you do, it should invalidate the
- * data.
- **/
-void
-camel_data_wrapper_set_mime_type (CamelDataWrapper *data_wrapper,
-				  const char *mime_type)
-{
-	g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
-	g_return_if_fail (mime_type != NULL);
-
-	CDW_CLASS (data_wrapper)->set_mime_type (data_wrapper, mime_type);
-}
-
-static char *
-get_mime_type (CamelDataWrapper *data_wrapper)
-{
-	return camel_content_type_simple (data_wrapper->mime_type);
-}
-
-/**
- * camel_data_wrapper_get_mime_type:
- * @data_wrapper: a data wrapper
- *
- * Return value: the text form of the data wrapper's MIME type,
- * which the caller must free.
- **/
-char *
-camel_data_wrapper_get_mime_type (CamelDataWrapper *data_wrapper)
-{
-	g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), NULL);
-
-	return CDW_CLASS (data_wrapper)->get_mime_type (data_wrapper);
-}
-
-
-static CamelContentType *
-get_mime_type_field (CamelDataWrapper *data_wrapper)
-{
-	return data_wrapper->mime_type;
-}
-
-/**
- * camel_data_wrapper_get_mime_type_field:
- * @data_wrapper: a data wrapper
- *
- * Return value: the parsed form of the data wrapper's MIME type
- **/
-CamelContentType *
-camel_data_wrapper_get_mime_type_field (CamelDataWrapper *data_wrapper)
-{
-	g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), NULL);
-
-	return CDW_CLASS (data_wrapper)->get_mime_type_field (data_wrapper);
-}
-
-/**
- * camel_data_wrapper_set_mime_type_field:
- * @data_wrapper: a data wrapper
- * @mime_type: the parsed representation of a MIME type
- *
- * This sets the data wrapper's MIME type. It suffers from the same
- * flaws as camel_data_wrapper_set_mime_type.
- **/
-static void
-set_mime_type_field (CamelDataWrapper *data_wrapper,
-		     CamelContentType *mime_type)
-{
-	g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
-	g_return_if_fail (mime_type != NULL);
-
-	if (data_wrapper->mime_type)
-		camel_content_type_unref (data_wrapper->mime_type);
-	data_wrapper->mime_type = mime_type;
-	if (mime_type)
-		camel_content_type_ref (data_wrapper->mime_type);
-}
-
-void
-camel_data_wrapper_set_mime_type_field (CamelDataWrapper *data_wrapper,
-					CamelContentType *mime_type)
-{
-	CDW_CLASS (data_wrapper)->set_mime_type_field (data_wrapper, mime_type);
-}
-
-
-static gboolean
-is_offline (CamelDataWrapper *data_wrapper)
-{
-	return data_wrapper->offline;
-}
-
-/**
- * camel_data_wrapper_is_offline:
- * @data_wrapper: a data wrapper
- *
- * Return value: whether @data_wrapper is "offline" (data stored
- * remotely) or not. Some optional code paths may choose to not
- * operate on offline data.
- **/
-gboolean
-camel_data_wrapper_is_offline (CamelDataWrapper *data_wrapper)
-{
-	return CDW_CLASS (data_wrapper)->is_offline (data_wrapper);
-}
diff --git a/camel/camel-data-wrapper.h b/camel/camel-data-wrapper.h
deleted file mode 100644
index 1e22595019..0000000000
--- a/camel/camel-data-wrapper.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Bertrand Guiheneuf 
- *           Michael Zucchi 
- *           Jeffrey Stedfast 
- *
- *  Copyright 1999-2003 Ximian, Inc. (www.ximian.com)
- *
- *  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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-
-#ifndef CAMEL_DATA_WRAPPER_H
-#define CAMEL_DATA_WRAPPER_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include 
-#include 
-#include 
-#include 
-
-#define CAMEL_DATA_WRAPPER_TYPE     (camel_data_wrapper_get_type ())
-#define CAMEL_DATA_WRAPPER(obj)     (CAMEL_CHECK_CAST((obj), CAMEL_DATA_WRAPPER_TYPE, CamelDataWrapper))
-#define CAMEL_DATA_WRAPPER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_DATA_WRAPPER_TYPE, CamelDataWrapperClass))
-#define CAMEL_IS_DATA_WRAPPER(o)    (CAMEL_CHECK_TYPE((o), CAMEL_DATA_WRAPPER_TYPE))
-
-struct _CamelDataWrapper {
-	CamelObject parent_object;
-	struct _CamelDataWrapperPrivate *priv;
-	
-	CamelTransferEncoding encoding;
-	
-	CamelContentType *mime_type;
-	CamelStream *stream;
-	
-	unsigned int offline:1;
-};
-
-typedef struct {
-	CamelObjectClass parent_class;
-	
-	/* Virtual methods */
-	void                (*set_mime_type)          (CamelDataWrapper *data_wrapper,
-						       const char *mime_type);
-	char *              (*get_mime_type)          (CamelDataWrapper *data_wrapper);
-	CamelContentType *  (*get_mime_type_field)    (CamelDataWrapper *data_wrapper);
-	void                (*set_mime_type_field)    (CamelDataWrapper *data_wrapper,
-						       CamelContentType *mime_type_field);
-	
-	ssize_t             (*write_to_stream)        (CamelDataWrapper *data_wrapper,
-						       CamelStream *stream);
-	
-	ssize_t             (*decode_to_stream)       (CamelDataWrapper *data_wrapper,
-						       CamelStream *stream);
-	
-	int                 (*construct_from_stream)  (CamelDataWrapper *data_wrapper,
-						       CamelStream *);
-	
-	gboolean            (*is_offline)             (CamelDataWrapper *data_wrapper);
-} CamelDataWrapperClass;
-
-/* Standard Camel function */
-CamelType camel_data_wrapper_get_type (void);
-
-/* public methods */
-CamelDataWrapper *camel_data_wrapper_new(void);
-ssize_t           camel_data_wrapper_write_to_stream        (CamelDataWrapper *data_wrapper,
-							     CamelStream *stream);
-ssize_t           camel_data_wrapper_decode_to_stream       (CamelDataWrapper *data_wrapper,
-							     CamelStream *stream);
-
-void              camel_data_wrapper_set_mime_type          (CamelDataWrapper *data_wrapper,
-							     const char *mime_type);
-char             *camel_data_wrapper_get_mime_type          (CamelDataWrapper *data_wrapper);
-CamelContentType *camel_data_wrapper_get_mime_type_field    (CamelDataWrapper *data_wrapper);
-void              camel_data_wrapper_set_mime_type_field    (CamelDataWrapper *data_wrapper,
-							     CamelContentType *mime_type);
-
-int               camel_data_wrapper_construct_from_stream  (CamelDataWrapper *data_wrapper,
-							     CamelStream *stream);
-
-gboolean          camel_data_wrapper_is_offline             (CamelDataWrapper *data_wrapper);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_DATA_WRAPPER_H */
diff --git a/camel/camel-digest-folder.c b/camel/camel-digest-folder.c
deleted file mode 100644
index b2c81b5d4d..0000000000
--- a/camel/camel-digest-folder.c
+++ /dev/null
@@ -1,396 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *
- *  Copyright 2001-2003 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include "camel-digest-folder.h"
-#include "camel-digest-summary.h"
-
-#include "camel-exception.h"
-#include "camel-multipart.h"
-#include "camel-mime-message.h"
-#include "camel-folder-search.h"
-
-#define d(x)
-
-#define _PRIVATE(o) (((CamelDigestFolder *)(o))->priv)
-
-struct _CamelDigestFolderPrivate {
-	CamelMimeMessage *message;
-	CamelFolderSearch *search;
-	GMutex *search_lock;
-};
-
-#define CAMEL_DIGEST_FOLDER_LOCK(f, l) (g_mutex_lock(((CamelDigestFolder *)f)->priv->l))
-#define CAMEL_DIGEST_FOLDER_UNLOCK(f, l) (g_mutex_unlock(((CamelDigestFolder *)f)->priv->l))
-
-static CamelFolderClass *parent_class = NULL;
-
-static void digest_refresh_info (CamelFolder *folder, CamelException *ex);
-static void digest_sync (CamelFolder *folder, gboolean expunge, CamelException *ex);
-static const char *digest_get_full_name (CamelFolder *folder);
-static void digest_expunge (CamelFolder *folder, CamelException *ex);
-
-/* message manipulation */
-static CamelMimeMessage *digest_get_message (CamelFolder *folder, const gchar *uid,
-					     CamelException *ex);
-static void digest_append_message (CamelFolder *folder, CamelMimeMessage *message,
-				   const CamelMessageInfo *info, char **appended_uid, CamelException *ex);
-static void digest_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
-					 CamelFolder *dest, GPtrArray **transferred_uids,
-					 gboolean delete_originals, CamelException *ex);
-
-static GPtrArray *digest_search_by_expression (CamelFolder *folder, const char *expression,
-					       CamelException *ex);
-
-static GPtrArray *digest_search_by_uids (CamelFolder *folder, const char *expression,
-					 GPtrArray *uids, CamelException *ex);
-
-static void digest_search_free (CamelFolder *folder, GPtrArray *result);
-
-static void
-camel_digest_folder_class_init (CamelDigestFolderClass *camel_digest_folder_class)
-{
-	CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_digest_folder_class);
-	
-	parent_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_folder_get_type ()));
-	
-	/* virtual method definition */
-	
-	/* virtual method overload */
-	camel_folder_class->refresh_info = digest_refresh_info;
-	camel_folder_class->sync = digest_sync;
-	camel_folder_class->expunge = digest_expunge;
-	camel_folder_class->get_full_name = digest_get_full_name;
-	
-	camel_folder_class->get_message = digest_get_message;
-	camel_folder_class->append_message = digest_append_message;
-	camel_folder_class->transfer_messages_to = digest_transfer_messages_to;
-	
-	camel_folder_class->search_by_expression = digest_search_by_expression;
-	camel_folder_class->search_by_uids = digest_search_by_uids;
-	camel_folder_class->search_free = digest_search_free;
-}
-
-static void
-camel_digest_folder_init (gpointer object, gpointer klass)
-{
-	CamelDigestFolder *digest_folder = CAMEL_DIGEST_FOLDER (object);
-	CamelFolder *folder = CAMEL_FOLDER (object);
-	
-	folder->folder_flags |= CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | CAMEL_FOLDER_HAS_SEARCH_CAPABILITY;
-	
-	folder->summary = camel_digest_summary_new ();
-	
-	digest_folder->priv = g_new (struct _CamelDigestFolderPrivate, 1);
-	digest_folder->priv->message = NULL;
-	digest_folder->priv->search = NULL;
-	digest_folder->priv->search_lock = g_mutex_new ();
-}
-
-static void
-digest_finalize (CamelObject *object)
-{
-	CamelDigestFolder *digest_folder = CAMEL_DIGEST_FOLDER (object);
-	CamelFolder *folder = CAMEL_FOLDER (object);
-	
-	if (folder->summary) {
-		camel_object_unref (folder->summary);
-		folder->summary = NULL;
-	}
-	
-	camel_object_unref (digest_folder->priv->message);
-	
-	if (digest_folder->priv->search)
-		camel_object_unref (digest_folder->priv->search);
-	
-	g_mutex_free (digest_folder->priv->search_lock);
-	
-	g_free (digest_folder->priv);
-}
-
-CamelType
-camel_digest_folder_get_type (void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-	
-	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register (CAMEL_FOLDER_TYPE,
-					    "CamelDigestFolder",
-					    sizeof (CamelDigestFolder),
-					    sizeof (CamelDigestFolderClass),
-					    (CamelObjectClassInitFunc) camel_digest_folder_class_init,
-					    NULL,
-					    (CamelObjectInitFunc) camel_digest_folder_init,
-					    (CamelObjectFinalizeFunc) digest_finalize);
-	}
-	
-	return type;
-}
-
-static gboolean
-multipart_contains_message_parts (CamelMultipart *multipart)
-{
-	gboolean has_message_parts = FALSE;
-	CamelDataWrapper *wrapper;
-	CamelMimePart *part;
-	int i, parts;
-	
-	parts = camel_multipart_get_number (multipart);
-	for (i = 0; i < parts && !has_message_parts; i++) {
-		part = camel_multipart_get_part (multipart, i);
-		wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
-		if (CAMEL_IS_MULTIPART (wrapper)) {
-			has_message_parts = multipart_contains_message_parts (CAMEL_MULTIPART (wrapper));
-		} else if (CAMEL_IS_MIME_MESSAGE (wrapper)) {
-			has_message_parts = TRUE;
-		}
-	}
-	
-	return has_message_parts;
-}
-
-static void
-digest_add_multipart (CamelFolder *folder, CamelMultipart *multipart, const char *preuid)
-{
-	CamelDataWrapper *wrapper;
-	CamelMessageInfo *info;
-	CamelMimePart *part;
-	int parts, i;
-	char *uid;
-	
-	parts = camel_multipart_get_number (multipart);
-	for (i = 0; i < parts; i++) {
-		part = camel_multipart_get_part (multipart, i);
-		
-		wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
-		
-		if (CAMEL_IS_MULTIPART (wrapper)) {
-			uid = g_strdup_printf ("%s%d.", preuid, i);
-			digest_add_multipart (folder, CAMEL_MULTIPART (wrapper), uid);
-			g_free (uid);
-			continue;
-		} else if (!CAMEL_IS_MIME_MESSAGE (wrapper)) {
-			continue;
-		}
-		
-		info = camel_folder_summary_info_new_from_message (folder->summary, CAMEL_MIME_MESSAGE (wrapper));
-		
-		uid = g_strdup_printf ("%s%d", preuid, i);
-		camel_message_info_set_uid (info, uid);
-		camel_folder_summary_add (folder->summary, info);
-	}
-}
-
-static void
-construct_summary (CamelFolder *folder, CamelMultipart *multipart)
-{
-	digest_add_multipart (folder, multipart, "");
-}
-
-CamelFolder *
-camel_digest_folder_new (CamelStore *parent_store, CamelMimeMessage *message)
-{
-	CamelDigestFolder *digest_folder;
-	CamelDataWrapper *wrapper;
-	CamelFolder *folder;
-	
-	wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (message));
-	if (!wrapper || !CAMEL_IS_MULTIPART (wrapper))
-		return NULL;
-	
-	/* Make sure we have a multipart/digest subpart or at least some message/rfc822 attachments... */
-	if (!camel_content_type_is (CAMEL_DATA_WRAPPER (message)->mime_type, "multipart", "digest")) {
-		if (!multipart_contains_message_parts (CAMEL_MULTIPART (wrapper)))
-			return NULL;
-	}
-	
-	folder = CAMEL_FOLDER (camel_object_new (camel_digest_folder_get_type ()));
-	digest_folder = CAMEL_DIGEST_FOLDER (folder);
-	
-	camel_folder_construct (folder, parent_store, "folder_name", "short_name");
-	
-	camel_object_ref (message);
-	digest_folder->priv->message = message;
-	
-	construct_summary (folder, CAMEL_MULTIPART (wrapper));
-	
-	return folder;
-}
-
-static void
-digest_refresh_info (CamelFolder *folder, CamelException *ex)
-{
-	
-}
-
-static void
-digest_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
-{
-	/* no-op */
-}
-
-static void
-digest_expunge (CamelFolder *folder, CamelException *ex)
-{
-	/* no-op */
-}
-
-static const char *
-digest_get_full_name (CamelFolder *folder)
-{
-	return folder->full_name;
-}
-
-static void
-digest_append_message (CamelFolder *folder, CamelMimeMessage *message,
-		       const CamelMessageInfo *info, char **appended_uid,
-		       CamelException *ex)
-{
-	/* no-op */
-	if (appended_uid)
-		*appended_uid = NULL;
-}
-
-static void
-digest_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
-			     CamelFolder *dest, GPtrArray **transferred_uids,
-			     gboolean delete_originals, CamelException *ex)
-{
-	/* no-op */
-	if (transferred_uids)
-		*transferred_uids = NULL;
-}
-
-static CamelMimeMessage *
-digest_get_message (CamelFolder *folder, const char *uid, CamelException *ex)
-{
-	CamelDigestFolder *digest = CAMEL_DIGEST_FOLDER (folder);
-	CamelDataWrapper *wrapper;
-	CamelMimeMessage *message;
-	CamelMimePart *part;
-	char *subuid;
-	int id;
-	
-	part = CAMEL_MIME_PART (digest->priv->message);
-	wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
-	
-	do {
-		id = strtoul (uid, &subuid, 10);
-		if (!CAMEL_IS_MULTIPART (wrapper))
-			return NULL;
-		
-		part = camel_multipart_get_part (CAMEL_MULTIPART (wrapper), id);
-		wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
-		uid = subuid + 1;
-	} while (*subuid == '.');
-	
-	if (!CAMEL_IS_MIME_MESSAGE (wrapper))
-		return NULL;
-	
-	message = CAMEL_MIME_MESSAGE (wrapper);
-	camel_object_ref (message);
-	
-	return message;
-}
-
-
-static GPtrArray *
-digest_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex)
-{
-	CamelDigestFolder *df = (CamelDigestFolder *) folder;
-	CamelFolderSearch *search;
-	GPtrArray *summary, *matches;
-	
-	summary = camel_folder_get_summary (folder);
-	
-	CAMEL_DIGEST_FOLDER_LOCK (folder, search_lock);
-	
-	if (!df->priv->search)
-		df->priv->search = camel_folder_search_new ();
-	
-	search = df->priv->search;
-	camel_folder_search_set_folder (search, folder);
-	camel_folder_search_set_summary (search, summary);
-	
-	matches = camel_folder_search_execute_expression (search, expression, ex);
-	
-	CAMEL_DIGEST_FOLDER_UNLOCK (folder, search_lock);
-	
-	camel_folder_free_summary (folder, summary);
-	
-	return matches;
-}
-
-static GPtrArray *
-digest_search_by_uids (CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex)
-{
-	CamelDigestFolder *df = (CamelDigestFolder *) folder;
-	CamelFolderSearch *search;
-	GPtrArray *summary, *matches;
-	int i;
-	
-	summary = g_ptr_array_new ();
-	for (i = 0; i < uids->len; i++) {
-		CamelMessageInfo *info;
-		
-		info = camel_folder_get_message_info (folder, uids->pdata[i]);
-		if (info)
-			g_ptr_array_add (summary, info);
-	}
-	
-	if (summary->len == 0)
-		return summary;
-	
-	CAMEL_DIGEST_FOLDER_LOCK (folder, search_lock);
-	
-	if (!df->priv->search)
-		df->priv->search = camel_folder_search_new ();
-	
-	search = df->priv->search;
-	camel_folder_search_set_folder (search, folder);
-	camel_folder_search_set_summary (search, summary);
-	
-	matches = camel_folder_search_execute_expression (search, expression, ex);
-	
-	CAMEL_DIGEST_FOLDER_UNLOCK (folder, search_lock);
-	
-	for (i = 0; i < summary->len; i++)
-		camel_folder_free_message_info (folder, summary->pdata[i]);
-	g_ptr_array_free (summary, TRUE);
-	
-	return matches;
-}
-
-static void
-digest_search_free (CamelFolder *folder, GPtrArray *result)
-{
-	CamelDigestFolder *digest_folder = CAMEL_DIGEST_FOLDER (folder);
-	
-	CAMEL_DIGEST_FOLDER_LOCK (folder, search_lock);
-	
-	camel_folder_search_free_result (digest_folder->priv->search, result);
-	
-	CAMEL_DIGEST_FOLDER_UNLOCK (folder, search_lock);
-}
diff --git a/camel/camel-digest-folder.h b/camel/camel-digest-folder.h
deleted file mode 100644
index 1035930f56..0000000000
--- a/camel/camel-digest-folder.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *
- *  Copyright 2001 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef _CAMEL_DIGEST_FOLDER_H
-#define _CAMEL_DIGEST_FOLDER_H
-
-#include 
-#include 
-#include 
-#include 
-
-#define CAMEL_DIGEST_FOLDER(obj)         CAMEL_CHECK_CAST (obj, camel_digest_folder_get_type (), CamelDigestFolder)
-#define CAMEL_DIGEST_FOLDER_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_digest_folder_get_type (), CamelDigestFolderClass)
-#define CAMEL_IS_DIGEST_FOLDER(obj)      CAMEL_CHECK_TYPE (obj, camel_digest_folder_get_type ())
-
-typedef struct _CamelDigestFolderClass CamelDigestFolderClass;
-
-struct _CamelDigestFolder {
-	CamelFolder parent;
-	
-	struct _CamelDigestFolderPrivate *priv;
-};
-
-struct _CamelDigestFolderClass {
-	CamelFolderClass parent_class;
-	
-};
-
-CamelType    camel_digest_folder_get_type (void);
-
-CamelFolder *camel_digest_folder_new      (CamelStore *parent_store, CamelMimeMessage *message);
-
-#endif /* ! _CAMEL_DIGEST_FOLDER_H */
diff --git a/camel/camel-digest-store.c b/camel/camel-digest-store.c
deleted file mode 100644
index 833593ac9f..0000000000
--- a/camel/camel-digest-store.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *
- *  Copyright 2002 Ximian, Inc. (www.ximian.com)
- *
- *  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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-
-#include "camel-exception.h"
-#include "camel-digest-store.h"
-#include "camel-digest-folder.h"
-
-#include "camel-private.h"
-
-#define d(x)
-
-static CamelFolder *digest_get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex);
-static void digest_delete_folder (CamelStore *store, const char *folder_name, CamelException *ex);
-static void digest_rename_folder (CamelStore *store, const char *old, const char *new, CamelException *ex);
-static void digest_init_trash (CamelStore *store);
-static CamelFolder *digest_get_trash  (CamelStore *store, CamelException *ex);
-static void digest_init_junk (CamelStore *store);
-static CamelFolder *digest_get_junk  (CamelStore *store, CamelException *ex);
-
-static CamelFolderInfo *digest_get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex);
-
-static void camel_digest_store_class_init (CamelDigestStoreClass *klass);
-static void camel_digest_store_init       (CamelDigestStore *obj);
-static void camel_digest_store_finalise   (CamelObject *obj);
-
-static int digest_setv (CamelObject *object, CamelException *ex, CamelArgV *args);
-static int digest_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args);
-
-static CamelStoreClass *parent_class = NULL;
-
-
-CamelType
-camel_digest_store_get_type (void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-	
-	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register (camel_store_get_type (),
-					    "CamelDigestStore",
-					    sizeof (CamelDigestStore),
-					    sizeof (CamelDigestStoreClass),
-					    (CamelObjectClassInitFunc) camel_digest_store_class_init,
-					    NULL,
-					    (CamelObjectInitFunc) camel_digest_store_init,
-					    (CamelObjectFinalizeFunc) camel_digest_store_finalise);
-	}
-	
-	return type;
-}
-
-static void
-camel_digest_store_class_init (CamelDigestStoreClass *klass)
-{
-	CamelObjectClass *object_class = (CamelObjectClass *) klass;
-	CamelStoreClass *store_class = (CamelStoreClass *) klass;
-	
-	parent_class = CAMEL_STORE_CLASS(camel_type_get_global_classfuncs (camel_store_get_type ()));
-	
-	/* virtual method overload */
-	object_class->setv = digest_setv;
-	object_class->getv = digest_getv;
-	
-	store_class->get_folder = digest_get_folder;
-	store_class->rename_folder = digest_rename_folder;
-	store_class->delete_folder = digest_delete_folder;
-	store_class->get_folder_info = digest_get_folder_info;
-	store_class->free_folder_info = camel_store_free_folder_info_full;
-	
-	store_class->init_trash = digest_init_trash;
-	store_class->get_trash = digest_get_trash;
-	store_class->init_junk = digest_init_junk;
-	store_class->get_junk = digest_get_junk;
-}
-
-static void
-camel_digest_store_init (CamelDigestStore *obj)
-{
-	CamelStore *store = (CamelStore *) obj;
-	
-	/* we dont want a vtrash and vjunk on this one */
-	store->flags &= ~(CAMEL_STORE_VTRASH | CAMEL_STORE_VJUNK);	
-}
-
-static void
-camel_digest_store_finalise (CamelObject *obj)
-{
-	
-}
-
-static int
-digest_setv (CamelObject *object, CamelException *ex, CamelArgV *args)
-{
-	/* CamelDigestStore doesn't currently have anything to set */
-	return CAMEL_OBJECT_CLASS (parent_class)->setv (object, ex, args);
-}
-
-static int
-digest_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args)
-{
-	/* CamelDigestStore doesn't currently have anything to get */
-	return CAMEL_OBJECT_CLASS (parent_class)->getv (object, ex, args);
-}
-
-
-/**
- * camel_digest_store_new:
- * @url:
- *
- * Create a new CamelDigestStore object.
- * 
- * Return value: A new CamelDigestStore widget.
- **/
-CamelStore *
-camel_digest_store_new (const char *url)
-{
-	CamelStore *store;
-	CamelURL *uri;
-	
-	uri = camel_url_new (url, NULL);
-	if (!uri)
-		return NULL;
-	
-	store = CAMEL_STORE (camel_object_new (camel_digest_store_get_type ()));
-	CAMEL_SERVICE (store)->url = uri;
-	
-	return store;
-}
-
-static CamelFolder *
-digest_get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex)
-{
-	return NULL;
-}
-
-static void
-digest_init_trash (CamelStore *store)
-{
-	/* no-op */
-	;
-}
-
-static CamelFolder *
-digest_get_trash (CamelStore *store, CamelException *ex)
-{
-	return NULL;
-}
-
-static void
-digest_init_junk (CamelStore *store)
-{
-	/* no-op */
-	;
-}
-
-static CamelFolder *
-digest_get_junk (CamelStore *store, CamelException *ex)
-{
-	return NULL;
-}
-
-static CamelFolderInfo *
-digest_get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex)
-{
-	return NULL;
-}
-
-static void
-digest_delete_folder (CamelStore *store, const char *folder_name, CamelException *ex)
-{
-	
-}
-
-static void
-digest_rename_folder (CamelStore *store, const char *old, const char *new, CamelException *ex)
-{
-	
-}
diff --git a/camel/camel-digest-store.h b/camel/camel-digest-store.h
deleted file mode 100644
index 90e802f09f..0000000000
--- a/camel/camel-digest-store.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *
- *  Copyright 2002 Ximian, Inc. (www.ximian.com)
- *
- *  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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-
-#ifndef __CAMEL_DIGEST_STORE_H__
-#define __CAMEL_DIGEST_STORE_H__
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include 
-#include 
-
-#define CAMEL_DIGEST_STORE(obj)         CAMEL_CHECK_CAST (obj, camel_digest_store_get_type (), CamelDigestStore)
-#define CAMEL_DIGEST_STORE_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_digest_store_get_type (), CamelDigestStoreClass)
-#define CAMEL_IS_DIGEST_STORE(obj)      CAMEL_CHECK_TYPE (obj, camel_digest_store_get_type ())
-
-typedef struct _CamelDigestStoreClass CamelDigestStoreClass;
-
-struct _CamelDigestStore {
-	CamelStore parent;
-	
-};
-
-struct _CamelDigestStoreClass {
-	CamelStoreClass parent_class;
-	
-};
-
-CamelType camel_digest_store_get_type (void);
-
-CamelStore *camel_digest_store_new (const char *url);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __CAMEL_DIGEST_STORE_H__ */
diff --git a/camel/camel-digest-summary.c b/camel/camel-digest-summary.c
deleted file mode 100644
index f17867e083..0000000000
--- a/camel/camel-digest-summary.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *
- *  Copyright 2002 Ximian, Inc. (www.ximian.com)
- *
- *  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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include "camel-digest-summary.h"
-
-#define CAMEL_DIGEST_SUMMARY_VERSION 0
-
-static void camel_digest_summary_class_init (CamelDigestSummaryClass *klass);
-static void camel_digest_summary_init       (CamelDigestSummary *obj);
-static void camel_digest_summary_finalise   (CamelObject *obj);
-
-
-static CamelFolderSummaryClass *parent_class = NULL;
-
-
-CamelType
-camel_digest_summary_get_type(void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-	
-	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register (
-			camel_folder_summary_get_type (),
-			"CamelDigestSummary",
-			sizeof (CamelDigestSummary),
-			sizeof (CamelDigestSummaryClass),
-			(CamelObjectClassInitFunc) camel_digest_summary_class_init,
-			NULL,
-			(CamelObjectInitFunc) camel_digest_summary_init,
-			(CamelObjectFinalizeFunc) camel_digest_summary_finalise);
-	}
-	
-	return type;
-}
-
-static void
-camel_digest_summary_class_init (CamelDigestSummaryClass *klass)
-{
-	parent_class = CAMEL_FOLDER_SUMMARY_CLASS (camel_type_get_global_classfuncs (camel_folder_summary_get_type ()));
-}
-
-static void
-camel_digest_summary_init (CamelDigestSummary *summary)
-{
-	CamelFolderSummary *s = (CamelFolderSummary *) summary;
-	
-	/* subclasses need to set the right instance data sizes */
-	s->message_info_size = sizeof (CamelMessageInfo);
-	s->content_info_size = sizeof (CamelMessageContentInfo);
-	
-	/* and a unique file version */
-	s->version += CAMEL_DIGEST_SUMMARY_VERSION;
-}
-
-static void
-camel_digest_summary_finalise (CamelObject *object)
-{
-	
-}
-
-
-CamelFolderSummary *
-camel_digest_summary_new (void)
-{
-	return (CamelFolderSummary *) camel_object_new (camel_digest_summary_get_type ());
-}
diff --git a/camel/camel-digest-summary.h b/camel/camel-digest-summary.h
deleted file mode 100644
index 16bf5e5c9f..0000000000
--- a/camel/camel-digest-summary.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *
- *  Copyright 2002 Ximian, Inc. (www.ximian.com)
- *
- *  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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-
-#ifndef __CAMEL_DIGEST_SUMMARY_H__
-#define __CAMEL_DIGEST_SUMMARY_H__
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include 
-#include 
-#include 
-
-#define CAMEL_DIGEST_SUMMARY(obj)         CAMEL_CHECK_CAST (obj, camel_digest_summary_get_type (), CamelDigestSummary)
-#define CAMEL_DIGEST_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_digest_summary_get_type (), CamelDigestSummaryClass)
-#define CAMEL_IS_DIGEST_SUMMARY(obj)      CAMEL_CHECK_TYPE (obj, camel_digest_summary_get_type ())
-
-typedef struct _CamelDigestSummary      CamelDigestSummary;
-typedef struct _CamelDigestSummaryClass CamelDigestSummaryClass;
-
-struct _CamelDigestSummary {
-	CamelFolderSummary parent_object;
-	
-};
-
-struct _CamelDigestSummaryClass {
-	CamelFolderSummaryClass parent_class;
-	
-};
-
-
-CamelType camel_digest_summary_get_type (void);
-
-CamelFolderSummary *camel_digest_summary_new (void);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __CAMEL_DIGEST_SUMMARY_H__ */
diff --git a/camel/camel-disco-diary.c b/camel/camel-disco-diary.c
deleted file mode 100644
index 927a97f432..0000000000
--- a/camel/camel-disco-diary.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-disco-diary.c: class for a disconnected operation log */
-
-/* 
- * Authors: Dan Winship 
- *
- * Copyright (C) 2001 Ximian, Inc.
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of version 2 of the GNU General Public 
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#define __USE_LARGEFILE 1
-#include 
-#include 
-
-#include "camel-disco-diary.h"
-#include "camel-disco-folder.h"
-#include "camel-disco-store.h"
-#include "camel-exception.h"
-#include "camel-file-utils.h"
-#include "camel-folder.h"
-#include "camel-operation.h"
-#include "camel-session.h"
-#include "camel-store.h"
-
-
-static void
-camel_disco_diary_class_init (CamelDiscoDiaryClass *camel_disco_diary_class)
-{
-	/* virtual method definition */
-}
-
-static void
-camel_disco_diary_init (CamelDiscoDiary *diary)
-{
-	diary->folders = g_hash_table_new (g_str_hash, g_str_equal);
-	diary->uidmap = g_hash_table_new (g_str_hash, g_str_equal);
-}
-
-static void
-unref_folder (gpointer key, gpointer value, gpointer data)
-{
-	camel_object_unref (value);
-}
-
-static void
-free_uid (gpointer key, gpointer value, gpointer data)
-{
-	g_free (key);
-	g_free (value);
-}
-
-static void
-camel_disco_diary_finalize (CamelDiscoDiary *diary)
-{
-	if (diary->file)
-		fclose (diary->file);
-	if (diary->folders) {
-		g_hash_table_foreach (diary->folders, unref_folder, NULL);
-		g_hash_table_destroy (diary->folders);
-	}
-	if (diary->uidmap) {
-		g_hash_table_foreach (diary->uidmap, free_uid, NULL);
-		g_hash_table_destroy (diary->uidmap);
-	}
-}
-
-CamelType
-camel_disco_diary_get_type (void)
-{
-	static CamelType camel_disco_diary_type = CAMEL_INVALID_TYPE;
-
-	if (camel_disco_diary_type == CAMEL_INVALID_TYPE) {
-		camel_disco_diary_type = camel_type_register (
-			CAMEL_OBJECT_TYPE, "CamelDiscoDiary",
-			sizeof (CamelDiscoDiary),
-			sizeof (CamelDiscoDiaryClass),
-			(CamelObjectClassInitFunc) camel_disco_diary_class_init,
-			NULL,
-			(CamelObjectInitFunc) camel_disco_diary_init,
-			(CamelObjectFinalizeFunc) camel_disco_diary_finalize);
-	}
-
-	return camel_disco_diary_type;
-}
-
-
-static int
-diary_encode_uids (CamelDiscoDiary *diary, GPtrArray *uids)
-{
-	int i, status;
-
-	status = camel_file_util_encode_uint32 (diary->file, uids->len);
-	for (i = 0; status != -1 && i < uids->len; i++)
-		status = camel_file_util_encode_string (diary->file, uids->pdata[i]);
-	return status;
-}
-
-void
-camel_disco_diary_log (CamelDiscoDiary *diary, CamelDiscoDiaryAction action,
-		       ...)
-{
-	va_list ap;
-	int status;
-
-	/* You may already be a loser. */
-	if (!diary->file)
-		return;
-
-	status = camel_file_util_encode_uint32 (diary->file, action);
-	if (status == -1)
-		goto lose;
-
-	va_start (ap, action);
-	switch (action) {
-	case CAMEL_DISCO_DIARY_FOLDER_EXPUNGE:
-	{
-		CamelFolder *folder = va_arg (ap, CamelFolder *);
-		GPtrArray *uids = va_arg (ap, GPtrArray *);
-
-		status = camel_file_util_encode_string (diary->file, folder->full_name);
-		if (status != -1)
-			status = diary_encode_uids (diary, uids);
-		break;
-	}
-
-	case CAMEL_DISCO_DIARY_FOLDER_APPEND:
-	{
-		CamelFolder *folder = va_arg (ap, CamelFolder *);
-		char *uid = va_arg (ap, char *);
-
-		status = camel_file_util_encode_string (diary->file, folder->full_name);
-		if (status != -1)
-			status = camel_file_util_encode_string (diary->file, uid);
-		break;
-	}
-
-	case CAMEL_DISCO_DIARY_FOLDER_TRANSFER:
-	{
-		CamelFolder *source = va_arg (ap, CamelFolder *);
-		CamelFolder *destination = va_arg (ap, CamelFolder *);
-		GPtrArray *uids = va_arg (ap, GPtrArray *);
-		gboolean delete_originals = va_arg (ap, gboolean);
-
-		status = camel_file_util_encode_string (diary->file, source->full_name);
-		if (status == -1)
-			break;
-		status = camel_file_util_encode_string (diary->file, destination->full_name);
-		if (status == -1)
-			break;
-		status = diary_encode_uids (diary, uids);
-		if (status == -1)
-			break;
-		status = camel_file_util_encode_uint32 (diary->file, delete_originals);
-		break;
-	}
-
-	default:
-		g_assert_not_reached ();
-		break;
-	}
-
-	va_end (ap);
-
- lose:
-	if (status == -1) {
-		char *msg;
-
-		msg = g_strdup_printf (_("Could not write log entry: %s\n"
-					 "Further operations on this server "
-					 "will not be replayed when you\n"
-					 "reconnect to the network."),
-				       g_strerror (errno));
-		camel_session_alert_user (camel_service_get_session (CAMEL_SERVICE (diary->store)),
-					  CAMEL_SESSION_ALERT_ERROR,
-					  msg, FALSE);
-		g_free (msg);
-
-		fclose (diary->file);
-		diary->file = NULL;
-	}
-}
-
-static void
-free_uids (GPtrArray *array)
-{
-	while (array->len--)
-		g_free (array->pdata[array->len]);
-	g_ptr_array_free (array, TRUE);
-}
-
-static GPtrArray *
-diary_decode_uids (CamelDiscoDiary *diary)
-{
-	GPtrArray *uids;
-	char *uid;
-	guint32 i;
-
-	if (camel_file_util_decode_uint32 (diary->file, &i) == -1)
-		return NULL;
-	uids = g_ptr_array_new ();
-	while (i--) {
-		if (camel_file_util_decode_string (diary->file, &uid) == -1) {
-			free_uids (uids);
-			return NULL;
-		}
-		g_ptr_array_add (uids, uid);
-	}
-
-	return uids;
-}
-
-static CamelFolder *
-diary_decode_folder (CamelDiscoDiary *diary)
-{
-	CamelFolder *folder;
-	char *name;
-
-	if (camel_file_util_decode_string (diary->file, &name) == -1)
-		return NULL;
-	folder = g_hash_table_lookup (diary->folders, name);
-	if (!folder) {
-		CamelException ex;
-		char *msg;
-
-		camel_exception_init (&ex);
-		folder = camel_store_get_folder (CAMEL_STORE (diary->store),
-						 name, 0, &ex);
-		if (folder)
-			g_hash_table_insert (diary->folders, name, folder);
-		else {
-			msg = g_strdup_printf (_("Could not open `%s':\n%s\nChanges made to this folder will not be resynchronized."),
-					       name, camel_exception_get_description (&ex));
-			camel_exception_clear (&ex);
-			camel_session_alert_user (camel_service_get_session (CAMEL_SERVICE (diary->store)),
-						  CAMEL_SESSION_ALERT_WARNING,
-						  msg, FALSE);
-			g_free (msg);
-			g_free (name);
-		}
-	} else
-		g_free (name);
-	return folder;
-}
-
-static void
-close_folder (gpointer name, gpointer folder, gpointer data)
-{
-	g_free (name);
-	camel_folder_sync (folder, FALSE, NULL);
-	camel_object_unref (folder);
-}
-
-void
-camel_disco_diary_replay (CamelDiscoDiary *diary, CamelException *ex)
-{
-	guint32 action;
-	off_t size;
-	double pc;
-
-	fseek (diary->file, 0, SEEK_END);
-	size = ftell (diary->file);
-	g_return_if_fail (size != 0);
-	rewind (diary->file);
-
-	camel_operation_start (NULL, _("Resynchronizing with server"));
-	while (!camel_exception_is_set (ex)) {
-		pc = ftell (diary->file) / size;
-		camel_operation_progress (NULL, pc * 100);
-
-		if (camel_file_util_decode_uint32 (diary->file, &action) == -1)
-			break;
-		if (action == CAMEL_DISCO_DIARY_END)
-			break;
-
-		switch (action) {
-		case CAMEL_DISCO_DIARY_FOLDER_EXPUNGE:
-		{
-			CamelFolder *folder;
-			GPtrArray *uids;
-
-			folder = diary_decode_folder (diary);
-			uids = diary_decode_uids (diary);
-			if (!uids)
-				goto lose;
-
-			if (folder)
-				camel_disco_folder_expunge_uids (folder, uids, ex);
-			free_uids (uids);
-			break;
-		}
-
-		case CAMEL_DISCO_DIARY_FOLDER_APPEND:
-		{
-			CamelFolder *folder;
-			char *uid, *ret_uid;
-			CamelMimeMessage *message;
-			CamelMessageInfo *info;
-
-			folder = diary_decode_folder (diary);
-			if (camel_file_util_decode_string (diary->file, &uid) == -1)
-				goto lose;
-
-			if (!folder) {
-				g_free (uid);
-				continue;
-			}
-
-			message = camel_folder_get_message (folder, uid, NULL);
-			if (!message) {
-				/* The message was appended and then deleted. */
-				g_free (uid);
-				continue;
-			}
-			info = camel_folder_get_message_info (folder, uid);
-
-			camel_folder_append_message (folder, message, info, &ret_uid, ex);
-			camel_folder_free_message_info (folder, info);
-
-			if (ret_uid) {
-				camel_disco_diary_uidmap_add (diary, uid, ret_uid);
-				g_free (ret_uid);
-			}
-			g_free (uid);
-
-			break;
-		}
-
-		case CAMEL_DISCO_DIARY_FOLDER_TRANSFER:
-		{
-			CamelFolder *source, *destination;
-			GPtrArray *uids, *ret_uids;
-			guint32 delete_originals;
-			int i;
-
-			source = diary_decode_folder (diary);
-			destination = diary_decode_folder (diary);
-			uids = diary_decode_uids (diary);
-			if (!uids)
-				goto lose;
-			if (camel_file_util_decode_uint32 (diary->file, &delete_originals) == -1)
-				goto lose;
-
-			if (!source || !destination) {
-				free_uids (uids);
-				continue;
-			}
-
-			camel_folder_transfer_messages_to (source, uids, destination, &ret_uids, delete_originals, ex);
-
-			if (ret_uids) {
-				for (i = 0; i < uids->len; i++) {
-					if (!ret_uids->pdata[i])
-						continue;
-					camel_disco_diary_uidmap_add (diary, uids->pdata[i], ret_uids->pdata[i]);
-					g_free (ret_uids->pdata[i]);
-				}
-				g_ptr_array_free (ret_uids, TRUE);
-			}
-			free_uids (uids);
-			break;
-		}
-
-		}
-	}
-
- lose:
-	camel_operation_end (NULL);
-
-	/* Close folders */
-	g_hash_table_foreach (diary->folders, close_folder, diary);
-	g_hash_table_destroy (diary->folders);
-	diary->folders = NULL;
-
-	/* Truncate the log */
-	ftruncate (fileno (diary->file), 0);
-}
-
-CamelDiscoDiary *
-camel_disco_diary_new (CamelDiscoStore *store, const char *filename, CamelException *ex)
-{
-	CamelDiscoDiary *diary;
-
-	g_return_val_if_fail (CAMEL_IS_DISCO_STORE (store), NULL);
-	g_return_val_if_fail (filename != NULL, NULL);
-
-	diary = CAMEL_DISCO_DIARY (camel_object_new (CAMEL_DISCO_DIARY_TYPE));
-	diary->store = store;
-
-	diary->file = fopen (filename, "a+");
-	if (!diary->file) {
-		camel_object_unref (diary);
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-				      "Could not open journal file: %s",
-				      g_strerror (errno));
-		return NULL;
-	}
-
-	return diary;
-}
-
-gboolean
-camel_disco_diary_empty  (CamelDiscoDiary *diary)
-{
-	return ftell (diary->file) == 0;
-}
-
-void
-camel_disco_diary_uidmap_add (CamelDiscoDiary *diary, const char *old_uid,
-			      const char *new_uid)
-{
-	g_hash_table_insert (diary->uidmap, g_strdup (old_uid),
-			     g_strdup (new_uid));
-}
-
-const char *
-camel_disco_diary_uidmap_lookup (CamelDiscoDiary *diary, const char *uid)
-{
-	return g_hash_table_lookup (diary->uidmap, uid);
-}
diff --git a/camel/camel-disco-diary.h b/camel/camel-disco-diary.h
deleted file mode 100644
index b177d8ef6f..0000000000
--- a/camel/camel-disco-diary.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * camel-disco-diary.h: class for logging disconnected operation
- *
- * Authors: Dan Winship 
- *
- * Copyright 2001 Ximian, Inc.
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of version 2 of the GNU General Public 
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-#ifndef CAMEL_DISCO_DIARY_H
-#define CAMEL_DISCO_DIARY_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus }*/
-
-#include "camel-object.h"
-#include 
-#include 
-
-#define CAMEL_DISCO_DIARY_TYPE     (camel_disco_diary_get_type ())
-#define CAMEL_DISCO_DIARY(obj)     (CAMEL_CHECK_CAST((obj), CAMEL_DISCO_DIARY_TYPE, CamelDiscoDiary))
-#define CAMEL_DISCO_DIARY_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_DISCO_DIARY_TYPE, CamelDiscoDiaryClass))
-#define CAMEL_IS_DISCO_DIARY(o)    (CAMEL_CHECK_TYPE((o), CAMEL_DISCO_DIARY_TYPE))
-
-typedef enum {
-	CAMEL_DISCO_DIARY_END = 0,
-
-	CAMEL_DISCO_DIARY_FOLDER_EXPUNGE,
-	CAMEL_DISCO_DIARY_FOLDER_APPEND,
-	CAMEL_DISCO_DIARY_FOLDER_TRANSFER,
-} CamelDiscoDiaryAction;
-
-typedef enum {
-	CAMEL_DISCO_DIARY_ARG_NONE = 0,
-
-	CAMEL_DISCO_DIARY_ARG_FOLDER,
-	CAMEL_DISCO_DIARY_ARG_UID,
-	CAMEL_DISCO_DIARY_ARG_UID_LIST
-} CamelDiscoDiaryArgType;
-
-struct _CamelDiscoDiary {
-	CamelObject parent_object;
-
-	CamelDiscoStore *store;
-	FILE *file;
-	GHashTable *folders, *uidmap;
-};
-
-typedef struct {
-	CamelObjectClass parent_class;
-
-} CamelDiscoDiaryClass;
-
-
-/* public methods */
-CamelDiscoDiary *camel_disco_diary_new    (CamelDiscoStore *store,
-					   const char *filename,
-					   CamelException *ex);
-
-gboolean         camel_disco_diary_empty  (CamelDiscoDiary *diary);
-
-void             camel_disco_diary_log    (CamelDiscoDiary *diary,
-					   CamelDiscoDiaryAction action,
-					   ...);
-void             camel_disco_diary_replay (CamelDiscoDiary *diary,
-					   CamelException *ex);
-
-/* Temporary->Permanent UID map stuff */
-void        camel_disco_diary_uidmap_add    (CamelDiscoDiary *diary,
-					     const char *old_uid,
-					     const char *new_uid);
-const char *camel_disco_diary_uidmap_lookup (CamelDiscoDiary *diary,
-					     const char *uid);
-
-/* Standard Camel function */
-CamelType camel_disco_diary_get_type (void);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_DISCO_DIARY_H */
diff --git a/camel/camel-disco-folder.c b/camel/camel-disco-folder.c
deleted file mode 100644
index 61e825020c..0000000000
--- a/camel/camel-disco-folder.c
+++ /dev/null
@@ -1,399 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-disco-folder.c: abstract class for a disconnectable folder */
-
-/* 
- * Authors: Dan Winship 
- *
- * Copyright (C) 2001 Ximian, Inc.
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of version 2 of the GNU General Public 
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include "camel-disco-folder.h"
-#include "camel-disco-store.h"
-#include "camel-exception.h"
-
-#include "camel-session.h"
-
-#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS (o)))
-#define CDF_CLASS(o) (CAMEL_DISCO_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS (o)))
-
-static CamelFolderClass *parent_class = NULL;
-
-static void disco_refresh_info (CamelFolder *folder, CamelException *ex);
-static void disco_sync (CamelFolder *folder, gboolean expunge, CamelException *ex);
-static void disco_expunge (CamelFolder *folder, CamelException *ex);
-
-static void disco_append_message (CamelFolder *folder, CamelMimeMessage *message,
-				  const CamelMessageInfo *info, char **appended_uid, CamelException *ex);
-static void disco_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
-					CamelFolder *destination,
-					GPtrArray **transferred_uids,
-					gboolean delete_originals,
-					CamelException *ex);
-
-static void disco_cache_message       (CamelDiscoFolder *disco_folder,
-				       const char *uid, CamelException *ex);
-static void disco_prepare_for_offline (CamelDiscoFolder *disco_folder,
-				       const char *expression,
-				       CamelException *ex);
-
-static void
-camel_disco_folder_class_init (CamelDiscoFolderClass *camel_disco_folder_class)
-{
-	CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_disco_folder_class);
-
-	parent_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_folder_get_type ()));
-
-	/* virtual method definition */
-	camel_disco_folder_class->cache_message = disco_cache_message;
-	camel_disco_folder_class->prepare_for_offline = disco_prepare_for_offline;
-
-	/* virtual method overload */
-	camel_folder_class->refresh_info = disco_refresh_info;
-	camel_folder_class->sync = disco_sync;
-	camel_folder_class->expunge = disco_expunge;
-
-	camel_folder_class->append_message = disco_append_message;
-	camel_folder_class->transfer_messages_to = disco_transfer_messages_to;
-}
-
-struct _cdf_sync_msg {
-	CamelSessionThreadMsg msg;
-
-	CamelFolder *folder;
-	CamelFolderChangeInfo *changes;
-};
-
-static void
-cdf_sync_offline(CamelSession *session, CamelSessionThreadMsg *mm)
-{
-	struct _cdf_sync_msg *m = (struct _cdf_sync_msg *)mm;
-	int i;
-
-	camel_operation_start(NULL, _("Downloading new messages for offline mode"));
-
-	if (m->changes) {
-		for (i=0;ichanges->uid_added->len;i++) {
-			int pc = i * 100 / m->changes->uid_added->len;
-
-			camel_operation_progress(NULL, pc);
-			camel_disco_folder_cache_message((CamelDiscoFolder *)m->folder,
-							 m->changes->uid_added->pdata[i],
-							 &mm->ex);
-		}
-	} else {
-		camel_disco_folder_prepare_for_offline((CamelDiscoFolder *)m->folder,
-						       "(match-all)",
-						       &mm->ex);
-	}
-
-	camel_operation_end(NULL);
-}
-
-static void
-cdf_sync_free(CamelSession *session, CamelSessionThreadMsg *mm)
-{
-	struct _cdf_sync_msg *m = (struct _cdf_sync_msg *)mm;
-
-	if (m->changes)
-		camel_folder_change_info_free(m->changes);
-	camel_object_unref(m->folder);
-}
-
-static CamelSessionThreadOps cdf_sync_ops = {
-	cdf_sync_offline,
-	cdf_sync_free,
-};
-
-static void
-cdf_folder_changed(CamelFolder *folder, CamelFolderChangeInfo *changes, void *dummy)
-{
-	if (changes->uid_added->len > 0
-	    && camel_url_get_param(((CamelService *)folder->parent_store)->url, "offline_sync")) {
-		CamelSession *session = ((CamelService *)folder->parent_store)->session;
-		struct _cdf_sync_msg *m;
-
-		m = camel_session_thread_msg_new(session, &cdf_sync_ops, sizeof(*m));
-		m->changes = camel_folder_change_info_new();
-		camel_folder_change_info_cat(m->changes, changes);
-		m->folder = folder;
-		camel_object_ref(folder);
-		camel_session_thread_queue(session, &m->msg, 0);
-	}
-}
-
-static void
-camel_disco_folder_init(CamelDiscoFolder *folder)
-{
-	camel_object_hook_event(folder, "folder_changed", (CamelObjectEventHookFunc)cdf_folder_changed, NULL);
-}
-
-CamelType
-camel_disco_folder_get_type (void)
-{
-	static CamelType camel_disco_folder_type = CAMEL_INVALID_TYPE;
-
-	if (camel_disco_folder_type == CAMEL_INVALID_TYPE) {
-		camel_disco_folder_type = camel_type_register (
-			CAMEL_FOLDER_TYPE, "CamelDiscoFolder",
-			sizeof (CamelDiscoFolder),
-			sizeof (CamelDiscoFolderClass),
-			(CamelObjectClassInitFunc)camel_disco_folder_class_init, NULL,
-			(CamelObjectInitFunc)camel_disco_folder_init, NULL);
-	}
-
-	return camel_disco_folder_type;
-}
-
-
-static void
-disco_refresh_info (CamelFolder *folder, CamelException *ex)
-{
-	if (camel_disco_store_status (CAMEL_DISCO_STORE (folder->parent_store)) != CAMEL_DISCO_STORE_ONLINE)
-		return;
-	CDF_CLASS (folder)->refresh_info_online (folder, ex);
-}
-
-static void
-disco_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
-{
-	if (expunge) {
-		disco_expunge (folder, ex);
-		if (camel_exception_is_set (ex))
-			return;
-	}
-
-	switch (camel_disco_store_status (CAMEL_DISCO_STORE (folder->parent_store))) {
-	case CAMEL_DISCO_STORE_ONLINE:
-		CDF_CLASS (folder)->sync_online (folder, ex);
-		break;
-
-	case CAMEL_DISCO_STORE_OFFLINE:
-		CDF_CLASS (folder)->sync_offline (folder, ex);
-		break;
-
-	case CAMEL_DISCO_STORE_RESYNCING:
-		CDF_CLASS (folder)->sync_resyncing (folder, ex);
-		break;
-	}
-}
-
-static void
-disco_expunge_uids (CamelFolder *folder, GPtrArray *uids, CamelException *ex)
-{
-	CamelDiscoStore *disco = CAMEL_DISCO_STORE (folder->parent_store);
-
-	if (uids->len == 0)
-		return;
-
-	switch (camel_disco_store_status (disco)) {
-	case CAMEL_DISCO_STORE_ONLINE:
-		CDF_CLASS (folder)->expunge_uids_online (folder, uids, ex);
-		break;
-
-	case CAMEL_DISCO_STORE_OFFLINE:
-		CDF_CLASS (folder)->expunge_uids_offline (folder, uids, ex);
-		break;
-
-	case CAMEL_DISCO_STORE_RESYNCING:
-		CDF_CLASS (folder)->expunge_uids_resyncing (folder, uids, ex);
-		break;
-	}
-}
-
-static void
-disco_expunge (CamelFolder *folder, CamelException *ex)
-{
-	GPtrArray *uids;
-	int i, count;
-	CamelMessageInfo *info;
-
-	uids = g_ptr_array_new ();
-	count = camel_folder_summary_count (folder->summary);
-	for (i = 0; i < count; i++) {
-		info = camel_folder_summary_index (folder->summary, i);
-		if (info->flags & CAMEL_MESSAGE_DELETED)
-			g_ptr_array_add (uids, g_strdup (camel_message_info_uid (info)));
-		camel_folder_summary_info_free (folder->summary, info);
-	}
-
-	disco_expunge_uids (folder, uids, ex);
-
-	for (i = 0; i < uids->len; i++)
-		g_free (uids->pdata[i]);
-	g_ptr_array_free (uids, TRUE);
-}
-
-static void
-disco_append_message (CamelFolder *folder, CamelMimeMessage *message,
-		      const CamelMessageInfo *info, char **appended_uid,
-		      CamelException *ex)
-{
-	CamelDiscoStore *disco = CAMEL_DISCO_STORE (folder->parent_store);
-
-	switch (camel_disco_store_status (disco)) {
-	case CAMEL_DISCO_STORE_ONLINE:
-		CDF_CLASS (folder)->append_online (folder, message, info,
-						   appended_uid, ex);
-		break;
-
-	case CAMEL_DISCO_STORE_OFFLINE:
-		CDF_CLASS (folder)->append_offline (folder, message, info,
-						    appended_uid, ex);
-		break;
-
-	case CAMEL_DISCO_STORE_RESYNCING:
-		CDF_CLASS (folder)->append_resyncing (folder, message, info,
-						      appended_uid, ex);
-		break;
-	}
-}
-
-static void
-disco_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
-			    CamelFolder *dest, GPtrArray **transferred_uids,
-			    gboolean delete_originals, CamelException *ex)
-{
-	CamelDiscoStore *disco = CAMEL_DISCO_STORE (source->parent_store);
-
-	switch (camel_disco_store_status (disco)) {
-	case CAMEL_DISCO_STORE_ONLINE:
-		CDF_CLASS (source)->transfer_online (source, uids,
-						     dest, transferred_uids,
-						     delete_originals, ex);
-		break;
-
-	case CAMEL_DISCO_STORE_OFFLINE:
-		CDF_CLASS (source)->transfer_offline (source, uids,
-						      dest, transferred_uids,
-						      delete_originals, ex);
-		break;
-
-	case CAMEL_DISCO_STORE_RESYNCING:
-		CDF_CLASS (source)->transfer_resyncing (source, uids,
-							dest, transferred_uids,
-							delete_originals, ex);
-		break;
-	}
-}
-
-
-/**
- * camel_disco_folder_expunge_uids:
- * @folder: a (disconnectable) folder
- * @uids: array of UIDs to expunge
- * @ex: a CamelException
- *
- * This expunges the messages in @uids from @folder. It should take
- * whatever steps are needed to avoid expunging any other messages,
- * although in some cases it may not be possible to avoid expunging
- * messages that are marked deleted by another client at the same time
- * as the expunge_uids call is running.
- **/
-void
-camel_disco_folder_expunge_uids (CamelFolder *folder, GPtrArray *uids,
-				 CamelException *ex)
-{
-	disco_expunge_uids (folder, uids, ex);
-}
-
-
-static void
-disco_cache_message (CamelDiscoFolder *disco_folder, const char *uid,
-		     CamelException *ex)
-{
-	g_warning ("CamelDiscoFolder::cache_message not implemented for `%s'",
-		   camel_type_to_name (CAMEL_OBJECT_GET_TYPE (disco_folder)));
-}
-
-/**
- * camel_disco_folder_cache_message:
- * @disco_folder: the folder
- * @uid: the UID of the message to cache
- * @ex: a CamelException
- *
- * Requests that @disco_folder cache message @uid to disk.
- **/
-void
-camel_disco_folder_cache_message (CamelDiscoFolder *disco_folder,
-				  const char *uid, CamelException *ex)
-{
-	CDF_CLASS (disco_folder)->cache_message (disco_folder, uid, ex);
-}
-
-
-static void
-disco_prepare_for_offline (CamelDiscoFolder *disco_folder,
-			   const char *expression,
-			   CamelException *ex)
-{
-	CamelFolder *folder = CAMEL_FOLDER (disco_folder);
-	GPtrArray *uids;
-	int i;
-
-	camel_operation_start(NULL, _("Preparing folder '%s' for offline"), folder->full_name);
-
-	if (expression)
-		uids = camel_folder_search_by_expression (folder, expression, ex);
-	else
-		uids = camel_folder_get_uids (folder);
-
-	if (!uids) {
-		camel_operation_end(NULL);
-		return;
-	}
-
-	for (i = 0; i < uids->len; i++) {
-		int pc = i * 100 / uids->len;
-
-		camel_disco_folder_cache_message (disco_folder, uids->pdata[i], ex);
-		camel_operation_progress(NULL, pc);
-		if (camel_exception_is_set (ex))
-			break;
-	}
-
-	if (expression)
-		camel_folder_search_free (folder, uids);
-	else
-		camel_folder_free_uids (folder, uids);
-
-	camel_operation_end(NULL);
-}
-
-/**
- * camel_disco_folder_prepare_for_offline:
- * @disco_folder: the folder
- * @expression: an expression describing messages to synchronize, or %NULL
- * if all messages should be sync'ed.
- * @ex: a CamelException
- *
- * This prepares @disco_folder for offline operation, by downloading
- * the bodies of all messages described by @expression (using the
- * same syntax as camel_folder_search_by_expression() ).
- **/
-void 
-camel_disco_folder_prepare_for_offline (CamelDiscoFolder *disco_folder,
-					const char *expression,
-					CamelException *ex)
-{
-	g_return_if_fail (CAMEL_IS_DISCO_FOLDER (disco_folder));
-
-	CDF_CLASS (disco_folder)->prepare_for_offline (disco_folder, expression, ex);
-}
diff --git a/camel/camel-disco-folder.h b/camel/camel-disco-folder.h
deleted file mode 100644
index 0d857c0b9b..0000000000
--- a/camel/camel-disco-folder.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * camel-disco-folder.h: Abstract class for a disconnectable folder
- *
- * Authors: Dan Winship 
- *
- * Copyright 2001 Ximian, Inc.
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of version 2 of the GNU General Public 
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-#ifndef CAMEL_DISCO_FOLDER_H
-#define CAMEL_DISCO_FOLDER_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus }*/
-
-#include "camel-folder.h"
-
-#define CAMEL_DISCO_FOLDER_TYPE     (camel_disco_folder_get_type ())
-#define CAMEL_DISCO_FOLDER(obj)     (CAMEL_CHECK_CAST((obj), CAMEL_DISCO_FOLDER_TYPE, CamelDiscoFolder))
-#define CAMEL_DISCO_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_DISCO_FOLDER_TYPE, CamelDiscoFolderClass))
-#define CAMEL_IS_DISCO_FOLDER(o)    (CAMEL_CHECK_TYPE((o), CAMEL_DISCO_FOLDER_TYPE))
-
-struct _CamelDiscoFolder {
-	CamelFolder parent_object;
-
-};
-
-typedef struct {
-	CamelFolderClass parent_class;
-
-	void (*refresh_info_online) (CamelFolder *folder, CamelException *ex);
-
-	void (*sync_online)    (CamelFolder *folder, CamelException *ex);
-	void (*sync_offline)   (CamelFolder *folder, CamelException *ex);
-	void (*sync_resyncing) (CamelFolder *folder, CamelException *ex);
-
-	void (*expunge_uids_online)    (CamelFolder *folder, GPtrArray *uids,
-					CamelException *ex);
-	void (*expunge_uids_offline)   (CamelFolder *folder, GPtrArray *uids,
-					CamelException *ex);
-	void (*expunge_uids_resyncing) (CamelFolder *folder, GPtrArray *uids,
-					CamelException *ex);
-
-	void (*append_online)    (CamelFolder *folder,
-				  CamelMimeMessage *message,
-				  const CamelMessageInfo *info,
-				  char **appended_uid,
-				  CamelException *ex);
-	void (*append_offline)   (CamelFolder *folder,
-				  CamelMimeMessage *message,
-				  const CamelMessageInfo *info,
-				  char **appended_uid,
-				  CamelException *ex);
-	void (*append_resyncing) (CamelFolder *folder,
-				  CamelMimeMessage *message,
-				  const CamelMessageInfo *info,
-				  char **appended_uid,
-				  CamelException *ex);
-
-	void (*transfer_online)    (CamelFolder *source, GPtrArray *uids,
-				    CamelFolder *destination,
-				    GPtrArray **transferred_uids,
-				    gboolean delete_originals,
-				    CamelException *ex);
-	void (*transfer_offline)   (CamelFolder *source, GPtrArray *uids,
-				    CamelFolder *destination,
-				    GPtrArray **transferred_uids,
-				    gboolean delete_originals,
-				    CamelException *ex);
-	void (*transfer_resyncing) (CamelFolder *source, GPtrArray *uids,
-				    CamelFolder *destination,
-				    GPtrArray **transferred_uids,
-				    gboolean delete_originals,
-				    CamelException *ex);
-
-	void (*cache_message)       (CamelDiscoFolder *disco_folder,
-				     const char *uid, CamelException *ex);
-	void (*prepare_for_offline) (CamelDiscoFolder *disco_folder,
-				     const char *expression,
-				     CamelException *ex);
-
-	void (*update_uid) (CamelFolder *folder, const char *old_uid,
-			    const char *new_uid);
-} CamelDiscoFolderClass;
-
-
-/* public methods */
-void camel_disco_folder_expunge_uids (CamelFolder *folder, GPtrArray *uids,
-				      CamelException *ex);
-
-void camel_disco_folder_cache_message       (CamelDiscoFolder *disco_folder,
-					     const char *uid,
-					     CamelException *ex);
-void camel_disco_folder_prepare_for_offline (CamelDiscoFolder *disco_folder,
-					     const char *expression,
-					     CamelException *ex);
-
-/* Standard Camel function */
-CamelType camel_disco_folder_get_type (void);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_DISCO_FOLDER_H */
diff --git a/camel/camel-disco-store.c b/camel/camel-disco-store.c
deleted file mode 100644
index 7afff575b1..0000000000
--- a/camel/camel-disco-store.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-disco-store.c: abstract class for a disconnectable store */
-
-/*
- *  Authors: Dan Winship 
- *
- *  Copyright 2001 Ximian, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include "camel-disco-store.h"
-#include "camel-disco-diary.h"
-#include "camel-exception.h"
-#include "camel-session.h"
-
-#define CDS_CLASS(o) (CAMEL_DISCO_STORE_CLASS (CAMEL_OBJECT_GET_CLASS (o)))
-
-static CamelStoreClass *parent_class = NULL;
-
-static void disco_construct (CamelService *service, CamelSession *session,
-			     CamelProvider *provider, CamelURL *url,
-			     CamelException *ex);
-static gboolean disco_connect (CamelService *service, CamelException *ex);
-static void disco_cancel_connect (CamelService *service);
-static gboolean disco_disconnect (CamelService *service, gboolean clean, CamelException *ex);
-static CamelFolder *disco_get_folder (CamelStore *store, const char *name,
-				      guint32 flags, CamelException *ex);
-static CamelFolderInfo *disco_get_folder_info (CamelStore *store,
-					       const char *top, guint32 flags,
-					       CamelException *ex);
-static void set_status (CamelDiscoStore *disco_store,
-			CamelDiscoStoreStatus status,
-			CamelException *ex);
-static gboolean can_work_offline (CamelDiscoStore *disco_store);
-
-static int disco_setv (CamelObject *object, CamelException *ex, CamelArgV *args);
-static int disco_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args);
-
-static void
-camel_disco_store_class_init (CamelDiscoStoreClass *camel_disco_store_class)
-{
-	CamelObjectClass *camel_object_class =
-		CAMEL_OBJECT_CLASS (camel_disco_store_class);
-	CamelServiceClass *camel_service_class =
-		CAMEL_SERVICE_CLASS (camel_disco_store_class);
-	CamelStoreClass *camel_store_class =
-		CAMEL_STORE_CLASS (camel_disco_store_class);
-	
-	parent_class = CAMEL_STORE_CLASS (camel_type_get_global_classfuncs (camel_store_get_type ()));
-	
-	/* virtual method definition */
-	camel_disco_store_class->set_status = set_status;
-	camel_disco_store_class->can_work_offline = can_work_offline;
-	
-	/* virtual method overload */
-	camel_object_class->setv = disco_setv;
-	camel_object_class->getv = disco_getv;
-	
-	camel_service_class->construct = disco_construct;
-	camel_service_class->connect = disco_connect;
-	camel_service_class->disconnect = disco_disconnect;
-	camel_service_class->cancel_connect = disco_cancel_connect;
-	
-	camel_store_class->get_folder = disco_get_folder;
-	camel_store_class->get_folder_info = disco_get_folder_info;
-}
-
-CamelType
-camel_disco_store_get_type (void)
-{
-	static CamelType camel_disco_store_type = CAMEL_INVALID_TYPE;
-	
-	if (camel_disco_store_type == CAMEL_INVALID_TYPE) {
-		camel_disco_store_type = camel_type_register (
-			CAMEL_STORE_TYPE,
-			"CamelDiscoStore",
-			sizeof (CamelDiscoStore),
-			sizeof (CamelDiscoStoreClass),
-			(CamelObjectClassInitFunc) camel_disco_store_class_init,
-			NULL,
-			NULL,
-			NULL);
-	}
-	
-	return camel_disco_store_type;
-}
-
-static int
-disco_setv (CamelObject *object, CamelException *ex, CamelArgV *args)
-{
-	/* CamelDiscoStore doesn't currently have anything to set */
-	return CAMEL_OBJECT_CLASS (parent_class)->setv (object, ex, args);
-}
-
-static int
-disco_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args)
-{
-	/* CamelDiscoStore doesn't currently have anything to get */
-	return CAMEL_OBJECT_CLASS (parent_class)->getv (object, ex, args);
-}
-
-static void
-disco_construct (CamelService *service, CamelSession *session,
-		 CamelProvider *provider, CamelURL *url,
-		 CamelException *ex)
-{
-	CamelDiscoStore *disco = CAMEL_DISCO_STORE (service);
-
-	CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex);
-	if (camel_exception_is_set (ex))
-		return;
-
-	disco->status = camel_session_is_online (session) ?
-		CAMEL_DISCO_STORE_ONLINE : CAMEL_DISCO_STORE_OFFLINE;
-}
-
-static gboolean
-disco_connect (CamelService *service, CamelException *ex)
-{
-	CamelDiscoStore *store = CAMEL_DISCO_STORE (service);
-	CamelDiscoStoreStatus status;
-
-	status = camel_disco_store_status (store);
-	if (status != CAMEL_DISCO_STORE_OFFLINE) {
-		if (!CAMEL_SERVICE_CLASS (parent_class)->connect (service, ex)) {
-			status = camel_disco_store_status (store);
-			if (status != CAMEL_DISCO_STORE_OFFLINE)
-				return FALSE;
-			camel_exception_clear (ex);
-		}
-	}
-
-	switch (status) {
-	case CAMEL_DISCO_STORE_ONLINE:
-	case CAMEL_DISCO_STORE_RESYNCING:
-		if (!CDS_CLASS (service)->connect_online (service, ex))
-			return FALSE;
-		if (camel_disco_diary_empty (store->diary))
-			return TRUE;
-
-		/* Need to resync */
-		store->status = CAMEL_DISCO_STORE_RESYNCING;
-		camel_disco_diary_replay (store->diary, ex);
-		store->status = CAMEL_DISCO_STORE_ONLINE;
-		if (camel_exception_is_set (ex))
-			return FALSE;
-
-		if (!camel_service_disconnect (service, TRUE, ex))
-			return FALSE;
-		return camel_service_connect (service, ex);
-
-	case CAMEL_DISCO_STORE_OFFLINE:
-		return CDS_CLASS (service)->connect_offline (service, ex);
-	}
-
-	g_assert_not_reached ();
-	return FALSE;
-}
-
-static void
-disco_cancel_connect (CamelService *service)
-{
-	CamelDiscoStore *store = CAMEL_DISCO_STORE (service);
-
-	/* Fall back */
-	store->status = CAMEL_DISCO_STORE_OFFLINE;
-
-	CAMEL_SERVICE_CLASS (parent_class)->cancel_connect (service);
-}
-
-static gboolean
-disco_disconnect (CamelService *service, gboolean clean, CamelException *ex)
-{
-	CamelDiscoStore *store = CAMEL_DISCO_STORE (service);
-
-	switch (camel_disco_store_status (store)) {
-	case CAMEL_DISCO_STORE_ONLINE:
-	case CAMEL_DISCO_STORE_RESYNCING:
-		if (!CDS_CLASS (service)->disconnect_online (service, clean, ex))
-			return FALSE;
-		break;
-
-	case CAMEL_DISCO_STORE_OFFLINE:
-		if (!CDS_CLASS (service)->disconnect_offline (service, clean, ex))
-			return FALSE;
-		break;
-
-	}
-
-	return CAMEL_SERVICE_CLASS (parent_class)->disconnect (service, clean, ex);
-}
-
-static CamelFolder *
-disco_get_folder (CamelStore *store, const char *name,
-		  guint32 flags, CamelException *ex)
-{
-	CamelDiscoStore *disco_store = CAMEL_DISCO_STORE (store);
-	
-	switch (camel_disco_store_status (disco_store)) {
-	case CAMEL_DISCO_STORE_ONLINE:
-		return CDS_CLASS (store)->get_folder_online (store, name, flags, ex);
-		
-	case CAMEL_DISCO_STORE_OFFLINE:
-		return CDS_CLASS (store)->get_folder_offline (store, name, flags, ex);
-		
-	case CAMEL_DISCO_STORE_RESYNCING:
-		return CDS_CLASS (store)->get_folder_resyncing (store, name, flags, ex);	
-	}
-	
-	g_assert_not_reached ();
-	return NULL;
-}
-
-static CamelFolderInfo *
-disco_get_folder_info (CamelStore *store, const char *top,
-		       guint32 flags, CamelException *ex)
-{
-	CamelDiscoStore *disco_store = CAMEL_DISCO_STORE (store);
-
-	/* Do this first so if we get forced offline, we'll switch to
-	 * the correct branch below. (FIXME: This only works because
-	 * we know that get_folder_info is the first call that the
-	 * mailer makes on a store.)
-	 */
-	if (CAMEL_SERVICE (store)->status == CAMEL_SERVICE_DISCONNECTED) {
-		if (!camel_service_connect (CAMEL_SERVICE (store), ex))
-			return NULL;
-	}
-
-	switch (camel_disco_store_status (disco_store)) {
-	case CAMEL_DISCO_STORE_ONLINE:
-		return CDS_CLASS (store)->get_folder_info_online (store, top, flags, ex);
-		
-	case CAMEL_DISCO_STORE_OFFLINE:
-		/* Can't edit subscriptions while offline */
-		if ((store->flags & CAMEL_STORE_SUBSCRIPTIONS) &&
-		    !(flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED)) {
-			camel_disco_store_check_online (disco_store, ex);
-			return NULL;
-		}
-		
-		return CDS_CLASS (store)->get_folder_info_offline (store, top, flags, ex);
-		
-	case CAMEL_DISCO_STORE_RESYNCING:
-		return CDS_CLASS (store)->get_folder_info_resyncing (store, top, flags, ex);
-	}
-	
-	g_assert_not_reached ();
-	return NULL;
-}
-
-
-/**
- * camel_disco_store_status:
- * @store: a disconnectable store
- *
- * Return value: the current online/offline status of @store.
- **/
-CamelDiscoStoreStatus
-camel_disco_store_status (CamelDiscoStore *store)
-{
-	CamelService *service = CAMEL_SERVICE (store);
-
-	g_return_val_if_fail (CAMEL_IS_DISCO_STORE (store), CAMEL_DISCO_STORE_ONLINE);
-
-	if (service->status == CAMEL_SERVICE_CONNECTING &&
-	    store->status == CAMEL_DISCO_STORE_ONLINE &&
-	    !camel_session_is_online (service->session))
-		store->status = CAMEL_DISCO_STORE_OFFLINE;
-
-	return store->status;
-}
-
-
-static void
-set_status (CamelDiscoStore *disco_store, CamelDiscoStoreStatus status,
-	    CamelException *ex)
-{
-	if (disco_store->status == status)
-		return;
-
-	camel_store_sync (CAMEL_STORE (disco_store), ex);
-	if (camel_exception_is_set (ex))
-		return;
-	if (!camel_service_disconnect (CAMEL_SERVICE (disco_store), TRUE, ex))
-		return;
-
-	disco_store->status = status;
-	camel_service_connect (CAMEL_SERVICE (disco_store), ex);
-}
-
-/**
- * camel_disco_store_set_status:
- * @store: a disconnectable store
- * @status: the new status
- * @ex: a CamelException
- *
- * Sets @store to @status. If an error occurrs and the status cannot
- * be set to @status, @ex will be set.
- **/
-void
-camel_disco_store_set_status (CamelDiscoStore *store,
-			      CamelDiscoStoreStatus status,
-			      CamelException *ex)
-{
-	CDS_CLASS (store)->set_status (store, status, ex);
-}
-
-
-static gboolean
-can_work_offline (CamelDiscoStore *disco_store)
-{
-	g_warning ("CamelDiscoStore::can_work_offline not implemented for `%s'",
-		   camel_type_to_name (CAMEL_OBJECT_GET_TYPE (disco_store)));
-	return FALSE;
-}
-
-/**
- * camel_disco_store_can_work_offline:
- * @store: a disconnectable store
- *
- * Return value: whether or not @store can be used offline. (Will be
- * %FALSE if the store is not caching data to local disk, for example.)
- **/
-gboolean
-camel_disco_store_can_work_offline (CamelDiscoStore *store)
-{
-	return CDS_CLASS (store)->can_work_offline (store);
-}
-
-
-/**
- * camel_disco_store_check_online:
- * @store: a disconnectable store
- * @ex: a CamelException
- *
- * This checks that @store is online, and sets @ex if it is not. This
- * can be used as a simple way to set a generic error message in @ex
- * for operations that won't work offline.
- *
- * Return value: whether or not @store is online.
- **/
-gboolean
-camel_disco_store_check_online (CamelDiscoStore *store, CamelException *ex)
-{
-	if (camel_disco_store_status (store) != CAMEL_DISCO_STORE_ONLINE) {
-		camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
-				     _("You must be working online to "
-				       "complete this operation"));
-		return FALSE;
-	}
-
-	return TRUE;
-}
diff --git a/camel/camel-disco-store.h b/camel/camel-disco-store.h
deleted file mode 100644
index 7c95c96456..0000000000
--- a/camel/camel-disco-store.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-disco-store.h: abstruct class for a disconnectable store */
-
-/* 
- * Authors: Dan Winship 
- *
- * Copyright (C) 2001 Ximian, Inc.
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of version 2 of the GNU General Public 
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-
-#ifndef CAMEL_DISCO_STORE_H
-#define CAMEL_DISCO_STORE_H 1
-
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include 
-
-#define CAMEL_DISCO_STORE_TYPE     (camel_disco_store_get_type ())
-#define CAMEL_DISCO_STORE(obj)     (CAMEL_CHECK_CAST((obj), CAMEL_DISCO_STORE_TYPE, CamelDiscoStore))
-#define CAMEL_DISCO_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_DISCO_STORE_TYPE, CamelDiscoStoreClass))
-#define CAMEL_IS_DISCO_STORE(o)    (CAMEL_CHECK_TYPE((o), CAMEL_DISCO_STORE_TYPE))
-
-enum {
-	CAMEL_DISCO_STORE_ARG_FIRST  = CAMEL_STORE_ARG_FIRST + 100,
-};
-
-typedef enum {
-	CAMEL_DISCO_STORE_ONLINE,
-	CAMEL_DISCO_STORE_OFFLINE,
-	CAMEL_DISCO_STORE_RESYNCING
-} CamelDiscoStoreStatus;
-
-struct _CamelDiscoStore {
-	CamelStore parent_object;	
-
-	CamelDiscoStoreStatus status;
-	CamelDiscoDiary *diary;
-};
-
-
-typedef struct {
-	CamelStoreClass parent_class;
-
-	void              (*set_status)              (CamelDiscoStore *,
-						      CamelDiscoStoreStatus,
-						      CamelException *);
-	gboolean          (*can_work_offline)        (CamelDiscoStore *);
-
-
-	gboolean          (*connect_online)          (CamelService *,
-						      CamelException *);
-	gboolean          (*connect_offline)         (CamelService *,
-						      CamelException *);
-
-	gboolean          (*disconnect_online)       (CamelService *, gboolean,
-						      CamelException *);
-	gboolean          (*disconnect_offline)      (CamelService *, gboolean,
-						      CamelException *);
-
-	CamelFolder *     (*get_folder_online)       (CamelStore *store,
-						      const char *name,
-						      guint32 flags,
-						      CamelException *ex);
-	CamelFolder *     (*get_folder_offline)      (CamelStore *store,
-						      const char *name,
-						      guint32 flags,
-						      CamelException *ex);
-	CamelFolder *     (*get_folder_resyncing)    (CamelStore *store,
-						      const char *name,
-						      guint32 flags,
-						      CamelException *ex);
-
-	CamelFolderInfo * (*get_folder_info_online)    (CamelStore *store,
-							const char *top,
-							guint32 flags,
-							CamelException *ex);
-	CamelFolderInfo * (*get_folder_info_offline)   (CamelStore *store,
-							const char *top,
-							guint32 flags,
-							CamelException *ex);
-	CamelFolderInfo * (*get_folder_info_resyncing) (CamelStore *store,
-							const char *top,
-							guint32 flags,
-							CamelException *ex);
-
-} CamelDiscoStoreClass;
-
-
-/* Standard Camel function */
-CamelType camel_disco_store_get_type (void);
-
-/* Public methods */
-CamelDiscoStoreStatus camel_disco_store_status           (CamelDiscoStore *);
-void                  camel_disco_store_set_status       (CamelDiscoStore *,
-							  CamelDiscoStoreStatus,
-							  CamelException *);
-gboolean              camel_disco_store_can_work_offline (CamelDiscoStore *);
-
-
-/* Convenience functions */
-gboolean camel_disco_store_check_online (CamelDiscoStore *store, CamelException *ex);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_DISCO_STORE_H */
diff --git a/camel/camel-exception-list.def b/camel/camel-exception-list.def
deleted file mode 100644
index 8fe1e268cf..0000000000
--- a/camel/camel-exception-list.def
+++ /dev/null
@@ -1,37 +0,0 @@
-/* WARNING: Exceptions MUST NOT be renumbered: they need to be
- * consistent across libraries compiled at different times.
- * Categories should be widely separated, old unused exceptions can
- * never be deleted, and new exceptions can be added only to the
- * ends of categories.
- */
-
-CAMEL_EXCEPTION_NONE = 0,
-
-/* Generic exceptions */
-CAMEL_EXCEPTION_INVALID_PARAM,
-CAMEL_EXCEPTION_SYSTEM,
-CAMEL_EXCEPTION_USER_CANCEL,
-
-/* CamelFolderException */
-CAMEL_EXCEPTION_FOLDER_NULL = 100,
-CAMEL_EXCEPTION_FOLDER_INVALID,
-CAMEL_EXCEPTION_FOLDER_INVALID_STATE,
-CAMEL_EXCEPTION_FOLDER_NON_EMPTY,
-CAMEL_EXCEPTION_FOLDER_NON_UID,
-CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION,
-CAMEL_EXCEPTION_FOLDER_INVALID_PATH,
-CAMEL_EXCEPTION_FOLDER_INVALID_UID,
-CAMEL_EXCEPTION_FOLDER_SUMMARY_INVALID,
-
-/* CamelStoreException */
-CAMEL_EXCEPTION_STORE_NULL = 200,
-CAMEL_EXCEPTION_STORE_INVALID,
-CAMEL_EXCEPTION_STORE_NO_FOLDER,
-
-/* CamelServiceException */
-CAMEL_EXCEPTION_SERVICE_NULL = 300,
-CAMEL_EXCEPTION_SERVICE_INVALID,
-CAMEL_EXCEPTION_SERVICE_URL_INVALID,
-CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
-CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
-CAMEL_EXCEPTION_SERVICE_NOT_CONNECTED
diff --git a/camel/camel-exception.c b/camel/camel-exception.c
deleted file mode 100644
index 95e376624a..0000000000
--- a/camel/camel-exception.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* 
- *
- * Author : 
- *  Bertrand Guiheneuf 
- *
- * Copyright 1999-2003 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of version 2 of the GNU General Public 
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-#include 
-
-#include "camel-exception.h"
-#include "e-util/e-memory.h"
-
-/* i dont know why gthread_mutex stuff even exists, this is easier */
-
-/* also, i'm not convinced mutexes are needed here.  But it
-   doesn't really hurt either */
-static pthread_mutex_t exception_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-#define CAMEL_EXCEPTION_LOCK(e) (pthread_mutex_lock(&exception_mutex))
-#define CAMEL_EXCEPTION_UNLOCK(e) (pthread_mutex_unlock(&exception_mutex))
-
-static EMemChunk *exception_chunks = NULL;
-
-/**
- * camel_exception_new: allocate a new exception object. 
- * 
- * Create and returns a new exception object.
- * 
- * 
- * Return value: The newly allocated exception object.
- **/
-CamelException *
-camel_exception_new (void)
-{
-	CamelException *ex;
-
-	CAMEL_EXCEPTION_LOCK(exception);
-
-	if (exception_chunks == NULL)
-		exception_chunks = e_memchunk_new(16, sizeof(CamelException));
-
-	ex = e_memchunk_alloc(exception_chunks);
-	ex->desc = NULL;
-
-	/* set the Exception Id to NULL */
-	ex->id = CAMEL_EXCEPTION_NONE;
-
-	CAMEL_EXCEPTION_UNLOCK(exception);
-
-	return ex;
-}
-
-/**
- * camel_exception_init: init a (statically allocated) exception. 
- * 
- * Init an exception. This routine is mainly
- * useful when using a statically allocated
- * exception. 
- * 
- * 
- **/
-void
-camel_exception_init (CamelException *ex)
-{
-	ex->desc = NULL;
-
-	/* set the Exception Id to NULL */
-	ex->id = CAMEL_EXCEPTION_NONE;
-}
-
-
-/**
- * camel_exception_clear: Clear an exception
- * @exception: the exception object
- * 
- * Clear an exception, that is, set the 
- * exception ID to CAMEL_EXCEPTION_NONE and
- * free the description text.
- * If the exception is NULL, this funtion just
- * returns.
- **/
-void 
-camel_exception_clear (CamelException *exception)
-{
-	if (!exception)
-		return;
-
-	CAMEL_EXCEPTION_LOCK(exception);
-
-	if (exception->desc)
-		g_free (exception->desc);
-	exception->desc = NULL;
-	exception->id = CAMEL_EXCEPTION_NONE;
-
-	CAMEL_EXCEPTION_UNLOCK(exception);
-}
-
-/**
- * camel_exception_free: Free an exception 
- * @exception: The exception object to free
- * 
- * Free an exception object. If the exception
- * is NULL, nothing is done, the routine simply
- * returns.
- **/
-void 
-camel_exception_free (CamelException *exception)
-{
-	if (!exception)
-		return;
-	
-	if (exception->desc)
-		g_free (exception->desc);
-
-	CAMEL_EXCEPTION_LOCK(exception);
-
-	e_memchunk_free(exception_chunks, exception);
-
-	CAMEL_EXCEPTION_UNLOCK(exception);
-}
-
-/**
- * camel_exception_set: set an exception 
- * @ex: exception object 
- * @id: exception id 
- * @desc: textual description of the exception
- * 
- * Set the value of an exception. The exception id is 
- * a unique number representing the exception. The 
- * textual description is a small text explaining 
- * what happened and provoked the exception.
- *
- * When @ex is NULL, nothing is done, this routine
- * simply returns.
- *
- **/
-void
-camel_exception_set (CamelException *ex,
-		     ExceptionId id,
-		     const char *desc)
-{
-	if (!ex)
-		return;
-
-	CAMEL_EXCEPTION_LOCK(exception);
-
-	ex->id = id;
-
-	if (desc != ex->desc) {
-		g_free (ex->desc);
-		ex->desc = g_strdup (desc);
-	}
-
-	CAMEL_EXCEPTION_UNLOCK(exception);
-}
-
-/**
- * camel_exception_setv: set an exception 
- * @ex: exception object 
- * @id: exception id 
- * @format: format of the description string. The format string is
- * used as in printf().
- * 
- * Set the value of an exception. The exception id is 
- * a unique number representing the exception. The 
- * textual description is a small text explaining 
- * what happened and provoked the exception. 
- * In this version, the string is created from the format 
- * string and the variable argument list.
- *
- * It is safe to say:
- *   camel_exception_setv (ex, ..., camel_exception_get_description (ex), ...);
- *
- * When @ex is NULL, nothing is done, this routine
- * simply returns.
- *
- **/
-void
-camel_exception_setv (CamelException *ex,
-		      ExceptionId id,
-		      const char *format, 
-		      ...)
-{
-	va_list args;
-	char *old;
-	
-	if (!ex)
-		return;
-
-	CAMEL_EXCEPTION_LOCK(exception);
-	
-	old = ex->desc;
-	
-	va_start(args, format);
-	ex->desc = g_strdup_vprintf (format, args);
-	va_end (args);
-
-	g_free (old);
-	
-	ex->id = id;
-
-	CAMEL_EXCEPTION_UNLOCK(exception);
-}
-
-/**
- * camel_exception_xfer: transfer an exception
- * @ex_dst: Destination exception object 
- * @ex_src: Source exception object
- * 
- * Transfer the content of an exception from
- * an exception object to another. 
- * The destination exception receives the id and
- * the description text of the source exception. 
- **/
-void 
-camel_exception_xfer (CamelException *ex_dst,
-		      CamelException *ex_src)
-{
-	if (ex_src == NULL) {
-		g_warning ("camel_exception_xfer: trying to transfer NULL exception to %p\n", ex_dst);
-		return;
-	}
-
-	if (ex_dst == NULL) {
-		/* must have same side-effects */
-		camel_exception_clear (ex_src);
-		return;
-	}
-
-	CAMEL_EXCEPTION_LOCK(exception);
-
-	if (ex_dst->desc)
-		g_free (ex_dst->desc);
-
-	ex_dst->id = ex_src->id;
-	ex_dst->desc = ex_src->desc;
-
-	ex_src->desc = NULL;
-	ex_src->id = CAMEL_EXCEPTION_NONE;
-
-	CAMEL_EXCEPTION_UNLOCK(exception);
-}
-
-/**
- * camel_exception_get_id: get the exception id
- * @ex: The exception object
- * 
- * Return the id of an exception. 
- * If @ex is NULL, return CAMEL_EXCEPTION_NONE;
- * 
- * Return value: Exception ID.
- **/
-ExceptionId
-camel_exception_get_id (CamelException *ex)
-{
-	if (ex)
-		return ex->id;
-	else {
-		g_warning ("camel_exception_get_id called with NULL parameter.");
-		return CAMEL_EXCEPTION_NONE;
-	}
-}
-
-/**
- * camel_exception_get_description: get the description of an exception.
- * @ex: The exception object
- * 
- * Return the exception description text. 
- * If @ex is NULL, return NULL;
- * 
- * 
- * Return value: Exception description text.
- **/
-const gchar *
-camel_exception_get_description (CamelException *ex)
-{
-	char *ret = NULL;
-
-	if (ex)
-		ret = ex->desc;
-	else
-		g_warning ("camel_exception_get_description called with NULL parameter.");
-		
-	return ret;
-}
diff --git a/camel/camel-exception.h b/camel/camel-exception.h
deleted file mode 100644
index 77c2c16066..0000000000
--- a/camel/camel-exception.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-execpetion.h : exception utils */
-
-/* 
- *
- * Author : 
- *  Bertrand Guiheneuf 
- *
- * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of version 2 of the GNU General Public 
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-
-
-#ifndef CAMEL_EXCEPTION_H
-#define CAMEL_EXCEPTION_H 1
-
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus }*/
-
-#include 
-
-typedef enum {
-#include "camel-exception-list.def"
-
-} ExceptionId;
-
-
-struct _CamelException {
-	/* do not access the fields directly */
-	ExceptionId id;
-	char *desc;
-
-};
-
-
-
-/* creation and destruction functions */
-CamelException *          camel_exception_new           (void);
-void                      camel_exception_free          (CamelException *exception);
-void                      camel_exception_init          (CamelException *ex);
-
-
-/* exception content manipulation */
-void                      camel_exception_clear         (CamelException *exception);
-void                      camel_exception_set           (CamelException *ex,
-							 ExceptionId id,
-							 const char *desc);
-void                      camel_exception_setv          (CamelException *ex,
-							 ExceptionId id,
-							 const char *format,  
-							 ...);
-
-
-/* exception content transfer */
-void                      camel_exception_xfer          (CamelException *ex_dst,
-							 CamelException *ex_src);
-
-
-/* exception content retrieval */
-ExceptionId               camel_exception_get_id        (CamelException *ex);
-const char *             camel_exception_get_description (CamelException *ex);
-
-#define camel_exception_is_set(ex) (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE)
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_EXCEPTION_H */
-
diff --git a/camel/camel-file-utils.c b/camel/camel-file-utils.c
deleted file mode 100644
index 540fef2739..0000000000
--- a/camel/camel-file-utils.c
+++ /dev/null
@@ -1,546 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Authors:
- *   Michael Zucchi 
- *   Jeffrey Stedfast 
- *   Dan Winship 
- *
- * Copyright (C) 2000, 2003 Ximian, Inc.
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of version 2 of the GNU General Public 
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "camel-file-utils.h"
-#include "camel-operation.h"
-#include "camel-url.h"
-
-#ifndef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
-
-/**
- * camel_file_util_encode_uint32:
- * @out: file to output to
- * @value: value to output
- * 
- * Utility function to save an uint32 to a file.
- * 
- * Return value: 0 on success, -1 on error.
- **/
-int
-camel_file_util_encode_uint32 (FILE *out, guint32 value)
-{
-	int i;
-
-	for (i = 28; i > 0; i -= 7) {
-		if (value >= (1 << i)) {
-			unsigned int c = (value >> i) & 0x7f;
-			if (fputc (c, out) == -1)
-				return -1;
-		}
-	}
-	return fputc (value | 0x80, out);
-}
-
-
-/**
- * camel_file_util_decode_uint32:
- * @in: file to read from
- * @dest: pointer to a variable to store the value in
- * 
- * Retrieve an encoded uint32 from a file.
- * 
- * Return value: 0 on success, -1 on error.  @*dest will contain the
- * decoded value.
- **/
-int
-camel_file_util_decode_uint32 (FILE *in, guint32 *dest)
-{
-        guint32 value = 0;
-	int v;
-
-        /* until we get the last byte, keep decoding 7 bits at a time */
-        while ( ((v = fgetc (in)) & 0x80) == 0 && v!=EOF) {
-                value |= v;
-                value <<= 7;
-        }
-	if (v == EOF) {
-		*dest = value >> 7;
-		return -1;
-	}
-	*dest = value | (v & 0x7f);
-
-        return 0;
-}
-
-
-/**
- * camel_file_util_encode_fixed_int32:
- * @out: file to output to
- * @value: value to output
- * 
- * Encode a gint32, performing no compression, but converting
- * to network order.
- * 
- * Return value: 0 on success, -1 on error.
- **/
-int
-camel_file_util_encode_fixed_int32 (FILE *out, gint32 value)
-{
-	guint32 save;
-
-	save = htonl (value);
-	if (fwrite (&save, sizeof (save), 1, out) != 1)
-		return -1;
-	return 0;
-}
-
-
-/**
- * camel_file_util_decode_fixed_int32:
- * @in: file to read from
- * @dest: pointer to a variable to store the value in
- * 
- * Retrieve a gint32.
- * 
- * Return value: 0 on success, -1 on error.
- **/
-int
-camel_file_util_decode_fixed_int32 (FILE *in, gint32 *dest)
-{
-	guint32 save;
-
-	if (fread (&save, sizeof (save), 1, in) == 1) {
-		*dest = ntohl (save);
-		return 0;
-	} else {
-		return -1;
-	}
-}
-
-
-/**
- * camel_file_util_encode_time_t:
- * @out: file to output to
- * @value: value to output
- * 
- * Encode a time_t value to the file.
- * 
- * Return value: 0 on success, -1 on error.
- **/
-int
-camel_file_util_encode_time_t(FILE *out, time_t value)
-{
-	int i;
-
-	for (i = sizeof (time_t) - 1; i >= 0; i--) {
-		if (fputc((value >> (i * 8)) & 0xff, out) == -1)
-			return -1;
-	}
-	return 0;
-}
-
-
-/**
- * camel_file_util_decode_time_t:
- * @in: file to read from
- * @dest: pointer to a variable to store the value in
- * 
- * Decode a time_t value.
- * 
- * Return value: 0 on success, -1 on error.
- **/
-int
-camel_file_util_decode_time_t (FILE *in, time_t *dest)
-{
-	time_t save = 0;
-	int i = sizeof (time_t) - 1;
-	int v = EOF;
-
-        while (i >= 0 && (v = fgetc (in)) != EOF) {
-		save |= ((time_t)v) << (i * 8);
-		i--;
-	}
-	*dest = save;
-	if (v == EOF)
-		return -1;
-	return 0;
-}
-
-
-/**
- * camel_file_util_encode_off_t:
- * @out: file to output to
- * @value: value to output
- * 
- * Encode an off_t type.
- * 
- * Return value: 0 on success, -1 on error.
- **/
-int
-camel_file_util_encode_off_t (FILE *out, off_t value)
-{
-	int i;
-
-	for (i = sizeof (off_t) - 1; i >= 0; i--) {
-		if (fputc ((value >> (i * 8)) & 0xff, out) == -1)
-			return -1;
-	}
-	return 0;
-}
-
-
-/**
- * camel_file_util_decode_off_t:
- * @in: file to read from
- * @dest: pointer to a variable to put the value in
- * 
- * Decode an off_t type.
- * 
- * Return value: 0 on success, -1 on failure.
- **/
-int
-camel_file_util_decode_off_t (FILE *in, off_t *dest)
-{
-	off_t save = 0;
-	int i = sizeof(off_t) - 1;
-	int v = EOF;
-
-        while (i >= 0 && (v = fgetc (in)) != EOF) {
-		save |= ((off_t)v) << (i * 8);
-		i--;
-	}
-	*dest = save;
-	if (v == EOF)
-		return -1;
-	return 0;
-}
-
-
-/**
- * camel_file_util_encode_string:
- * @out: file to output to
- * @str: value to output
- * 
- * Encode a normal string and save it in the output file.
- * 
- * Return value: 0 on success, -1 on error.
- **/
-int
-camel_file_util_encode_string (FILE *out, const char *str)
-{
-	register int len;
-
-	if (str == NULL)
-		return camel_file_util_encode_uint32 (out, 1);
-
-	len = strlen (str);
-	if (camel_file_util_encode_uint32 (out, len+1) == -1)
-		return -1;
-	if (len == 0 || fwrite (str, len, 1, out) == 1)
-		return 0;
-	return -1;
-}
-
-
-/**
- * camel_file_util_decode_string:
- * @in: file to read from
- * @str: pointer to a variable to store the value in
- * 
- * Decode a normal string from the input file.
- * 
- * Return value: 0 on success, -1 on error.
- **/
-int
-camel_file_util_decode_string (FILE *in, char **str)
-{
-	guint32 len;
-	register char *ret;
-
-	if (camel_file_util_decode_uint32 (in, &len) == -1) {
-		*str = NULL;
-		return -1;
-	}
-
-	len--;
-	if (len > 65536) {
-		*str = NULL;
-		return -1;
-	}
-
-	ret = g_malloc (len+1);
-	if (len > 0 && fread (ret, len, 1, in) != 1) {
-		g_free (ret);
-		*str = NULL;
-		return -1;
-	}
-
-	ret[len] = 0;
-	*str = ret;
-	return 0;
-}
-
-
-/**
- * camel_mkdir:
- * @path: directory path to create
- * @mode: permissions
- *
- * Creates the directory path described in @path, creating any parent
- * directories as necessary.
- *
- * Returns 0 on success or -1 on fail. In the case of failure, errno
- * will be set appropriately.
- **/
-int
-camel_mkdir (const char *path, mode_t mode)
-{
-	char *copy, *p;
-	
-	g_assert(path && path[0] == '/');
-	
-	p = copy = g_alloca (strlen (path) + 1);
-	strcpy(copy, path);
-	do {
-		p = strchr(p + 1, '/');
-		if (p)
-			*p = '\0';
-		if (access(copy, F_OK) == -1) {
-			if (mkdir(copy, mode) == -1)
-				return -1;
-		}
-		if (p)
-			*p = '/';
-	} while (p);
-	
-	return 0;
-}
-
-
-/**
- * camel_file_util_safe_filename:
- * @name: string to 'flattened' into a safe filename
- *
- * 'Flattens' @name into a safe filename string by hex encoding any
- * chars that may cause problems on the filesystem.
- *
- * Returns a safe filename string.
- **/
-char *
-camel_file_util_safe_filename (const char *name)
-{
-	if (name == NULL)
-		return NULL;
-	
-	return camel_url_encode(name, "/?()'*");
-}
-
-
-/* FIXME: poll() might be more efficient and more portable? */
-
-/**
- * camel_read:
- * @fd: file descriptor
- * @buf: buffer to fill
- * @n: number of bytes to read into @buf
- *
- * Cancellable libc read() replacement.
- *
- * Returns number of bytes read or -1 on fail. On failure, errno will
- * be set appropriately.
- **/
-ssize_t
-camel_read (int fd, char *buf, size_t n)
-{
-	ssize_t nread;
-	int cancel_fd;
-	
-	if (camel_operation_cancel_check (NULL)) {
-		errno = EINTR;
-		return -1;
-	}
-	
-	cancel_fd = camel_operation_cancel_fd (NULL);
-	if (cancel_fd == -1) {
-		do {
-			nread = read (fd, buf, n);
-		} while (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
-	} else {
-		int errnosav, flags, fdmax;
-		fd_set rdset;
-		
-		flags = fcntl (fd, F_GETFL);
-		fcntl (fd, F_SETFL, flags | O_NONBLOCK);
-		
-		do {
-			FD_ZERO (&rdset);
-			FD_SET (fd, &rdset);
-			FD_SET (cancel_fd, &rdset);
-			fdmax = MAX (fd, cancel_fd) + 1;
-			
-			nread = -1;
-			if (select (fdmax, &rdset, 0, 0, NULL) != -1) {
-				if (FD_ISSET (cancel_fd, &rdset)) {
-					fcntl (fd, F_SETFL, flags);
-					errno = EINTR;
-					return -1;
-				}
-				
-				do {
-					nread = read (fd, buf, n);
-				} while (nread == -1 && errno == EINTR);
-			} else if (errno == EINTR) {
-				errno = EAGAIN;
-			}
-		} while (nread == -1 && (errno == EAGAIN || errno == EWOULDBLOCK));
-		
-		errnosav = errno;
-		fcntl (fd, F_SETFL, flags);
-		errno = errnosav;
-	}
-	
-	return nread;
-}
-
-
-/**
- * camel_write:
- * @fd: file descriptor
- * @buf: buffer to write
- * @n: number of bytes of @buf to write
- *
- * Cancellable libc write() replacement.
- *
- * Returns number of bytes written or -1 on fail. On failure, errno will
- * be set appropriately.
- **/
-ssize_t
-camel_write (int fd, const char *buf, size_t n)
-{
-	ssize_t w, written = 0;
-	int cancel_fd;
-	
-	if (camel_operation_cancel_check (NULL)) {
-		errno = EINTR;
-		return -1;
-	}
-	
-	cancel_fd = camel_operation_cancel_fd (NULL);
-	if (cancel_fd == -1) {
-		do {
-			do {
-				w = write (fd, buf + written, n - written);
-			} while (w == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
-			
-			if (w > 0)
-				written += w;
-		} while (w != -1 && written < n);
-	} else {
-		int errnosav, flags, fdmax;
-		fd_set rdset, wrset;
-		
-		flags = fcntl (fd, F_GETFL);
-		fcntl (fd, F_SETFL, flags | O_NONBLOCK);
-		
-		fdmax = MAX (fd, cancel_fd) + 1;
-		do {
-			FD_ZERO (&rdset);
-			FD_ZERO (&wrset);
-			FD_SET (fd, &wrset);
-			FD_SET (cancel_fd, &rdset);
-			
-			w = -1;
-			if (select (fdmax, &rdset, &wrset, 0, NULL) != -1) {
-				if (FD_ISSET (cancel_fd, &rdset)) {
-					fcntl (fd, F_SETFL, flags);
-					errno = EINTR;
-					return -1;
-				}
-				
-				do {
-					w = write (fd, buf + written, n - written);
-				} while (w == -1 && errno == EINTR);
-				
-				if (w == -1) {
-					if (errno == EAGAIN || errno == EWOULDBLOCK) {
-						w = 0;
-					} else {
-						errnosav = errno;
-						fcntl (fd, F_SETFL, flags);
-						errno = errnosav;
-						return -1;
-					}
-				} else
-					written += w;
-			} else if (errno == EINTR) {
-				w = 0;
-			}
-		} while (w != -1 && written < n);
-		
-		errnosav = errno;
-		fcntl (fd, F_SETFL, flags);
-		errno = errnosav;
-	}
-	
-	if (w == -1)
-		return -1;
-	
-	return written;
-}
-
-/**
- * camel_file_util_savename:
- * @filename: 
- * 
- * Builds a filename of the form ".#" + @filename, used to create
- * a two-stage commit file write.
- * 
- * Return value: ".#" + filename.  It must be free'd with g_free().
- **/
-char *
-camel_file_util_savename(const char *filename)
-{
-	char *name, *slash;
-	int off;
-
-	name = g_malloc(strlen(filename)+3);
-	slash = strrchr(filename, '/');
-	if (slash) {
-		off = slash-filename;
-
-		memcpy(name, filename, off+1);
-		memcpy(name + off+1, ".#", 2);
-		strcpy(name + off+3, filename+off+1);
-	} else {
-		sprintf(name, ".#%s", filename);
-	}
-
-	return name;
-}
diff --git a/camel/camel-file-utils.h b/camel/camel-file-utils.h
deleted file mode 100644
index 15022d99b3..0000000000
--- a/camel/camel-file-utils.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* 
- * Authors:
- *   Michael Zucchi 
- *   Jeffrey Stedfast 
- *   Dan Winship 
- *
- * Copyright (C) 2000, 2003 Ximian, Inc.
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of version 2 of the GNU General Public 
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-
-#ifndef CAMEL_FILE_UTILS_H
-#define CAMEL_FILE_UTILS_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include 
-#include 
-#include 
-#include 
-
-int camel_file_util_encode_fixed_int32 (FILE *out, gint32);
-int camel_file_util_decode_fixed_int32 (FILE *in, gint32 *);
-int camel_file_util_encode_uint32 (FILE *out, guint32);
-int camel_file_util_decode_uint32 (FILE *in, guint32 *);
-int camel_file_util_encode_time_t (FILE *out, time_t);
-int camel_file_util_decode_time_t (FILE *in, time_t *);
-int camel_file_util_encode_off_t (FILE *out, off_t);
-int camel_file_util_decode_off_t (FILE *in, off_t *);
-int camel_file_util_encode_string (FILE *out, const char *);
-int camel_file_util_decode_string (FILE *in, char **);
-
-int camel_mkdir (const char *path, mode_t mode);
-char *camel_file_util_safe_filename (const char *name);
-
-ssize_t camel_read (int fd, char *buf, size_t n);
-ssize_t camel_write (int fd, const char *buf, size_t n);
-
-char *camel_file_util_savename(const char *filename);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_FILE_UTILS_H */
diff --git a/camel/camel-filter-driver.c b/camel/camel-filter-driver.c
deleted file mode 100644
index 1282188eb0..0000000000
--- a/camel/camel-filter-driver.c
+++ /dev/null
@@ -1,1473 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Copyright (C) 2000 Ximian Inc.
- *
- *  Authors: Michael Zucchi 
- *           Jeffrey Stedfast 
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include 
-
-#include "camel-filter-driver.h"
-#include "camel-filter-search.h"
-
-#include "camel-service.h"
-#include "camel-stream-fs.h"
-#include "camel-stream-mem.h"
-#include "camel-mime-message.h"
-
-#include "e-util/e-sexp.h"
-#include "e-util/e-memory.h"
-#include "e-util/e-msgport.h"	/* for edlist */
-
-#define d(x)
-
-/* an invalid pointer */
-#define FOLDER_INVALID ((void *)~0)
-
-/* type of status for a log report */
-enum filter_log_t {
-	FILTER_LOG_NONE,
-	FILTER_LOG_START,       /* start of new log entry */
-	FILTER_LOG_ACTION,      /* an action performed */
-	FILTER_LOG_END,	        /* end of log */
-};
-
-/* list of rule nodes */
-struct _filter_rule {
-	struct _filter_rule *next;
-	struct _filter_rule *prev;
-
-	char *match;
-	char *action;
-	char *name;
-};
-
-struct _CamelFilterDriverPrivate {
-	GHashTable *globals;       /* global variables */
-
-	CamelSession *session;
-
-	CamelFolder *defaultfolder;        /* defualt folder */
-	
-	CamelFilterStatusFunc *statusfunc; /* status callback */
-	void *statusdata;                  /* status callback data */
-	
-	CamelFilterShellFunc *shellfunc;    /* execute shell command callback */
-	void *shelldata;                    /* execute shell command callback data */
-	
-	CamelFilterPlaySoundFunc *playfunc; /* play-sound command callback */
-	void *playdata;                     /* play-sound command callback data */
-	
-	CamelFilterSystemBeepFunc *beep;    /* system beep callback */
-	void *beepdata;                     /* system beep callback data */
-	
-	/* for callback */
-	CamelFilterGetFolderFunc get_folder;
-	void *data;
-	
-	/* run-time data */
-	GHashTable *folders;       /* folders that message has been copied to */
-	int closed;		   /* close count */
-	GHashTable *forwards;      /* addresses that have been forwarded the message */
-	GHashTable *only_once;     /* actions to run only-once */
-	
-	gboolean terminated;       /* message processing was terminated */
-	gboolean deleted;          /* message was marked for deletion */
-	gboolean copied;           /* message was copied to some folder or another */
-	
-	CamelMimeMessage *message; /* input message */
-	CamelMessageInfo *info;    /* message summary info */
-	const char *uid;           /* message uid */
-	CamelFolder *source;       /* message source folder */
-	gboolean modified;         /* has the input message been modified? */
-	
-	FILE *logfile;             /* log file */
-	
-	EDList rules;		   /* list of _filter_rule structs */
-	
-	CamelException *ex;
-	
-	/* evaluator */
-	ESExp *eval;
-};
-
-#define _PRIVATE(o) (((CamelFilterDriver *)(o))->priv)
-
-static void camel_filter_driver_class_init (CamelFilterDriverClass *klass);
-static void camel_filter_driver_init       (CamelFilterDriver *obj);
-static void camel_filter_driver_finalise   (CamelObject *obj);
-
-static void camel_filter_driver_log (CamelFilterDriver *driver, enum filter_log_t status, const char *desc, ...);
-
-static CamelFolder *open_folder (CamelFilterDriver *d, const char *folder_url);
-static int close_folders (CamelFilterDriver *d);
-
-static ESExpResult *do_delete (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *);
-static ESExpResult *mark_forward (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *);
-static ESExpResult *do_copy (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *);
-static ESExpResult *do_move (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *);
-static ESExpResult *do_stop (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *);
-static ESExpResult *do_colour (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *);
-static ESExpResult *do_score (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *);
-static ESExpResult *set_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *);
-static ESExpResult *unset_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *);
-static ESExpResult *do_shell (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *);
-static ESExpResult *do_beep (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *);
-static ESExpResult *play_sound (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *);
-static ESExpResult *do_only_once (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *);
-static ESExpResult *pipe_message (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *);
-
-/* these are our filter actions - each must have a callback */
-static struct {
-	char *name;
-	ESExpFunc *func;
-	int type;		/* set to 1 if a function can perform shortcut evaluation, or
-				   doesn't execute everything, 0 otherwise */
-} symbols[] = {
-	{ "delete",            (ESExpFunc *) do_delete,    0 },
-	{ "forward-to",        (ESExpFunc *) mark_forward, 0 },
-	{ "copy-to",           (ESExpFunc *) do_copy,      0 },
-	{ "move-to",           (ESExpFunc *) do_move,      0 },
-	{ "stop",              (ESExpFunc *) do_stop,      0 },
-	{ "set-colour",        (ESExpFunc *) do_colour,    0 },
-	{ "set-score",         (ESExpFunc *) do_score,     0 },
-	{ "set-system-flag",   (ESExpFunc *) set_flag,     0 },
-	{ "unset-system-flag", (ESExpFunc *) unset_flag,   0 },
-	{ "pipe-message",      (ESExpFunc *) pipe_message, 0 },
-	{ "shell",             (ESExpFunc *) do_shell,     0 },
-	{ "beep",              (ESExpFunc *) do_beep,      0 },
-	{ "play-sound",        (ESExpFunc *) play_sound,   0 },
-	{ "only-once",         (ESExpFunc *) do_only_once, 0 }
-};
-
-static CamelObjectClass *camel_filter_driver_parent;
-
-CamelType
-camel_filter_driver_get_type (void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-
-	if (type == CAMEL_INVALID_TYPE)	{
-		type = camel_type_register (CAMEL_OBJECT_TYPE,
-					    "CamelFilterDriver",
-					    sizeof (CamelFilterDriver),
-					    sizeof (CamelFilterDriverClass),
-					    (CamelObjectClassInitFunc) camel_filter_driver_class_init,
-					    NULL,
-					    (CamelObjectInitFunc) camel_filter_driver_init,
-					    (CamelObjectFinalizeFunc) camel_filter_driver_finalise);
-	}
-	
-	return type;
-}
-
-static void
-camel_filter_driver_class_init (CamelFilterDriverClass *klass)
-{
-	/*CamelObjectClass *object_class = (CamelObjectClass *) klass;*/
-
-	camel_filter_driver_parent = camel_type_get_global_classfuncs(camel_object_get_type());
-}
-
-static void
-camel_filter_driver_init (CamelFilterDriver *obj)
-{
-	struct _CamelFilterDriverPrivate *p;
-	int i;
-	
-	p = _PRIVATE (obj) = g_malloc0 (sizeof (*p));
-
-	e_dlist_init(&p->rules);
-
-	p->eval = e_sexp_new ();
-	/* Load in builtin symbols */
-	for (i = 0; i < sizeof (symbols) / sizeof (symbols[0]); i++) {
-		if (symbols[i].type == 1) {
-			e_sexp_add_ifunction (p->eval, 0, symbols[i].name, (ESExpIFunc *)symbols[i].func, obj);
-		} else {
-			e_sexp_add_function (p->eval, 0, symbols[i].name, symbols[i].func, obj);
-		}
-	}
-	
-	p->globals = g_hash_table_new (g_str_hash, g_str_equal);
-	
-	p->folders = g_hash_table_new (g_str_hash, g_str_equal);
-	
-	p->only_once = g_hash_table_new (g_str_hash, g_str_equal);
-}
-
-static void
-free_hash_strings (void *key, void *value, void *data)
-{
-	g_free (key);
-	g_free (value);
-}
-
-static void
-camel_filter_driver_finalise (CamelObject *obj)
-{
-	CamelFilterDriver *driver = (CamelFilterDriver *) obj;
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);	
-	struct _filter_rule *node;
-
-	/* close all folders that were opened for appending */
-	close_folders (driver);
-	g_hash_table_destroy (p->folders);
-	
-	g_hash_table_foreach (p->globals, free_hash_strings, driver);
-	g_hash_table_destroy (p->globals);
-	
-	g_hash_table_foreach (p->only_once, free_hash_strings, driver);
-	g_hash_table_destroy (p->only_once);
-	
-	e_sexp_unref(p->eval);
-	
-	if (p->defaultfolder) {
-		camel_folder_thaw (p->defaultfolder);
-		camel_object_unref (p->defaultfolder);
-	}
-
-	while ((node = (struct _filter_rule *)e_dlist_remhead(&p->rules))) {
-		g_free(node->match);
-		g_free(node->action);
-		g_free(node->name);
-		g_free(node);
-	}
-
-	camel_object_unref(p->session);
-
-	g_free (p);
-}
-
-/**
- * camel_filter_driver_new:
- *
- * Return value: A new CamelFilterDriver object
- **/
-CamelFilterDriver *
-camel_filter_driver_new (CamelSession *session)
-{
-	CamelFilterDriver *d = (CamelFilterDriver *)camel_object_new(camel_filter_driver_get_type());
-
-	d->priv->session = session;
-	camel_object_ref((CamelObject *)session);
-
-	return d;
-}
-
-void
-camel_filter_driver_set_folder_func (CamelFilterDriver *d, CamelFilterGetFolderFunc get_folder, void *data)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-
-	p->get_folder = get_folder;
-	p->data = data;
-}
-
-void
-camel_filter_driver_set_logfile (CamelFilterDriver *d, FILE *logfile)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-	
-	p->logfile = logfile;
-}
-
-void
-camel_filter_driver_set_status_func (CamelFilterDriver *d, CamelFilterStatusFunc *func, void *data)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-	
-	p->statusfunc = func;
-	p->statusdata = data;
-}
-
-void
-camel_filter_driver_set_shell_func (CamelFilterDriver *d, CamelFilterShellFunc *func, void *data)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-	
-	p->shellfunc = func;
-	p->shelldata = data;
-}
-
-void
-camel_filter_driver_set_play_sound_func (CamelFilterDriver *d, CamelFilterPlaySoundFunc *func, void *data)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-	
-	p->playfunc = func;
-	p->playdata = data;
-}
-
-void
-camel_filter_driver_set_system_beep_func (CamelFilterDriver *d, CamelFilterSystemBeepFunc *func, void *data)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-	
-	p->beep = func;
-	p->beepdata = data;
-}
-
-void
-camel_filter_driver_set_default_folder (CamelFilterDriver *d, CamelFolder *def)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-	
-	if (p->defaultfolder) {
-		camel_folder_thaw (p->defaultfolder);
-		camel_object_unref (p->defaultfolder);
-	}
-	
-	p->defaultfolder = def;
-	
-	if (p->defaultfolder) {
-		camel_folder_freeze (p->defaultfolder);
-		camel_object_ref (p->defaultfolder);
-	}
-}
-
-void
-camel_filter_driver_add_rule(CamelFilterDriver *d, const char *name, const char *match, const char *action)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-	struct _filter_rule *node;
-
-	node = g_malloc(sizeof(*node));
-	node->match = g_strdup(match);
-	node->action = g_strdup(action);
-	node->name = g_strdup(name);
-	e_dlist_addtail(&p->rules, (EDListNode *)node);
-}
-
-int
-camel_filter_driver_remove_rule_by_name (CamelFilterDriver *d, const char *name)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-	struct _filter_rule *node;
-	
-	node = (struct _filter_rule *) p->rules.head;
-	while (node->next) {
-		if (!strcmp (node->name, name)) {
-			e_dlist_remove ((EDListNode *) node);
-			g_free (node->match);
-			g_free (node->action);
-			g_free (node->name);
-			g_free (node);
-			
-			return 0;
-		}
-		
-		node = node->next;
-	}
-	
-	return -1;
-}
-
-static void
-report_status (CamelFilterDriver *driver, enum camel_filter_status_t status, int pc, const char *desc, ...)
-{
-	/* call user-defined status report function */
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	va_list ap;
-	char *str;
-	
-	if (p->statusfunc) {
-		va_start (ap, desc);
-		str = g_strdup_vprintf (desc, ap);
-		p->statusfunc (driver, status, pc, str, p->statusdata);
-		g_free (str);
-	}
-}
-
-
-#if 0
-void
-camel_filter_driver_set_global (CamelFilterDriver *d, const char *name, const char *value)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-	char *oldkey, *oldvalue;
-	
-	if (g_hash_table_lookup_extended (p->globals, name, (void *)&oldkey, (void *)&oldvalue)) {
-		g_free (oldvalue);
-		g_hash_table_insert (p->globals, oldkey, g_strdup (value));
-	} else {
-		g_hash_table_insert (p->globals, g_strdup (name), g_strdup (value));
-	}
-}
-#endif
-
-static ESExpResult *
-do_delete (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	
-	d(fprintf (stderr, "doing delete\n"));
-	p->deleted = TRUE;
-	camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Delete");
-	
-	return NULL;
-}
-
-static ESExpResult *
-mark_forward (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	/*struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);*/
-	
-	d(fprintf (stderr, "marking message for forwarding\n"));
-	/* FIXME: do stuff here */
-	camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Forward");
-	
-	return NULL;
-}
-
-static ESExpResult *
-do_copy (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	int i;
-	
-	d(fprintf (stderr, "copying message...\n"));
-	
-	for (i = 0; i < argc; i++) {
-		if (argv[i]->type == ESEXP_RES_STRING) {
-			/* open folders we intent to copy to */
-			char *folder = argv[i]->value.string;
-			CamelFolder *outbox;
-			
-			outbox = open_folder (driver, folder);
-			if (!outbox)
-				break;
-			
-			if (outbox == p->source)
-				break;
-			
-			if (!p->modified && p->uid && p->source && camel_folder_has_summary_capability (p->source)) {
-				GPtrArray *uids;
-				
-				uids = g_ptr_array_new ();
-				g_ptr_array_add (uids, (char *) p->uid);
-				camel_folder_transfer_messages_to (p->source, uids, outbox, NULL, FALSE, p->ex);
-				g_ptr_array_free (uids, TRUE);
-			} else {
-				if (p->message == NULL)
-					p->message = camel_folder_get_message (p->source, p->uid, p->ex);
-				
-				if (!p->message)
-					continue;
-				
-				camel_folder_append_message (outbox, p->message, p->info, NULL, p->ex);
-			}
-			
-			if (!camel_exception_is_set (p->ex))
-				p->copied = TRUE;
-			
-			camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Copy to folder %s",
-						 folder);
-		}
-	}
-	
-	return NULL;
-}
-
-static ESExpResult *
-do_move (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	int i;
-	
-	d(fprintf (stderr, "moving message...\n"));
-	
-	for (i = 0; i < argc; i++) {
-		if (argv[i]->type == ESEXP_RES_STRING) {
-			/* open folders we intent to move to */
-			char *folder = argv[i]->value.string;
-			CamelFolder *outbox;
-			
-			outbox = open_folder (driver, folder);
-			if (!outbox)
-				break;
-			
-			if (outbox == p->source)
-				break;
-			
-			if (!p->modified && p->uid && p->source && camel_folder_has_summary_capability (p->source)) {
-				GPtrArray *uids;
-				
-				uids = g_ptr_array_new ();
-				g_ptr_array_add (uids, (char *) p->uid);
-				camel_folder_transfer_messages_to (p->source, uids, outbox, NULL, FALSE, p->ex);
-				g_ptr_array_free (uids, TRUE);
-			} else {
-				if (p->message == NULL)
-					p->message = camel_folder_get_message (p->source, p->uid, p->ex);
-				
-				if (!p->message)
-					continue;
-				
-				camel_folder_append_message (outbox, p->message, p->info, NULL, p->ex);
-			}
-			
-			if (!camel_exception_is_set (p->ex)) {
-				/* a 'move' is a copy & delete */
-				p->copied = TRUE;
-				p->deleted = TRUE;
-			}
-			
-			camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Move to folder %s",
-						 folder);
-		}
-	}
-	
-	return NULL;
-}
-
-static ESExpResult *
-do_stop (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	
-	camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Stopped processing");
-	d(fprintf (stderr, "terminating message processing\n"));
-	p->terminated = TRUE;
-	
-	return NULL;
-}
-
-static ESExpResult *
-do_colour (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	
-	d(fprintf (stderr, "setting colour tag\n"));
-	if (argc > 0 && argv[0]->type == ESEXP_RES_STRING) {
-		if (p->source && p->uid && camel_folder_has_summary_capability (p->source))
-			camel_folder_set_message_user_tag (p->source, p->uid, "colour", argv[0]->value.string);
-		else
-			camel_tag_set (&p->info->user_tags, "colour", argv[0]->value.string);
-		camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Set colour to %s", argv[0]->value.string);
-	}
-	
-	return NULL;
-}
-
-static ESExpResult *
-do_score (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	
-	d(fprintf (stderr, "setting score tag\n"));
-	if (argc > 0 && argv[0]->type == ESEXP_RES_INT) {
-		char *value;
-		
-		value = g_strdup_printf ("%d", argv[0]->value.number);
-		if (p->source && p->uid && camel_folder_has_summary_capability (p->source))
-			camel_folder_set_message_user_tag (p->source, p->uid, "score", value);
-		else
-			camel_tag_set (&p->info->user_tags, "score", value);
-		camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Set score to %d", argv[0]->value.number);
-		g_free (value);
-	}
-	
-	return NULL;
-}
-
-static ESExpResult *
-set_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	guint32 flags;
-	
-	d(fprintf (stderr, "setting flag\n"));
-	if (argc == 1 && argv[0]->type == ESEXP_RES_STRING) {
-		flags = camel_system_flag (argv[0]->value.string);
-		if (p->source && p->uid && camel_folder_has_summary_capability (p->source))
-			camel_folder_set_message_flags (p->source, p->uid, flags, ~0);
-		else
-			p->info->flags |= flags | CAMEL_MESSAGE_FOLDER_FLAGGED;
-		camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Set %s flag", argv[0]->value.string);
-	}
-	
-	return NULL;
-}
-
-static ESExpResult *
-unset_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	guint32 flags;
-	
-	d(fprintf (stderr, "unsetting flag\n"));
-	if (argc == 1 && argv[0]->type == ESEXP_RES_STRING) {
-		flags = camel_system_flag (argv[0]->value.string);
-		if (p->source && p->uid && camel_folder_has_summary_capability (p->source))
-			camel_folder_set_message_flags (p->source, p->uid, flags, 0);
-		else
-			p->info->flags = (p->info->flags & ~flags) | CAMEL_MESSAGE_FOLDER_FLAGGED;
-		camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Unset %s flag", argv[0]->value.string);
-	}
-	
-	return NULL;
-}
-
-static int
-pipe_to_system (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	int result, status, fds[4], i;
-	CamelMimeMessage *message = NULL;
-	CamelMimeParser *parser;
-	CamelStream *stream, *mem;
-	pid_t pid;
-	
-	if (argc < 1 || argv[0]->value.string[0] == '\0')
-		return 0;
-	
-	/* make sure we have the message... */
-	if (p->message == NULL) {
-		if (!(p->message = camel_folder_get_message (p->source, p->uid, p->ex)))
-			return -1;
-	}
-	
-	for (i = 0; i < 4; i++)
-		fds[i] = -1;
-	
-	for (i = 0; i < 4; i += 2) {
-		if (pipe (fds + i) == -1) {
-			camel_exception_setv (p->ex, CAMEL_EXCEPTION_SYSTEM,
-					      _("Failed to create pipe to '%s': %s"),
-					      argv[0]->value.string, g_strerror (errno));
-			
-			for (i = 0; i < 4; i++) {
-				if (fds[i] == -1)
-					break;
-				close (fds[i]);
-			}
-			
-			return -1;
-		}
-	}
-	
-	if (!(pid = fork ())) {
-		/* child process */
-		GPtrArray *args;
-		int maxfd, fd;
-		
-		fd = open ("/dev/null", O_WRONLY);
-		
-		if (dup2 (fds[0], STDIN_FILENO) < 0 ||
-		    dup2 (fds[3], STDOUT_FILENO) < 0 ||
-		    dup2 (fd, STDERR_FILENO) < 0)
-			_exit (255);
-		
-		setsid ();
-		
-		maxfd = sysconf (_SC_OPEN_MAX);
-		for (fd = 3; fd < maxfd; fd++)
-			fcntl (fd, F_SETFD, FD_CLOEXEC);
-		
-		args = g_ptr_array_new ();
-		for (i = 0; i < argc; i++)
-			g_ptr_array_add (args, argv[i]->value.string);
-		g_ptr_array_add (args, NULL);
-		
-		execvp (argv[0]->value.string, (char **) args->pdata);
-		
-		g_ptr_array_free (args, TRUE);
-		
-		d(printf ("Could not execute %s: %s\n", argv[0]->value.string, g_strerror (errno)));
-		_exit (255);
-	} else if (pid < 0) {
-		camel_exception_setv (p->ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Failed to create create child process '%s': %s"),
-				      argv[0]->value.string, g_strerror (errno));
-		return -1;
-	}
-	
-	/* parent process */
-	close (fds[0]);
-	close (fds[3]);
-	
-	stream = camel_stream_fs_new_with_fd (fds[1]);
-	if (camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (p->message), stream) == -1) {
-		camel_object_unref (stream);
-		close (fds[2]);
-		goto wait;
-	}
-	
-	if (camel_stream_flush (stream) == -1) {
-		camel_object_unref (stream);
-		close (fds[2]);
-		goto wait;
-	}
-	
-	camel_object_unref (stream);
-	
-	stream = camel_stream_fs_new_with_fd (fds[2]);
-	mem = camel_stream_mem_new ();
-	if (camel_stream_write_to_stream (stream, mem) == -1) {
-		camel_object_unref (stream);
-		camel_object_unref (mem);
-		goto wait;
-	}
-	
-	camel_object_unref (stream);
-	camel_stream_reset (mem);
-	
-	parser = camel_mime_parser_new ();
-	camel_mime_parser_init_with_stream (parser, mem);
-	camel_mime_parser_scan_from (parser, FALSE);
-	camel_object_unref (mem);
-	
-	message = camel_mime_message_new ();
-	if (camel_mime_part_construct_from_parser ((CamelMimePart *) message, parser) == -1) {
-		camel_exception_setv (p->ex, CAMEL_EXCEPTION_SYSTEM,
-				     _("Invalid message stream received from %s: %s"),
-				      argv[0]->value.string,
-				      g_strerror (camel_mime_parser_errno (parser)));
-		camel_object_unref (message);
-		message = NULL;
-	} else {
-		camel_object_unref (p->message);
-		p->message = message;
-		p->modified = TRUE;
-	}
-	
-	camel_object_unref (parser);
-	
- wait:
-	
-	result = waitpid (pid, &status, 0);
-	
-	if (result == -1 && errno == EINTR) {
-		/* child process is hanging... */
-		kill (pid, SIGTERM);
-		sleep (1);
-		result = waitpid (pid, &status, WNOHANG);
-		if (result == 0) {
-			/* ...still hanging, set phasers to KILL */
-			kill (pid, SIGKILL);
-			sleep (1);
-			result = waitpid (pid, &status, WNOHANG);
-		}
-	}
-	
-	if (message && result != -1 && WIFEXITED (status))
-		return WEXITSTATUS (status);
-	else
-		return -1;
-}
-
-static ESExpResult *
-pipe_message (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	int i;
-	
-	/* make sure all args are strings */
-	for (i = 0; i < argc; i++) {
-		if (argv[i]->type != ESEXP_RES_STRING)
-			return NULL;
-	}
-	
-	camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Piping message to %s", argv[0]->value.string);
-	pipe_to_system (f, argc, argv, driver);
-	
-	return NULL;
-}
-
-static ESExpResult *
-do_shell (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	GString *command;
-	GPtrArray *args;
-	int i;
-	
-	d(fprintf (stderr, "executing shell command\n"));
-	
-	command = g_string_new ("");
-	
-	args = g_ptr_array_new ();
-	
-	/* make sure all args are strings */
-	for (i = 0; i < argc; i++) {
-		if (argv[i]->type != ESEXP_RES_STRING)
-			goto done;
-		
-		g_ptr_array_add (args, argv[i]->value.string);
-		
-		g_string_append (command, argv[i]->value.string);
-		g_string_append_c (command, ' ');
-	}
-	
-	g_string_truncate (command, command->len - 1);
-	
-	if (p->shellfunc && argc >= 1) {
-		p->shellfunc (driver, argc, (char **) args->pdata, p->shelldata);
-		camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Executing shell command: [%s]",
-					 command->str);
-	}
-	
- done:
-	
-	g_ptr_array_free (args, TRUE);
-	g_string_free (command, TRUE);
-	
-	return NULL;
-}
-
-static ESExpResult *
-do_beep (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	
-	d(fprintf (stderr, "beep\n"));
-	
-	if (p->beep) {
-		p->beep (driver, p->beepdata);
-		camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Beep");
-	}
-	
-	return NULL;
-}
-
-static ESExpResult *
-play_sound (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	
-	d(fprintf (stderr, "play sound\n"));
-	
-	if (p->playfunc && argc == 1 && argv[0]->type == ESEXP_RES_STRING) {
-		p->playfunc (driver, argv[0]->value.string, p->playdata);
-		camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Play sound");
-	}
-	
-	return NULL;
-}
-
-static ESExpResult *
-do_only_once (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	
-	d(fprintf (stderr, "only once\n"));
-	
-	if (argc == 2 && !g_hash_table_lookup (p->only_once, argv[0]->value.string))
-		g_hash_table_insert (p->only_once, g_strdup (argv[0]->value.string),
-				     g_strdup (argv[1]->value.string));
-	
-	return NULL;
-}
-
-static CamelFolder *
-open_folder (CamelFilterDriver *driver, const char *folder_url)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	CamelFolder *camelfolder;
-	CamelException ex;
-	
-	/* we have a lookup table of currently open folders */
-	camelfolder = g_hash_table_lookup (p->folders, folder_url);
-	if (camelfolder)
-		return camelfolder == FOLDER_INVALID?NULL:camelfolder;
-	
-	camel_exception_init (&ex);
-	camelfolder = p->get_folder (driver, folder_url, p->data, &ex);
-	camel_exception_clear (&ex);
-	
-	if (camelfolder) {
-		g_hash_table_insert (p->folders, g_strdup (folder_url), camelfolder);
-		camel_folder_freeze (camelfolder);
-	} else {
-		g_hash_table_insert (p->folders, g_strdup (folder_url), FOLDER_INVALID);
-	}
-	
-	return camelfolder;
-}
-
-static void
-close_folder (void *key, void *value, void *data)
-{	
-	CamelFolder *folder = value;
-	CamelFilterDriver *driver = data;
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-
-	p->closed++;
-	g_free (key);
-
-	if (folder != FOLDER_INVALID) {
-		camel_folder_sync (folder, FALSE, p->ex);
-		camel_folder_thaw (folder);
-		camel_object_unref (folder);
-	}
-
-	report_status(driver, CAMEL_FILTER_STATUS_PROGRESS, g_hash_table_size(p->folders)* 100 / p->closed, _("Syncing folders"));
-}
-
-/* flush/close all folders */
-static int
-close_folders (CamelFilterDriver *driver)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-
-	report_status(driver, CAMEL_FILTER_STATUS_PROGRESS, 0, _("Syncing folders"));
-
-	p->closed = 0;
-	g_hash_table_foreach (p->folders, close_folder, driver);
-	g_hash_table_destroy (p->folders);
-	p->folders = g_hash_table_new (g_str_hash, g_str_equal);
-	
-	/* FIXME: status from driver */
-	return 0;
-}
-
-#if 0
-static void
-free_key (gpointer key, gpointer value, gpointer user_data)
-{
-	g_free (key);
-}
-#endif
-
-
-static void
-camel_filter_driver_log (CamelFilterDriver *driver, enum filter_log_t status, const char *desc, ...)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	
-	if (p->logfile) {
-		char *str = NULL;
-		
-		if (desc) {
-			va_list ap;
-			
-			va_start (ap, desc);
-			str = g_strdup_vprintf (desc, ap);
-		}
-		
-		switch (status) {
-		case FILTER_LOG_START: {
-			/* write log header */
-			const char *subject = NULL;
-			const char *from = NULL;
-			char date[50];
-			time_t t;
-			
-			/* FIXME: does this need locking?  Probably */
-			
-			from = camel_message_info_from (p->info);
-			subject = camel_message_info_subject (p->info);
-			
-			time (&t);
-			strftime (date, 49, "%a, %d %b %Y %H:%M:%S", localtime (&t));
-			fprintf (p->logfile, "Applied filter \"%s\" to message from %s - \"%s\" at %s\n",
-				 str, from ? from : "unknown", subject ? subject : "", date);
-			
-			break;
-		}
-		case FILTER_LOG_ACTION:
-			fprintf (p->logfile, "Action: %s\n", str);
-			break;
-		case FILTER_LOG_END:
-			fprintf (p->logfile, "\n");
-			break;
-		default:
-			/* nothing else is loggable */
-			break;
-		}
-		
-		g_free (str);
-	}
-}
-
-
-struct _run_only_once {
-	CamelFilterDriver *driver;
-	CamelException *ex;
-};
-
-static gboolean
-run_only_once (gpointer key, char *action, struct _run_only_once *data)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (data->driver);
-	CamelException *ex = data->ex;
-	ESExpResult *r;
-	
-	d(printf ("evaluating: %s\n\n", action));
-	
-	e_sexp_input_text (p->eval, action, strlen (action));
-	if (e_sexp_parse (p->eval) == -1) {
-		if (!camel_exception_is_set (ex))
-			camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-					      _("Error parsing filter: %s: %s"),
-					      e_sexp_error (p->eval), action);
-		goto done;
-	}
-	
-	r = e_sexp_eval (p->eval);
-	if (r == NULL) {
-		if (!camel_exception_is_set (ex))
-			camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-					      _("Error executing filter: %s: %s"),
-					      e_sexp_error (p->eval), action);
-		goto done;
-	}
-	
-	e_sexp_result_free (p->eval, r);
-	
- done:
-	
-	g_free (key);
-	g_free (action);
-	
-	return TRUE;
-}
-
-
-/**
- * camel_filter_driver_flush:
- * @driver:
- * @ex:
- *
- * Flush all of the only-once filter actions.
- **/
-void
-camel_filter_driver_flush (CamelFilterDriver *driver, CamelException *ex)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	struct _run_only_once data;
-	
-	if (!p->only_once)
-		return;
-	
-	data.driver = driver;
-	data.ex = ex;
-	
-	g_hash_table_foreach_remove (p->only_once, (GHRFunc) run_only_once, &data);
-}
-
-/**
- * camel_filter_driver_filter_mbox:
- * @driver: CamelFilterDriver
- * @mbox: mbox filename to be filtered
- * @ex: exception
- *
- * Filters an mbox file based on rules defined in the FilterDriver
- * object. Is more efficient as it doesn't need to open the folder
- * through Camel directly.
- *
- * Returns -1 if errors were encountered during filtering,
- * otherwise returns 0.
- *
- **/
-int
-camel_filter_driver_filter_mbox (CamelFilterDriver *driver, const char *mbox, const char *original_source_url, CamelException *ex)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	CamelMimeParser *mp = NULL;
-	char *source_url = NULL;
-	int fd = -1;
-	int i = 0;
-	struct stat st;
-	int status;
-	off_t last = 0;
-	int ret = -1;
-	
-	fd = open (mbox, O_RDONLY);
-	if (fd == -1) {
-		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Unable to open spool folder"));
-		goto fail;
-	}
-	/* to get the filesize */
-	fstat (fd, &st);
-	
-	mp = camel_mime_parser_new ();
-	camel_mime_parser_scan_from (mp, TRUE);
-	if (camel_mime_parser_init_with_fd (mp, fd) == -1) {
-		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Unable to process spool folder"));
-		goto fail;
-	}
-	fd = -1;
-	
-	source_url = g_strdup_printf ("file://%s", mbox);
-	
-	while (camel_mime_parser_step (mp, 0, 0) == CAMEL_MIME_PARSER_STATE_FROM) {
-		CamelMessageInfo *info;
-		CamelMimeMessage *msg;
-		int pc = 0;
-		
-		if (st.st_size > 0)
-			pc = (int)(100.0 * ((double)camel_mime_parser_tell (mp) / (double)st.st_size));
-		
-		report_status (driver, CAMEL_FILTER_STATUS_START, pc, _("Getting message %d (%d%%)"), i, pc);
-		
-		msg = camel_mime_message_new ();
-		if (camel_mime_part_construct_from_parser (CAMEL_MIME_PART (msg), mp) == -1) {
-			camel_exception_set (ex, (errno==EINTR)?CAMEL_EXCEPTION_USER_CANCEL:CAMEL_EXCEPTION_SYSTEM, _("Cannot open message"));
-			report_status (driver, CAMEL_FILTER_STATUS_END, 100, _("Failed on message %d"), i);
-			camel_object_unref (msg);
-			goto fail;
-		}
-		
-		info = camel_message_info_new_from_header(((CamelMimePart *)msg)->headers);
-		info->size = camel_mime_parser_tell(mp) - last;
-		last = camel_mime_parser_tell(mp);
-		status = camel_filter_driver_filter_message (driver, msg, info, NULL, NULL, source_url, 
-							     original_source_url ? original_source_url : source_url, ex);
-		camel_object_unref (msg);
-		if (camel_exception_is_set (ex) || status == -1) {
-			report_status (driver, CAMEL_FILTER_STATUS_END, 100, _("Failed on message %d"), i);
-			camel_message_info_free (info);
-			goto fail;
-		}
-		
-		i++;
-		
-		/* skip over the FROM_END state */
-		camel_mime_parser_step (mp, 0, 0);
-
-		camel_message_info_free (info);
-	}
-	
-	if (p->defaultfolder) {
-		report_status(driver, CAMEL_FILTER_STATUS_PROGRESS, 100, _("Syncing folder"));
-		camel_folder_sync(p->defaultfolder, FALSE, camel_exception_is_set (ex) ? NULL : ex);
-	}
-	
-	report_status (driver, CAMEL_FILTER_STATUS_END, 100, _("Complete"));
-	
-	ret = 0;
-fail:
-	g_free (source_url);
-	if (fd != -1)
-		close (fd);
-	if (mp)
-		camel_object_unref (mp);
-	
-	return -1;
-}
-
-
-/**
- * camel_filter_driver_filter_folder:
- * @driver: CamelFilterDriver
- * @folder: CamelFolder to be filtered
- * @cache: UID cache (needed for POP folders)
- * @uids: message uids to be filtered or NULL (as a shortcut to filter all messages)
- * @remove: TRUE to mark filtered messages as deleted
- * @ex: exception
- *
- * Filters a folder based on rules defined in the FilterDriver
- * object.
- *
- * Returns -1 if errors were encountered during filtering,
- * otherwise returns 0.
- *
- **/
-int
-camel_filter_driver_filter_folder (CamelFilterDriver *driver, CamelFolder *folder, CamelUIDCache *cache,
-				   GPtrArray *uids, gboolean remove, CamelException *ex)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	gboolean freeuids = FALSE;
-	CamelMessageInfo *info;
-	char *source_url, *service_url;
-	int status = 0;
-	CamelURL *url;
-	int i;
-	
-	service_url = camel_service_get_url (CAMEL_SERVICE (camel_folder_get_parent_store (folder)));
-	url = camel_url_new (service_url, NULL);
-	g_free (service_url);
-	
-	source_url = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
-	camel_url_free (url);
-	
-	if (uids == NULL) {
-		uids = camel_folder_get_uids (folder);
-		freeuids = TRUE;
-	}
-	
-	for (i = 0; i < uids->len; i++) {
-		int pc = (100 * i)/uids->len;
-		
-		report_status (driver, CAMEL_FILTER_STATUS_START, pc, _("Getting message %d of %d"), i+1,
-			       uids->len);
-		
-		if (camel_folder_has_summary_capability (folder))
-			info = camel_folder_get_message_info (folder, uids->pdata[i]);
-		else
-			info = NULL;
-		
-		status = camel_filter_driver_filter_message (driver, NULL, info, uids->pdata[i],
-							     folder, source_url, source_url, ex);
-		
-		if (camel_folder_has_summary_capability (folder))
-			camel_folder_free_message_info (folder, info);
-		
-		if (camel_exception_is_set (ex) || status == -1) {
-			report_status (driver, CAMEL_FILTER_STATUS_END, 100, _("Failed at message %d of %d"),
-				       i+1, uids->len);
-			status = -1;
-			break;
-		}
-		
-		if (remove)
-			camel_folder_set_message_flags (folder, uids->pdata[i],
-							CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN, ~0);
-		
-		if (cache)
-			camel_uid_cache_save_uid (cache, uids->pdata[i]);
-	}
-	
-	if (freeuids)
-		camel_folder_free_uids (folder, uids);
-	
-	if (p->defaultfolder) {
-		report_status (driver, CAMEL_FILTER_STATUS_PROGRESS, 100, _("Syncing folder"));
-		camel_folder_sync (p->defaultfolder, FALSE, camel_exception_is_set (ex) ? NULL : ex);
-	}
-	
-	if (i == uids->len)
-		report_status (driver, CAMEL_FILTER_STATUS_END, 100, _("Complete"));
-	
-	g_free (source_url);
-	
-	return status;
-}
-
-
-struct _get_message {
-	struct _CamelFilterDriverPrivate *p;
-	const char *source_url;
-};
-
-
-static CamelMimeMessage *
-get_message_cb (void *data, CamelException *ex)
-{
-	struct _get_message *msgdata = data;
-	struct _CamelFilterDriverPrivate *p = msgdata->p;
-	const char *source_url = msgdata->source_url;
-	CamelMimeMessage *message;
-	
-	if (p->message) {
-		message = p->message;
-		camel_object_ref (message);
-	} else {
-		const char *uid;
-		
-		if (p->uid)
-			uid = p->uid;
-		else
-			uid = camel_message_info_uid (p->info);
-		
-		message = camel_folder_get_message (p->source, uid, ex);
-	}
-	
-	if (source_url && message && camel_mime_message_get_source (message) == NULL)
-		camel_mime_message_set_source (message, source_url);
-	
-	return message;
-}
-
-/**
- * camel_filter_driver_filter_message:
- * @driver: CamelFilterDriver
- * @message: message to filter or NULL
- * @info: message info or NULL
- * @uid: message uid or NULL
- * @source: source folder or NULL
- * @source_url: url of source folder or NULL
- * @original_source_url: url of original source folder (pre-movemail) or NULL
- * @ex: exception
- *
- * Filters a message based on rules defined in the FilterDriver
- * object. If the source folder (@source) and the uid (@uid) are
- * provided, the filter will operate on the CamelFolder (which in
- * certain cases is more efficient than using the default
- * camel_folder_append_message() function).
- *
- * Returns -1 if errors were encountered during filtering,
- * otherwise returns 0.
- *
- **/
-int
-camel_filter_driver_filter_message (CamelFilterDriver *driver, CamelMimeMessage *message,
-				    CamelMessageInfo *info, const char *uid,
-				    CamelFolder *source, const char *source_url,
-				    const char *original_source_url,
-				    CamelException *ex)
-{
-	struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-	struct _filter_rule *node;
-	gboolean freeinfo = FALSE;
-	gboolean filtered = FALSE;
-	ESExpResult *r;
-	int result;
-	
-	/* FIXME: make me into a g_return_if_fail/g_assert or whatever... */
-	if (message == NULL && (source == NULL || uid == NULL)) {
-		g_warning ("there is no way to fetch the message using the information provided...");
-		return -1;
-	}
-	
-	if (info == NULL) {
-		struct _camel_header_raw *h;
-		
-		if (message) {
-			camel_object_ref (message);
-		} else {
-			message = camel_folder_get_message (source, uid, ex);
-			if (!message)
-				return -1;
-		}
-		
-		h = CAMEL_MIME_PART (message)->headers;
-		info = camel_message_info_new_from_header (h);
-		freeinfo = TRUE;
-	} else {
-		if (info->flags & CAMEL_MESSAGE_DELETED)
-			return 0;
-		
-		uid = camel_message_info_uid (info);
-		
-		if (message)
-			camel_object_ref (message);
-	}
-	
-	p->ex = ex;
-	p->terminated = FALSE;
-	p->deleted = FALSE;
-	p->copied = FALSE;
-	p->message = message;
-	p->info = info;
-	p->uid = uid;
-	p->source = source;
-	
-	if (message && original_source_url && camel_mime_message_get_source (message) == NULL)
-		camel_mime_message_set_source (message, original_source_url);
-	
-	node = (struct _filter_rule *) p->rules.head;
-	result = CAMEL_SEARCH_NOMATCH;
-	while (node->next && !p->terminated) {
-		struct _get_message data;
-		
-		d(fprintf (stderr, "applying rule %s\naction %s\n", node->match, node->action));
-		
-		data.p = p;
-		data.source_url = original_source_url;
-		
-		result = camel_filter_search_match (p->session, get_message_cb, &data, p->info, 
-						    original_source_url ? original_source_url : source_url,
-						    node->match, p->ex);
-		
-		switch (result) {
-		case CAMEL_SEARCH_ERROR:
-			goto error;
-		case CAMEL_SEARCH_MATCHED:
-			filtered = TRUE;
-			camel_filter_driver_log (driver, FILTER_LOG_START, node->name);
-			
-			/* perform necessary filtering actions */
-			e_sexp_input_text (p->eval, node->action, strlen (node->action));
-			if (e_sexp_parse (p->eval) == -1) {
-				camel_exception_setv (ex, 1, _("Error parsing filter: %s: %s"),
-						      e_sexp_error (p->eval), node->action);
-				goto error;
-			}
-			r = e_sexp_eval (p->eval);
-			if (r == NULL) {
-				camel_exception_setv (ex, 1, _("Error executing filter: %s: %s"),
-						      e_sexp_error (p->eval), node->action);
-				goto error;
-			}
-			e_sexp_result_free (p->eval, r);
-		default:
-			break;
-		}
-		
-		node = node->next;
-	}
-	
-	/* *Now* we can set the DELETED flag... */
-	if (p->deleted) {
-		if (p->source && p->uid && camel_folder_has_summary_capability (p->source))
-			camel_folder_set_message_flags(p->source, p->uid, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN, ~0);
-		else
-			info->flags |= CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_FOLDER_FLAGGED;
-	}
-	
-	/* Logic: if !Moved and there exists a default folder... */
-	if (!(p->copied && p->deleted) && p->defaultfolder) {
-		/* copy it to the default inbox */
-		filtered = TRUE;
-		camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Copy to default folder");
-		if (!p->modified && p->uid && p->source && camel_folder_has_summary_capability (p->source)) {
-			GPtrArray *uids;
-			
-			uids = g_ptr_array_new ();
-			g_ptr_array_add (uids, (char *) p->uid);
-			camel_folder_transfer_messages_to (p->source, uids, p->defaultfolder, NULL, FALSE, p->ex);
-			g_ptr_array_free (uids, TRUE);
-		} else {
-			if (p->message == NULL) {
-				p->message = camel_folder_get_message (source, uid, ex);
-				if (!p->message)
-					goto error;
-			}
-			
-			camel_folder_append_message (p->defaultfolder, p->message, p->info, NULL, p->ex);
-		}
-	}
-	
-	if (p->message)
-		camel_object_unref (p->message);
-	
-	if (freeinfo)
-		camel_message_info_free (info);
-	
-	return 0;
-	
- error:
-	if (filtered)
-		camel_filter_driver_log (driver, FILTER_LOG_END, NULL);
-	
-	if (p->message)
-		camel_object_unref (p->message);
-	
-	if (freeinfo)
-		camel_message_info_free (info);
-	
-	return -1;
-}
diff --git a/camel/camel-filter-driver.h b/camel/camel-filter-driver.h
deleted file mode 100644
index 8295859cb0..0000000000
--- a/camel/camel-filter-driver.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- *  Copyright (C) 2000 Ximian Inc.
- *
- *  Authors: Michael Zucchi 
- *           Jeffrey Stedfast 
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef _CAMEL_FILTER_DRIVER_H
-#define _CAMEL_FILTER_DRIVER_H
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#define CAMEL_FILTER_DRIVER_TYPE         (camel_filter_driver_get_type ())
-#define CAMEL_FILTER_DRIVER(obj)         CAMEL_CHECK_CAST (obj, CAMEL_FILTER_DRIVER_TYPE, CamelFilterDriver)
-#define CAMEL_FILTER_DRIVER_CLASS(klass) CAMEL__CHECK_CLASS_CAST (klass, CAMEL_FILTER_DRIVER_TYPE, CamelFilterDriverClass)
-#define CAMEL_IS_FILTER_DRIVER(obj)      CAMEL_CHECK_TYPE (obj, CAMEL_FILTER_DRIVER_TYPE)
-
-typedef struct _CamelFilterDriverClass CamelFilterDriverClass;
-
-struct _CamelFilterDriver {
-	CamelObject parent;
-	
-	struct _CamelFilterDriverPrivate *priv;
-};
-
-struct _CamelFilterDriverClass {
-	CamelObjectClass parent_class;
-};
-
-/* FIXME: this maybe should change... */
-/* type of status for a status report */
-enum camel_filter_status_t {
-	CAMEL_FILTER_STATUS_NONE,
-	CAMEL_FILTER_STATUS_START,	/* start of new message processed */
-	CAMEL_FILTER_STATUS_ACTION,	/* an action performed */
-	CAMEL_FILTER_STATUS_PROGRESS,	/* (an) extra update(s), if its taking longer to process */
-	CAMEL_FILTER_STATUS_END,	/* end of message */
-};
-
-typedef CamelFolder * (*CamelFilterGetFolderFunc) (CamelFilterDriver *driver, const char *uri,
-						   void *data, CamelException *ex);
-/* report status */
-typedef void (CamelFilterStatusFunc) (CamelFilterDriver *driver, enum camel_filter_status_t status,
-				      int pc, const char *desc, void *data);
-
-typedef void (CamelFilterShellFunc)      (CamelFilterDriver *driver, int argc, char **argv, void *data);
-typedef void (CamelFilterPlaySoundFunc)  (CamelFilterDriver *driver, const char *filename, void *data);
-typedef void (CamelFilterSystemBeepFunc) (CamelFilterDriver *driver, void *data);
-
-CamelType          camel_filter_driver_get_type (void);
-CamelFilterDriver  *camel_filter_driver_new     (CamelSession *);
-
-/* modifiers */
-void camel_filter_driver_set_logfile          (CamelFilterDriver *d, FILE *logfile);
-
-void camel_filter_driver_set_status_func      (CamelFilterDriver *d, CamelFilterStatusFunc *func, void *data);
-void camel_filter_driver_set_shell_func       (CamelFilterDriver *d, CamelFilterShellFunc *func, void *data);
-void camel_filter_driver_set_play_sound_func  (CamelFilterDriver *d, CamelFilterPlaySoundFunc *func, void *data);
-void camel_filter_driver_set_system_beep_func (CamelFilterDriver *d, CamelFilterSystemBeepFunc *func, void *data);
-void camel_filter_driver_set_folder_func      (CamelFilterDriver *d, CamelFilterGetFolderFunc fetcher, void *data);
-
-void camel_filter_driver_set_default_folder   (CamelFilterDriver *d, CamelFolder *def);
-
-void camel_filter_driver_add_rule             (CamelFilterDriver *d, const char *name, const char *match,
-					       const char *action);
-int  camel_filter_driver_remove_rule_by_name  (CamelFilterDriver *d, const char *name);
-
-/*void camel_filter_driver_set_global(CamelFilterDriver *, const char *name, const char *value);*/
-
-void camel_filter_driver_flush                (CamelFilterDriver *driver, CamelException *ex);
-
-int  camel_filter_driver_filter_message       (CamelFilterDriver *driver, CamelMimeMessage *message,
-					       CamelMessageInfo *info, const char *uri,
-					       CamelFolder *source, const char *source_url,
-					       const char *original_source_url, CamelException *ex);
-
-int  camel_filter_driver_filter_mbox          (CamelFilterDriver *driver, const char *mbox,
-					       const char *original_source_url, CamelException *ex);
-
-int  camel_filter_driver_filter_folder        (CamelFilterDriver *driver, CamelFolder *folder, CamelUIDCache *cache,
-					       GPtrArray *uids, gboolean remove, CamelException *ex);
-
-#if 0
-/* generate the search query/action string for a filter option */
-void camel_filter_driver_expand_option (CamelFilterDriver *d, GString *s, GString *action, struct filter_option *op);
-
-/* get info about rules (options) */
-int camel_filter_driver_rule_count (CamelFilterDriver *d);
-struct filter_option *camel_filter_driver_rule_get (CamelFilterDriver *d, int n);
-#endif
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* ! _CAMEL_FILTER_DRIVER_H */
diff --git a/camel/camel-filter-search.c b/camel/camel-filter-search.c
deleted file mode 100644
index 53fe074b10..0000000000
--- a/camel/camel-filter-search.c
+++ /dev/null
@@ -1,703 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *	     Michael Zucchi 
- *
- *  Copyright 2000 Ximian, Inc. (www.ximian.com)
- *  Copyright 2001 Ximian Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-/* (from glibc headers:
-   POSIX says that  must be included (by the caller) before .  */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include 
-
-#include 
-
-#include "camel-mime-message.h"
-#include "camel-provider.h"
-#include "camel-session.h"
-#include "camel-filter-search.h"
-#include "camel-exception.h"
-#include "camel-multipart.h"
-#include "camel-stream-mem.h"
-#include "camel-stream-fs.h"
-#include "camel-search-private.h"
-
-#include "camel-url.h"
-
-#define d(x)
-
-typedef struct {
-	CamelSession *session;
-	CamelFilterSearchGetMessageFunc get_message;
-	void *get_message_data;
-	CamelMimeMessage *message;
-	CamelMessageInfo *info;
-	const char *source;
-	CamelException *ex;
-} FilterMessageSearch;
-
-/* ESExp callbacks */
-static ESExpResult *header_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *header_matches (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *header_starts_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *header_ends_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *header_exists (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *header_soundex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *header_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *header_full_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *match_all (struct _ESExp *f, int argc, struct _ESExpTerm **argv, FilterMessageSearch *fms);
-static ESExpResult *body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *body_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *user_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *user_tag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *system_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *get_sent_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *get_received_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *get_current_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *header_source (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *get_size (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *pipe_message (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-static ESExpResult *junk_test (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
-
-/* builtin functions */
-static struct {
-	char *name;
-	ESExpFunc *func;
-	int type;		/* set to 1 if a function can perform shortcut evaluation, or
-				   doesn't execute everything, 0 otherwise */
-} symbols[] = {
-	{ "match-all",          (ESExpFunc *) match_all,          1 },
-	{ "body-contains",      (ESExpFunc *) body_contains,      0 },
-	{ "body-regex",         (ESExpFunc *) body_regex,         0 },
-	{ "header-contains",    (ESExpFunc *) header_contains,    0 },
-	{ "header-matches",     (ESExpFunc *) header_matches,     0 },
-	{ "header-starts-with", (ESExpFunc *) header_starts_with, 0 },
-	{ "header-ends-with",   (ESExpFunc *) header_ends_with,   0 },
-	{ "header-exists",      (ESExpFunc *) header_exists,      0 },
-	{ "header-soundex",     (ESExpFunc *) header_soundex,     0 },
-	{ "header-regex",       (ESExpFunc *) header_regex,       0 },
-	{ "header-full-regex",  (ESExpFunc *) header_full_regex,  0 },
-	{ "user-tag",           (ESExpFunc *) user_tag,           0 },
-	{ "user-flag",          (ESExpFunc *) user_flag,          0 },
-	{ "system-flag",        (ESExpFunc *) system_flag,        0 },
-	{ "get-sent-date",      (ESExpFunc *) get_sent_date,      0 },
-	{ "get-received-date",  (ESExpFunc *) get_received_date,  0 },
-	{ "get-current-date",   (ESExpFunc *) get_current_date,   0 },
-	{ "header-source",      (ESExpFunc *) header_source,      0 },
-	{ "get-size",           (ESExpFunc *) get_size,           0 },
-	{ "pipe-message",       (ESExpFunc *) pipe_message,       0 },
-	{ "junk-test",          (ESExpFunc *) junk_test,          0 },
-};
-
-
-static CamelMimeMessage *
-camel_filter_search_get_message (FilterMessageSearch *fms, struct _ESExp *sexp)
-{
-	if (fms->message)
-		return fms->message;
-	
-	fms->message = fms->get_message (fms->get_message_data, fms->ex);
-	
-	if (fms->message == NULL)
-		e_sexp_fatal_error (sexp, _("Failed to retrieve message"));
-	
-	return fms->message;
-}
-
-static ESExpResult *
-check_header (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms, camel_search_match_t how)
-{
-	gboolean matched = FALSE;
-	ESExpResult *r;
-	int i;
-	
-	if (argc > 1 && argv[0]->type == ESEXP_RES_STRING) {
-		char *name = argv[0]->value.string;
-		const char *header;
-		camel_search_t type = CAMEL_SEARCH_TYPE_ENCODED;
-		CamelContentType *ct;
-		const char *charset = NULL;
-		
-		if (strcasecmp(name, "x-camel-mlist") == 0) {
-			header = camel_message_info_mlist(fms->info);
-			type = CAMEL_SEARCH_TYPE_MLIST;
-		} else {
-			CamelMimeMessage *message = camel_filter_search_get_message (fms, f);
-			
-			header = camel_medium_get_header (CAMEL_MEDIUM (message), argv[0]->value.string);
-			/* FIXME: what about Resent-To, Resent-Cc and Resent-From? */
-			if (strcasecmp("to", name) == 0 || strcasecmp("cc", name) == 0 || strcasecmp("from", name) == 0)
-				type = CAMEL_SEARCH_TYPE_ADDRESS_ENCODED;
-			else {
-				ct = camel_mime_part_get_content_type (CAMEL_MIME_PART (message));
-				if (ct) {
-					charset = camel_content_type_param (ct, "charset");
-					charset = e_iconv_charset_name (charset);
-				}
-			}
-		}
-		
-		if (header) {
-			for (i=1; itype == ESEXP_RES_STRING)
-					matched = camel_search_header_match(header, argv[i]->value.string, how, type, charset);
-			}
-		}
-	}
-	
-	r = e_sexp_result_new (f, ESEXP_RES_BOOL);
-	r->value.bool = matched;
-	
-	return r;
-}
-
-static ESExpResult *
-header_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	return check_header (f, argc, argv, fms, CAMEL_SEARCH_MATCH_CONTAINS);
-}
-
-
-static ESExpResult *
-header_matches (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	return check_header (f, argc, argv, fms, CAMEL_SEARCH_MATCH_EXACT);
-}
-
-static ESExpResult *
-header_starts_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	return check_header (f, argc, argv, fms, CAMEL_SEARCH_MATCH_STARTS);
-}
-
-static ESExpResult *
-header_ends_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	return check_header (f, argc, argv, fms, CAMEL_SEARCH_MATCH_ENDS);
-}
-
-static ESExpResult *
-header_soundex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	return check_header (f, argc, argv, fms, CAMEL_SEARCH_MATCH_SOUNDEX);
-}
-
-static ESExpResult *
-header_exists (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	CamelMimeMessage *message;
-	gboolean matched = FALSE;
-	ESExpResult *r;
-	int i;
-	
-	message = camel_filter_search_get_message (fms, f);
-	
-	for (i = 0; i < argc && !matched; i++) {
-		if (argv[i]->type == ESEXP_RES_STRING)
-			matched = camel_medium_get_header (CAMEL_MEDIUM (message), argv[i]->value.string) != NULL;
-	}
-	
-	r = e_sexp_result_new (f, ESEXP_RES_BOOL);
-	r->value.bool = matched;
-	
-	return r;
-}
-
-static ESExpResult *
-header_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	ESExpResult *r = e_sexp_result_new (f, ESEXP_RES_BOOL);
-	CamelMimeMessage *message;
-	regex_t pattern;
-	const char *contents;
-	
-	message = camel_filter_search_get_message (fms, f);
-	
-	if (argc > 1 && argv[0]->type == ESEXP_RES_STRING
-	    && (contents = camel_medium_get_header (CAMEL_MEDIUM (message), argv[0]->value.string))
-	    && camel_search_build_match_regex(&pattern, CAMEL_SEARCH_MATCH_REGEX|CAMEL_SEARCH_MATCH_ICASE, argc-1, argv+1, fms->ex) == 0) {
-		r->value.bool = regexec (&pattern, contents, 0, NULL, 0) == 0;
-		regfree (&pattern);
-	} else
-		r->value.bool = FALSE;
-	
-	return r;
-}
-
-static gchar *
-get_full_header (CamelMimeMessage *message)
-{
-	CamelMimePart *mp = CAMEL_MIME_PART (message);
-	GString *str = g_string_new ("");
-	char   *ret;
-	struct _camel_header_raw *h;
-	
-	for (h = mp->headers; h; h = h->next) {
-		if (h->value != NULL) {
-			g_string_append (str, h->name);
-			if (isspace (h->value[0]))
-				g_string_append (str, ":");
-			else
-				g_string_append (str, ": ");
-			g_string_append (str, h->value);
-			g_string_append_c(str, '\n');
-		}
-	}
-	
-	ret = str->str;
-	g_string_free (str, FALSE);
-	
-	return ret;
-}
-
-static ESExpResult *
-header_full_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	ESExpResult *r = e_sexp_result_new (f, ESEXP_RES_BOOL);
-	CamelMimeMessage *message;
-	regex_t pattern;
-	char *contents;
-	
-	if (camel_search_build_match_regex(&pattern, CAMEL_SEARCH_MATCH_REGEX|CAMEL_SEARCH_MATCH_ICASE|CAMEL_SEARCH_MATCH_NEWLINE,
-					   argc, argv, fms->ex) == 0) {
-		message = camel_filter_search_get_message (fms, f);
-		contents = get_full_header (message);
-		r->value.bool = regexec (&pattern, contents, 0, NULL, 0) == 0;
-		g_free (contents);
-		regfree (&pattern);
-	} else
-		r->value.bool = FALSE;
-	
-	return r;
-}
-
-static ESExpResult *
-match_all (struct _ESExp *f, int argc, struct _ESExpTerm **argv, FilterMessageSearch *fms)
-{
-	/* match-all: when dealing with single messages is a no-op */
-	ESExpResult *r;
-	
-	if (argc > 0)
-		return e_sexp_term_eval (f, argv[0]);
-	
-	r = e_sexp_result_new (f, ESEXP_RES_BOOL);
-	r->value.bool = TRUE;
-	
-	return r;
-}
-
-static ESExpResult *
-body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	ESExpResult *r = e_sexp_result_new (f, ESEXP_RES_BOOL);
-	CamelMimeMessage *message;
-	regex_t pattern;
-	
-	if (camel_search_build_match_regex (&pattern, CAMEL_SEARCH_MATCH_ICASE, argc, argv, fms->ex) == 0) {
-		message = camel_filter_search_get_message (fms, f);
-		r->value.bool = camel_search_message_body_contains ((CamelDataWrapper *) message, &pattern);
-		regfree (&pattern);
-	} else
-		r->value.bool = FALSE;
-	
-	return r;
-}
-
-static ESExpResult *
-body_regex (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	ESExpResult *r = e_sexp_result_new(f, ESEXP_RES_BOOL);
-	CamelMimeMessage *message;
-	regex_t pattern;
-	
-	if (camel_search_build_match_regex(&pattern, CAMEL_SEARCH_MATCH_ICASE|CAMEL_SEARCH_MATCH_REGEX|CAMEL_SEARCH_MATCH_NEWLINE,
-					   argc, argv, fms->ex) == 0) {
-		message = camel_filter_search_get_message (fms, f);
-		r->value.bool = camel_search_message_body_contains ((CamelDataWrapper *) message, &pattern);
-		regfree (&pattern);
-	} else
-		r->value.bool = FALSE;
-	
-	return r;
-}
-
-static ESExpResult *
-user_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	ESExpResult *r;
-	gboolean truth = FALSE;
-	int i;
-	
-	/* performs an OR of all words */
-	for (i = 0; i < argc && !truth; i++) {
-		if (argv[i]->type == ESEXP_RES_STRING
-		    && camel_flag_get (&fms->info->user_flags, argv[i]->value.string)) {
-			truth = TRUE;
-			break;
-		}
-	}
-	
-	r = e_sexp_result_new (f, ESEXP_RES_BOOL);
-	r->value.bool = truth;
-	
-	return r;
-}
-
-static ESExpResult *
-system_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	ESExpResult *r;
-	
-	if (argc != 1 || argv[0]->type != ESEXP_RES_STRING)
-		e_sexp_fatal_error(f, _("Invalid arguments to (system-flag)"));
-	
-	r = e_sexp_result_new (f, ESEXP_RES_BOOL);
-	r->value.bool = camel_system_flag_get (fms->info->flags, argv[0]->value.string);
-	
-	return r;
-}
-
-static ESExpResult *
-user_tag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	ESExpResult *r;
-	const char *tag;
-
-	if (argc != 1 || argv[0]->type != ESEXP_RES_STRING)
-		e_sexp_fatal_error(f, _("Invalid arguments to (user-tag)"));
-	
-	tag = camel_tag_get (&fms->info->user_tags, argv[0]->value.string);
-	
-	r = e_sexp_result_new (f, ESEXP_RES_STRING);
-	r->value.string = g_strdup (tag ? tag : "");
-	
-	return r;
-}
-
-static ESExpResult *
-get_sent_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	CamelMimeMessage *message;
-	ESExpResult *r;
-	
-	message = camel_filter_search_get_message (fms, f);
-	r = e_sexp_result_new (f, ESEXP_RES_INT);
-	r->value.number = camel_mime_message_get_date (message, NULL);
-	
-	return r;
-}
-
-static ESExpResult *
-get_received_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	CamelMimeMessage *message;
-	ESExpResult *r;
-	
-	message = camel_filter_search_get_message (fms, f);
-	r = e_sexp_result_new (f, ESEXP_RES_INT);
-	r->value.number = camel_mime_message_get_date_received (message, NULL);
-	
-	return r;
-}
-
-static ESExpResult *
-get_current_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	ESExpResult *r;
-	
-	r = e_sexp_result_new (f, ESEXP_RES_INT);
-	r->value.number = time (NULL);
-	
-	return r;
-}
-
-static ESExpResult *
-header_source (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	CamelMimeMessage *message;
-	ESExpResult *r;
-	const char *src;
-	int truth = FALSE, i;
-	CamelProvider *provider;
-	CamelURL *uria, *urib;
-
-	if (fms->source) {
-		src = fms->source;
-	} else {
-		message = camel_filter_search_get_message(fms, f);
-		src = camel_mime_message_get_source(message);
-	}
-
-	if (src
-	    && (provider = camel_session_get_provider(fms->session, src, NULL))
-	    && provider->url_equal) {
-		uria = camel_url_new(src, NULL);
-		if (uria) {
-			for (i=0;itype == ESEXP_RES_STRING
-				    && (urib = camel_url_new(argv[i]->value.string, NULL))) {
-					truth = provider->url_equal(uria, urib);
-					camel_url_free(urib);
-				}
-			}
-			camel_url_free(uria);
-		}
-	}
-
-	r = e_sexp_result_new(f, ESEXP_RES_BOOL);
-	r->value.bool = truth;
-	
-	return r;
-}
-
-/* remember, the size comparisons are done at Kbytes */
-static ESExpResult *
-get_size (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	ESExpResult *r;
-	
-	r = e_sexp_result_new(f, ESEXP_RES_INT);
-	r->value.number = fms->info->size / 1024;
-
-	return r;
-}
-
-static int
-run_command (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	CamelMimeMessage *message;
-	CamelStream *stream;
-	int result, status;
-	int in_fds[2];
-	pid_t pid;
-	
-	if (argc < 1 || argv[0]->value.string[0] == '\0')
-		return 0;
-	
-	if (pipe (in_fds) == -1) {
-		camel_exception_setv (fms->ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Failed to create pipe to '%s': %s"),
-				      argv[0]->value.string, g_strerror (errno));
-		return -1;
-	}
-	
-	if (!(pid = fork ())) {
-		/* child process */
-		GPtrArray *args;
-		int maxfd, fd, i;
-		
-		fd = open ("/dev/null", O_WRONLY);
-		
-		if (dup2 (in_fds[0], STDIN_FILENO) < 0 ||
-		    dup2 (fd, STDOUT_FILENO) < 0 ||
-		    dup2 (fd, STDERR_FILENO) < 0)
-			_exit (255);
-		
-		setsid ();
-		
-		maxfd = sysconf (_SC_OPEN_MAX);
-		for (fd = 3; fd < maxfd; fd++)
-			fcntl (fd, F_SETFD, FD_CLOEXEC);
-		
-		args = g_ptr_array_new ();
-		for (i = 0; i < argc; i++)
-			g_ptr_array_add (args, argv[i]->value.string);
-		g_ptr_array_add (args, NULL);
-		
-		execvp (argv[0]->value.string, (char **) args->pdata);
-		
-		g_ptr_array_free (args, TRUE);
-		
-		d(printf ("Could not execute %s: %s\n", argv[0]->value.string, g_strerror (errno)));
-		_exit (255);
-	} else if (pid < 0) {
-		camel_exception_setv (fms->ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Failed to create create child process '%s': %s"),
-				      argv[0]->value.string, g_strerror (errno));
-		return -1;
-	}
-	
-	/* parent process */
-	close (in_fds[0]);
-	
-	message = camel_filter_search_get_message (fms, f);
-	
-	stream = camel_stream_fs_new_with_fd (in_fds[1]);
-	camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), stream);
-	camel_stream_flush (stream);
-	camel_object_unref (stream);
-	
-	result = waitpid (pid, &status, 0);
-	
-	if (result == -1 && errno == EINTR) {
-		/* child process is hanging... */
-		kill (pid, SIGTERM);
-		sleep (1);
-		result = waitpid (pid, &status, WNOHANG);
-		if (result == 0) {
-			/* ...still hanging, set phasers to KILL */
-			kill (pid, SIGKILL);
-			sleep (1);
-			result = waitpid (pid, &status, WNOHANG);
-		}
-	}
-	
-	if (result != -1 && WIFEXITED (status))
-		return WEXITSTATUS (status);
-	else
-		return -1;
-}
-
-static ESExpResult *
-pipe_message (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	ESExpResult *r;
-	int retval, i;
-	
-	/* make sure all args are strings */
-	for (i = 0; i < argc; i++) {
-		if (argv[i]->type != ESEXP_RES_STRING) {
-			retval = -1;
-			goto done;
-		}
-	}
-	
-	retval = run_command (f, argc, argv, fms);
-	
- done:
-	r = e_sexp_result_new (f, ESEXP_RES_INT);
-	r->value.number = retval;
-	
-	return r;
-}
-
-static ESExpResult *
-junk_test (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
-{
-	ESExpResult *r;
-	gboolean retval = FALSE;
-	
-	if (fms->session->junk_plugin != NULL) {
-		retval = camel_junk_plugin_check_junk (fms->session->junk_plugin, camel_filter_search_get_message (fms, f));
-	
-		fprintf (stderr, "junk filter => %s\n", retval ? "*JUNK*" : "clean");
-	}
-	r = e_sexp_result_new (f, ESEXP_RES_BOOL);
-	r->value.number = retval;
-
-	return r;
-}
-
-
-/**
- * camel_filter_search_match:
- * @session:
- * @get_message: function to retrieve the message if necessary
- * @data: data for above
- * @info:
- * @source:
- * @expression:
- * @ex:
- *
- * Returns one of CAMEL_SEARCH_MATCHED, CAMEL_SEARCH_NOMATCH, or CAMEL_SEARCH_ERROR.
- **/
-int
-camel_filter_search_match (CamelSession *session,
-			   CamelFilterSearchGetMessageFunc get_message, void *data,
-			   CamelMessageInfo *info, const char *source,
-			   const char *expression, CamelException *ex)
-{
-	FilterMessageSearch fms;
-	ESExp *sexp;
-	ESExpResult *result;
-	gboolean retval;
-	int i;
-
-	fms.session = session;
-	fms.get_message = get_message;
-	fms.get_message_data = data;
-	fms.message = NULL;
-	fms.info = info;
-	fms.source = source;
-	fms.ex = ex;
-	
-	sexp = e_sexp_new ();
-	
-	for (i = 0; i < sizeof (symbols) / sizeof (symbols[0]); i++) {
-		if (symbols[i].type == 1)
-			e_sexp_add_ifunction (sexp, 0, symbols[i].name, (ESExpIFunc *)symbols[i].func, &fms);
-		else
-			e_sexp_add_function (sexp, 0, symbols[i].name, symbols[i].func, &fms);
-	}
-	
-	e_sexp_input_text (sexp, expression, strlen (expression));
-	if (e_sexp_parse (sexp) == -1) {
-		if (!camel_exception_is_set (ex))
-			camel_exception_setv (ex, 1, _("Error executing filter search: %s: %s"),
-					      e_sexp_error (sexp), expression);
-		goto error;
-	}
-	
-	result = e_sexp_eval (sexp);
-	if (result == NULL) {
-		if (!camel_exception_is_set (ex))
-			camel_exception_setv (ex, 1, _("Error executing filter search: %s: %s"),
-					      e_sexp_error (sexp), expression);
-		goto error;
-	}
-	
-	if (result->type == ESEXP_RES_BOOL)
-		retval = result->value.bool ? CAMEL_SEARCH_MATCHED : CAMEL_SEARCH_NOMATCH;
-	else
-		retval = CAMEL_SEARCH_NOMATCH;
-	
-	e_sexp_result_free (sexp, result);
-	e_sexp_unref (sexp);
-	
-	if (fms.message)
-		camel_object_unref (fms.message);
-	
-	return retval;
-	
- error:
-	if (fms.message)
-		camel_object_unref (fms.message);
-	
-	e_sexp_unref (sexp);
-	
-	return CAMEL_SEARCH_ERROR;
-}
diff --git a/camel/camel-filter-search.h b/camel/camel-filter-search.h
deleted file mode 100644
index 51b988362f..0000000000
--- a/camel/camel-filter-search.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *	     Michael Zucchi 
- *
- *  Copyright 2000 Ximian, Inc. (www.ximian.com)
- *  Copyright 2001 Ximian Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef CAMEL_FILTER_SEARCH_H
-#define CAMEL_FILTER_SEARCH_H
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include 
-#include 
-#include 
-
-enum {
-	CAMEL_SEARCH_ERROR    = -1,
-	CAMEL_SEARCH_NOMATCH  =  0,
-	CAMEL_SEARCH_MATCHED  =  1,
-};
-
-typedef CamelMimeMessage * (*CamelFilterSearchGetMessageFunc) (void *data, CamelException *ex);
-
-int camel_filter_search_match (CamelSession *session,
-			       CamelFilterSearchGetMessageFunc get_message, void *data,
-			       CamelMessageInfo *info, const char *source,
-			       const char *expression, CamelException *ex);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* ! CAMEL_FILTER_SEARCH_H */
diff --git a/camel/camel-folder-search.c b/camel/camel-folder-search.c
deleted file mode 100644
index 8262ee3c3a..0000000000
--- a/camel/camel-folder-search.c
+++ /dev/null
@@ -1,1174 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Copyright (C) 2000-2003 Ximian Inc.
- *
- *  Authors: Michael Zucchi 
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/* This is a helper class for folders to implement the search function.
-   It implements enough to do basic searches on folders that can provide
-   an in-memory summary and a body index. */
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-
-#include "camel-folder-search.h"
-
-#include "camel-exception.h"
-#include "camel-medium.h"
-#include "camel-multipart.h"
-#include "camel-mime-message.h"
-#include "camel-stream-mem.h"
-#include "e-util/e-memory.h"
-#include "camel-search-private.h"
-
-#define d(x) 
-#define r(x) 
-
-struct _CamelFolderSearchPrivate {
-	GHashTable *mempool_hash;
-	CamelException *ex;
-};
-
-#define _PRIVATE(o) (((CamelFolderSearch *)(o))->priv)
-
-static ESExpResult *search_not(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search);
-
-static ESExpResult *search_header_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search);
-static ESExpResult *search_header_matches(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search);
-static ESExpResult *search_header_starts_with(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search);
-static ESExpResult *search_header_ends_with(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search);
-static ESExpResult *search_header_exists(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search);
-static ESExpResult *search_match_all(struct _ESExp *f, int argc, struct _ESExpTerm **argv, CamelFolderSearch *search);
-static ESExpResult *search_body_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search);
-static ESExpResult *search_user_flag(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-static ESExpResult *search_user_tag(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-static ESExpResult *search_system_flag(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-static ESExpResult *search_get_sent_date(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-static ESExpResult *search_get_received_date(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-static ESExpResult *search_get_current_date(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-static ESExpResult *search_get_size(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-static ESExpResult *search_uid(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
-static ESExpResult *search_dummy(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search);
-
-static void camel_folder_search_class_init (CamelFolderSearchClass *klass);
-static void camel_folder_search_init       (CamelFolderSearch *obj);
-static void camel_folder_search_finalize   (CamelObject *obj);
-
-static CamelObjectClass *camel_folder_search_parent;
-
-static void
-camel_folder_search_class_init (CamelFolderSearchClass *klass)
-{
-	camel_folder_search_parent = camel_type_get_global_classfuncs (camel_object_get_type ());
-
-	klass->not = search_not;
-
-	klass->match_all = search_match_all;
-	klass->body_contains = search_body_contains;
-	klass->header_contains = search_header_contains;
-	klass->header_matches = search_header_matches;
-	klass->header_starts_with = search_header_starts_with;
-	klass->header_ends_with = search_header_ends_with;
-	klass->header_exists = search_header_exists;
-	klass->user_tag = search_user_tag;
-	klass->user_flag = search_user_flag;
-	klass->system_flag = search_system_flag;
-	klass->get_sent_date = search_get_sent_date;
-	klass->get_received_date = search_get_received_date;
-	klass->get_current_date = search_get_current_date;
-	klass->get_size = search_get_size;
-	klass->uid = search_uid;
-}
-
-static void
-camel_folder_search_init (CamelFolderSearch *obj)
-{
-	struct _CamelFolderSearchPrivate *p;
-
-	p = _PRIVATE(obj) = g_malloc0(sizeof(*p));
-
-	obj->sexp = e_sexp_new();
-
-	/* use a hash of mempools to associate the returned uid lists with
-	   the backing mempool.  yes pretty weird, but i didn't want to change
-	   the api just yet */
-
-	p->mempool_hash = g_hash_table_new(0, 0);
-}
-
-static void
-free_mempool(void *key, void *value, void *data)
-{
-	GPtrArray *uids = key;
-	EMemPool *pool = value;
-
-	g_warning("Search closed with outstanding result unfreed: %p", uids);
-
-	g_ptr_array_free(uids, TRUE);
-	e_mempool_destroy(pool);
-}
-
-static void
-camel_folder_search_finalize (CamelObject *obj)
-{
-	CamelFolderSearch *search = (CamelFolderSearch *)obj;
-	struct _CamelFolderSearchPrivate *p = _PRIVATE(obj);
-
-	if (search->sexp)
-		e_sexp_unref(search->sexp);
-	if (search->summary_hash)
-		g_hash_table_destroy(search->summary_hash);
-
-	g_free(search->last_search);
-	g_hash_table_foreach(p->mempool_hash, free_mempool, obj);
-	g_hash_table_destroy(p->mempool_hash);
-	g_free(p);
-}
-
-CamelType
-camel_folder_search_get_type (void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-	
-	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register (camel_object_get_type (), "CamelFolderSearch",
-					    sizeof (CamelFolderSearch),
-					    sizeof (CamelFolderSearchClass),
-					    (CamelObjectClassInitFunc) camel_folder_search_class_init,
-					    NULL,
-					    (CamelObjectInitFunc) camel_folder_search_init,
-					    (CamelObjectFinalizeFunc) camel_folder_search_finalize);
-	}
-	
-	return type;
-}
-
-#ifdef offsetof
-#define CAMEL_STRUCT_OFFSET(type, field)        ((gint) offsetof (type, field))
-#else
-#define CAMEL_STRUCT_OFFSET(type, field)        ((gint) ((gchar*) &((type *) 0)->field))
-#endif
-
-struct {
-	char *name;
-	int offset;
-	int flags;		/* 0x02 = immediate, 0x01 = always enter */
-} builtins[] = {
-	/* these have default implementations in e-sexp */
-	{ "and", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, and), 2 },
-	{ "or", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, or), 2 },
-	/* we need to override this one though to implement an 'array not' */
-	{ "not", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, not), 0 },
-	{ "<", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, lt), 2 },
-	{ ">", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, gt), 2 },
-	{ "=", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, eq), 2 },
-
-	/* these we have to use our own default if there is none */
-	/* they should all be defined in the language? so it parses, or should they not?? */
-	{ "match-all", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, match_all), 3 },
-	{ "body-contains", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, body_contains), 1 },
-	{ "header-contains", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, header_contains), 1 },
-	{ "header-matches", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, header_matches), 1 },
-	{ "header-starts-with", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, header_starts_with), 1 },
-	{ "header-ends-with", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, header_ends_with), 1 },
-	{ "header-exists", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, header_exists), 1 },
-	{ "user-tag", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, user_tag), 1 },
-	{ "user-flag", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, user_flag), 1 },
-	{ "system-flag", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, system_flag), 1 },
-	{ "get-sent-date", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, get_sent_date), 1 },
-	{ "get-received-date", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, get_received_date), 1 },
-	{ "get-current-date", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, get_current_date), 1 },
-	{ "get-size", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, get_size), 1 },
-	{ "uid", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, uid), 1 },
-};
-
-void
-camel_folder_search_construct (CamelFolderSearch *search)
-{
-	int i;
-	CamelFolderSearchClass *klass = (CamelFolderSearchClass *)CAMEL_OBJECT_GET_CLASS(search);
-
-	for (i=0;isexp, 0, builtins[i].name, (ESExpIFunc *)func, search);
-			} else {
-				e_sexp_add_function(search->sexp, 0, builtins[i].name, (ESExpFunc *)func, search);
-			}
-		}
-	}
-}
-
-/**
- * camel_folder_search_new:
- *
- * Create a new CamelFolderSearch object.
- * 
- * A CamelFolderSearch is a subclassable, extensible s-exp
- * evaluator which enforces a particular set of s-expressions.
- * Particular methods may be overriden by an implementation to
- * implement a search for any sort of backend.
- *
- * Return value: A new CamelFolderSearch widget.
- **/
-CamelFolderSearch *
-camel_folder_search_new (void)
-{
-	CamelFolderSearch *new = CAMEL_FOLDER_SEARCH (camel_object_new (camel_folder_search_get_type ()));
-
-	camel_folder_search_construct(new);
-	return new;
-}
-
-/**
- * camel_folder_search_set_folder:
- * @search:
- * @folder: A folder.
- * 
- * Set the folder attribute of the search.  This is currently unused, but
- * could be used to perform a slow-search when indexes and so forth are not
- * available.  Or for use by subclasses.
- **/
-void
-camel_folder_search_set_folder(CamelFolderSearch *search, CamelFolder *folder)
-{
-	search->folder = folder;
-}
-
-/**
- * camel_folder_search_set_summary:
- * @search: 
- * @summary: An array of CamelMessageInfo pointers.
- * 
- * Set the array of summary objects representing the span of the search.
- *
- * If this is not set, then a subclass must provide the functions
- * for searching headers and for the match-all operator.
- **/
-void
-camel_folder_search_set_summary(CamelFolderSearch *search, GPtrArray *summary)
-{
-	int i;
-
-	search->summary = summary;
-	if (search->summary_hash)
-		g_hash_table_destroy(search->summary_hash);
-	search->summary_hash = g_hash_table_new(g_str_hash, g_str_equal);
-	for (i=0;ilen;i++)
-		g_hash_table_insert(search->summary_hash, (char *)camel_message_info_uid(summary->pdata[i]), summary->pdata[i]);
-}
-
-/**
- * camel_folder_search_set_body_index:
- * @search: 
- * @index: 
- * 
- * Set the index representing the contents of all messages
- * in this folder.  If this is not set, then the folder implementation
- * should sub-class the CamelFolderSearch and provide its own
- * body-contains function.
- **/
-void
-camel_folder_search_set_body_index(CamelFolderSearch *search, CamelIndex *index)
-{
-	if (search->body_index)
-		camel_object_unref((CamelObject *)search->body_index);
-	search->body_index = index;
-	if (index)
-		camel_object_ref((CamelObject *)index);
-}
-
-/**
- * camel_folder_search_execute_expression:
- * @search: 
- * @expr: 
- * @ex: 
- * 
- * Execute the search expression @expr, returning an array of
- * all matches as a GPtrArray of uid's of matching messages.
- *
- * Note that any settings such as set_body_index(), set_folder(),
- * and so on are reset to #NULL once the search has completed.
- *
- * TODO: The interface should probably return summary items instead
- * (since they are much more useful to any client).
- * 
- * Return value: A GPtrArray of strings of all matching messages.
- * This must only be freed by camel_folder_search_free_result.
- **/
-GPtrArray *
-camel_folder_search_execute_expression(CamelFolderSearch *search, const char *expr, CamelException *ex)
-{
-	ESExpResult *r;
-	GPtrArray *matches;
-	int i;
-	GHashTable *results;
-	EMemPool *pool;
-	struct _CamelFolderSearchPrivate *p = _PRIVATE(search);
-
-	p->ex = ex;
-
-	/* only re-parse if the search has changed */
-	if (search->last_search == NULL
-	    || strcmp(search->last_search, expr)) {
-		e_sexp_input_text(search->sexp, expr, strlen(expr));
-		if (e_sexp_parse(search->sexp) == -1) {
-			camel_exception_setv(ex, 1, _("Cannot parse search expression: %s:\n%s"), e_sexp_error(search->sexp), expr);
-			return NULL;
-		}
-
-		g_free(search->last_search);
-		search->last_search = g_strdup(expr);
-	}
-	r = e_sexp_eval(search->sexp);
-	if (r == NULL) {
-		if (!camel_exception_is_set(ex))
-			camel_exception_setv(ex, 1, _("Error executing search expression: %s:\n%s"), e_sexp_error(search->sexp), expr);
-		return NULL;
-	}
-
-	matches = g_ptr_array_new();
-
-	/* now create a folder summary to return?? */
-	if (r->type == ESEXP_RES_ARRAY_PTR) {
-		d(printf("got result ...\n"));
-		/* we use a mempool to store the strings, packed in tight as possible, and freed together */
-		/* because the strings are often short (like <8 bytes long), we would be wasting appx 50%
-		   of memory just storing the size tag that malloc assigns us and alignment padding, so this
-		   gets around that (and is faster to allocate and free as a bonus) */
-		pool = e_mempool_new(512, 256, E_MEMPOOL_ALIGN_BYTE);
-		if (search->summary) {
-			/* reorder result in summary order */
-			results = g_hash_table_new(g_str_hash, g_str_equal);
-			for (i=0;ivalue.ptrarray->len;i++) {
-				d(printf("adding match: %s\n", (char *)g_ptr_array_index(r->value.ptrarray, i)));
-				g_hash_table_insert(results, g_ptr_array_index(r->value.ptrarray, i), (void *)1);
-			}
-			for (i=0;isummary->len;i++) {
-				CamelMessageInfo *info = g_ptr_array_index(search->summary, i);
-				char *uid = (char *)camel_message_info_uid(info);
-				if (g_hash_table_lookup(results, uid)) {
-					g_ptr_array_add(matches, e_mempool_strdup(pool, uid));
-				}
-			}
-			g_hash_table_destroy(results);
-		} else {
-			for (i=0;ivalue.ptrarray->len;i++) {
-				d(printf("adding match: %s\n", (char *)g_ptr_array_index(r->value.ptrarray, i)));
-				g_ptr_array_add(matches, e_mempool_strdup(pool, g_ptr_array_index(r->value.ptrarray, i)));
-			}
-		}
-		/* instead of putting the mempool_hash in the structure, we keep the api clean by
-		   putting a reference to it in a hashtable.  Lets us do some debugging and catch
-		   unfree'd results as well. */
-		g_hash_table_insert(p->mempool_hash, matches, pool);
-	} else {
-		g_warning("Search returned an invalid result type");
-	}
-
-	e_sexp_result_free(search->sexp, r);
-
-	search->folder = NULL;
-	search->summary = NULL;
-	search->current = NULL;
-	search->body_index = NULL;
-
-	return matches;
-}
-
-/**
- * camel_folder_search_match_expression:
- * @search: 
- * @expr: 
- * @info: 
- * @ex: 
- * 
- * Returns #TRUE if the expression matches the specific message info @info.
- * Note that the folder and index may need to be set for body searches to
- * operate as well.
- * 
- * Return value: 
- **/
-gboolean
-camel_folder_search_match_expression(CamelFolderSearch *search, const char *expr, const CamelMessageInfo *info, CamelException *ex)
-{
-	GPtrArray *uids;
-	int ret = FALSE;
-
-	search->current = (CamelMessageInfo *)info;
-
-	uids = camel_folder_search_execute_expression(search, expr, ex);
-	if (uids) {
-		if (uids->len == 1)
-			ret = TRUE;
-		camel_folder_search_free_result(search, uids);
-	}
-	search->current = NULL;
-
-	return ret;
-}
-
-void camel_folder_search_free_result(CamelFolderSearch *search, GPtrArray *result)
-{
-	int i;
-	struct _CamelFolderSearchPrivate *p = _PRIVATE(search);
-	EMemPool *pool;
-
-	pool = g_hash_table_lookup(p->mempool_hash, result);
-	if (pool) {
-		e_mempool_destroy(pool);
-		g_hash_table_remove(p->mempool_hash, result);
-	} else {
-		for (i=0;ilen;i++)
-			g_free(g_ptr_array_index(result, i));
-	}
-	g_ptr_array_free(result, TRUE);
-}
-
-
-
-
-/* dummy function, returns false always, or an empty match array */
-static ESExpResult *
-search_dummy(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
-{
-	ESExpResult *r;
-
-	if (search->current == NULL) {
-		r = e_sexp_result_new(f, ESEXP_RES_BOOL);
-		r->value.bool = FALSE;
-	} else {
-		r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
-		r->value.ptrarray = g_ptr_array_new();
-	}
-
-	return r;
-}
-
-/* impelemnt an 'array not', i.e. everything in the summary, not in the supplied array */
-static ESExpResult *
-search_not(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
-{
-	ESExpResult *r;
-	int i;
-
-	if (argc>0) {
-		if (argv[0]->type == ESEXP_RES_ARRAY_PTR) {
-			GPtrArray *v = argv[0]->value.ptrarray;
-			const char *uid;
-
-			r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
-			r->value.ptrarray = g_ptr_array_new();
-
-			/* not against a single message?*/
-			if (search->current) {
-				int found = FALSE;
-
-				uid = camel_message_info_uid(search->current);
-				for (i=0;!found && ilen;i++) {
-					if (strcmp(uid, v->pdata[i]) == 0)
-						found = TRUE;
-				}
-
-				if (!found)
-					g_ptr_array_add(r->value.ptrarray, (char *)uid);
-			} else if (search->summary == NULL) {
-				g_warning("No summary set, 'not' against an array requires a summary");
-			} else {
-				/* 'not' against the whole summary */
-				GHashTable *have = g_hash_table_new(g_str_hash, g_str_equal);
-				char **s;
-				CamelMessageInfo **m;
-
-				s = (char **)v->pdata;
-				for (i=0;ilen;i++)
-					g_hash_table_insert(have, s[i], s[i]);
-
-				v = search->summary;
-				m = (CamelMessageInfo **)v->pdata;
-				for (i=0;ilen;i++) {
-					char *uid = (char *)camel_message_info_uid(m[i]);
-
-					if (g_hash_table_lookup(have, uid) == NULL)
-						g_ptr_array_add(r->value.ptrarray, uid);
-				}
-				g_hash_table_destroy(have);
-			}
-		} else {
-			int res = TRUE;
-
-			if (argv[0]->type == ESEXP_RES_BOOL)
-				res = ! argv[0]->value.bool;
-
-			r = e_sexp_result_new(f, ESEXP_RES_BOOL);
-			r->value.bool = res;
-		}
-	} else {
-		r = e_sexp_result_new(f, ESEXP_RES_BOOL);
-		r->value.bool = TRUE;
-	}
-
-	return r;
-}
-
-static ESExpResult *
-search_match_all(struct _ESExp *f, int argc, struct _ESExpTerm **argv, CamelFolderSearch *search)
-{
-	int i;
-	ESExpResult *r, *r1;
-
-	if (argc>1) {
-		g_warning("match-all only takes a single argument, other arguments ignored");
-	}
-
-	/* we are only matching a single message?  or already inside a match-all? */
-	if (search->current) {
-		d(printf("matching against 1 message: %s\n", camel_message_info_subject(search->current)));
-
-		r = e_sexp_result_new(f, ESEXP_RES_BOOL);
-		r->value.bool = FALSE;
-
-		if (argc>0) {
-			r1 = e_sexp_term_eval(f, argv[0]);
-			if (r1->type == ESEXP_RES_BOOL) {
-				r->value.bool = r1->value.bool;
-			} else {
-				g_warning("invalid syntax, matches require a single bool result");
-				e_sexp_fatal_error(f, _("(match-all) requires a single bool result"));
-			}
-			e_sexp_result_free(f, r1);
-		} else {
-			r->value.bool = TRUE;
-		}
-		return r;
-	}
-
-	r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
-	r->value.ptrarray = g_ptr_array_new();
-
-	if (search->summary == NULL) {
-		/* TODO: make it work - e.g. use the folder and so forth for a slower search */
-		g_warning("No summary supplied, match-all doesn't work with no summary");
-		g_assert(0);
-		return r;
-	}
-
-	/* TODO: Could make this a bit faster in the uncommon case (of match-everything) */
-	for (i=0;isummary->len;i++) {
-		search->current = g_ptr_array_index(search->summary, i);
-		if (argc>0) {
-			r1 = e_sexp_term_eval(f, argv[0]);
-			if (r1->type == ESEXP_RES_BOOL) {
-				if (r1->value.bool)
-					g_ptr_array_add(r->value.ptrarray, (char *)camel_message_info_uid(search->current));
-			} else {
-				g_warning("invalid syntax, matches require a single bool result");
-				e_sexp_fatal_error(f, _("(match-all) requires a single bool result"));
-			}
-			e_sexp_result_free(f, r1);
-		} else {
-			g_ptr_array_add(r->value.ptrarray, (char *)camel_message_info_uid(search->current));
-		}
-	}
-	search->current = NULL;
-
-	return r;
-}
-
-static ESExpResult *
-check_header(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search, camel_search_match_t how)
-{
-	ESExpResult *r;
-	int truth = FALSE;
-
-	r(printf("executing check-header %d\n", how));
-
-	/* are we inside a match-all? */
-	if (search->current && argc>1
-	    && argv[0]->type == ESEXP_RES_STRING) {
-		char *headername;
-		const char *header = NULL;
-		char strbuf[32];
-		int i, j;
-		camel_search_t type = CAMEL_SEARCH_TYPE_ASIS;
-		struct _camel_search_words *words;
-
-		/* only a subset of headers are supported .. */
-		headername = argv[0]->value.string;
-		if (!strcasecmp(headername, "subject")) {
-			header = camel_message_info_subject(search->current);
-		} else if (!strcasecmp(headername, "date")) {
-			/* FIXME: not a very useful form of the date */
-			sprintf(strbuf, "%d", (int)search->current->date_sent);
-			header = strbuf;
-		} else if (!strcasecmp(headername, "from")) {
-			header = camel_message_info_from(search->current);
-			type = CAMEL_SEARCH_TYPE_ADDRESS;
-		} else if (!strcasecmp(headername, "to")) {
-			header = camel_message_info_to(search->current);
-			type = CAMEL_SEARCH_TYPE_ADDRESS;
-		} else if (!strcasecmp(headername, "cc")) {
-			header = camel_message_info_cc(search->current);
-			type = CAMEL_SEARCH_TYPE_ADDRESS;
-		} else if (!strcasecmp(headername, "x-camel-mlist")) {
-			header = camel_message_info_mlist(search->current);
-			type = CAMEL_SEARCH_TYPE_MLIST;
-		} else {
-			e_sexp_resultv_free(f, argc, argv);
-			e_sexp_fatal_error(f, _("Performing query on unknown header: %s"), headername);
-		}
-
-		if (header) {
-			/* performs an OR of all words */
-			for (i=1;itype == ESEXP_RES_STRING) {
-					if (argv[i]->value.string[0] == 0) {
-						truth = TRUE;
-					} else if (how == CAMEL_SEARCH_MATCH_CONTAINS) {
-						/* doesn't make sense to split words on anything but contains i.e. we can't have an ending match different words */
-						words = camel_search_words_split(argv[i]->value.string);
-						truth = TRUE;
-						for (j=0;jlen && truth;j++) {
-							truth = camel_search_header_match(header, words->words[j]->word, how, type, NULL);
-						}
-						camel_search_words_free(words);
-					} else {
-						truth = camel_search_header_match(header, argv[i]->value.string, how, type, NULL);
-					}
-				}
-			}
-		}
-	}
-	/* TODO: else, find all matches */
-
-	r = e_sexp_result_new(f, ESEXP_RES_BOOL);
-	r->value.bool = truth;
-
-	return r;
-}
-
-static ESExpResult *
-search_header_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
-{
-	return check_header(f, argc, argv, search, CAMEL_SEARCH_MATCH_CONTAINS);
-}
-
-static ESExpResult *
-search_header_matches(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
-{
-	return check_header(f, argc, argv, search, CAMEL_SEARCH_MATCH_EXACT);
-}
-
-static ESExpResult *
-search_header_starts_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
-{
-	return check_header(f, argc, argv, search, CAMEL_SEARCH_MATCH_STARTS);
-}
-
-static ESExpResult *
-search_header_ends_with (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
-{
-	return check_header(f, argc, argv, search, CAMEL_SEARCH_MATCH_ENDS);
-}
-
-static ESExpResult *
-search_header_exists (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
-{
-	ESExpResult *r;
-	
-	r(printf ("executing header-exists\n"));
-	
-	if (search->current) {
-		r = e_sexp_result_new(f, ESEXP_RES_BOOL);
-		if (argc == 1 && argv[0]->type == ESEXP_RES_STRING)
-			r->value.bool = camel_medium_get_header(CAMEL_MEDIUM(search->current), argv[0]->value.string) != NULL;
-		
-	} else {
-		r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
-		r->value.ptrarray = g_ptr_array_new();
-	}
-	
-	return r;
-}
-
-/* this is just to OR results together */
-struct _glib_sux_donkeys {
-	int count;
-	GPtrArray *uids;
-};
-
-/* or, store all unique values */
-static void
-g_lib_sux_htor(char *key, int value, struct _glib_sux_donkeys *fuckup)
-{
-	g_ptr_array_add(fuckup->uids, key);
-}
-
-/* and, only store duplicates */
-static void
-g_lib_sux_htand(char *key, int value, struct _glib_sux_donkeys *fuckup)
-{
-	if (value == fuckup->count)
-		g_ptr_array_add(fuckup->uids, key);
-}
-
-static int
-match_message_index(CamelIndex *idx, const char *uid, const char *match, CamelException *ex)
-{
-	CamelIndexCursor *wc, *nc;
-	const char *word, *name;
-	int truth = FALSE;
-
-	wc = camel_index_words(idx);
-	if (wc) {
-		while (!truth && (word = camel_index_cursor_next(wc))) {
-			if (camel_ustrstrcase(word,match) != NULL) {
-				/* perf: could have the wc cursor return the name cursor */
-				nc = camel_index_find(idx, word);
-				if (nc) {
-					while (!truth && (name = camel_index_cursor_next(nc)))
-						truth = strcmp(name, uid) == 0;
-					camel_object_unref((CamelObject *)nc);
-				}
-			}
-		}
-		camel_object_unref((CamelObject *)wc);
-	}
-
-	return truth;
-}
-
-/*
- "one two" "three" "four five"
-
-  one and two
-or
-  three
-or
-  four and five
-*/
-
-/* returns messages which contain all words listed in words */
-static GPtrArray *
-match_words_index(CamelFolderSearch *search, struct _camel_search_words *words, CamelException *ex)
-{
-	GPtrArray *result = g_ptr_array_new();
-	GHashTable *ht = g_hash_table_new(g_str_hash, g_str_equal);
-	struct _glib_sux_donkeys lambdafoo;
-	CamelIndexCursor *wc, *nc;
-	const char *word, *name;
-	CamelMessageInfo *mi;
-	int i;
-
-	/* we can have a maximum of 32 words, as we use it as the AND mask */
-			
-	wc = camel_index_words(search->body_index);
-	if (wc) {
-		while ((word = camel_index_cursor_next(wc))) {
-			for (i=0;ilen;i++) {
-				if (camel_ustrstrcase(word, words->words[i]->word) != NULL) {
-					/* perf: could have the wc cursor return the name cursor */
-					nc = camel_index_find(search->body_index, word);
-					if (nc) {
-						while ((name = camel_index_cursor_next(nc))) {
-							mi = g_hash_table_lookup(search->summary_hash, name);
-							if (mi) {
-								int mask;
-								const char *uid = camel_message_info_uid(mi);
-
-								mask = (GPOINTER_TO_INT(g_hash_table_lookup(ht, uid))) | (1<len) - 1;
-		g_hash_table_foreach(ht, (GHFunc)g_lib_sux_htand, &lambdafoo);
-		g_hash_table_destroy(ht);
-	}
-
-	return result;
-}
-
-static gboolean
-match_words_1message (CamelDataWrapper *object, struct _camel_search_words *words, guint32 *mask)
-{
-	CamelDataWrapper *containee;
-	int truth = FALSE;
-	int parts, i;
-	
-	containee = camel_medium_get_content_object (CAMEL_MEDIUM (object));
-	
-	if (containee == NULL)
-		return FALSE;
-	
-	/* using the object types is more accurate than using the mime/types */
-	if (CAMEL_IS_MULTIPART (containee)) {
-		parts = camel_multipart_get_number (CAMEL_MULTIPART (containee));
-		for (i = 0; i < parts && truth == FALSE; i++) {
-			CamelDataWrapper *part = (CamelDataWrapper *)camel_multipart_get_part (CAMEL_MULTIPART (containee), i);
-			if (part)
-				truth = match_words_1message(part, words, mask);
-		}
-	} else if (CAMEL_IS_MIME_MESSAGE (containee)) {
-		/* for messages we only look at its contents */
-		truth = match_words_1message((CamelDataWrapper *)containee, words, mask);
-	} else if (camel_content_type_is(CAMEL_DATA_WRAPPER (containee)->mime_type, "text", "*")) {
-		/* for all other text parts, we look inside, otherwise we dont care */
-		CamelStreamMem *mem = (CamelStreamMem *)camel_stream_mem_new ();
-
-		/* FIXME: The match should be part of a stream op */
-		camel_data_wrapper_decode_to_stream (containee, CAMEL_STREAM (mem));
-		camel_stream_write (CAMEL_STREAM (mem), "", 1);
-		for (i=0;ilen;i++) {
-			/* FIXME: This is horridly slow, and should use a real search algorithm */
-			if (camel_ustrstrcase(mem->buffer->data, words->words[i]->word) != NULL) {
-				*mask |= (1<len))-1)
-					return TRUE;
-			}
-		}
-		
-		camel_object_unref (mem);
-	}
-	
-	return truth;
-}
-
-static gboolean
-match_words_message(CamelFolder *folder, const char *uid, struct _camel_search_words *words, CamelException *ex)
-{
-	guint32 mask;
-	CamelMimeMessage *msg;
-	int truth;
-
-	msg = camel_folder_get_message(folder, uid, ex);
-	if (msg) {
-		mask = 0;
-		truth = match_words_1message((CamelDataWrapper *)msg, words, &mask);
-		camel_object_unref((CamelObject *)msg);
-	} else {
-		camel_exception_clear(ex);
-		truth = FALSE;
-	}
-
-	return truth;
-}
-
-static GPtrArray *
-match_words_messages(CamelFolderSearch *search, struct _camel_search_words *words, CamelException *ex)
-{
-	int i;
-	GPtrArray *matches = g_ptr_array_new();
-
-	if (search->body_index) {
-		GPtrArray *indexed;
-		struct _camel_search_words *simple;
-
-		simple = camel_search_words_simple(words);
-		indexed = match_words_index(search, simple, ex);
-		camel_search_words_free(simple);
-
-		for (i=0;ilen;i++) {
-			const char *uid = g_ptr_array_index(indexed, i);
-			
-			if (match_words_message(search->folder, uid, words, ex))
-				g_ptr_array_add(matches, (char *)uid);
-		}
-		
-		g_ptr_array_free(indexed, TRUE);
-	} else {
-		for (i=0;isummary->len;i++) {
-			CamelMessageInfo *info = g_ptr_array_index(search->summary, i);
-			const char *uid = camel_message_info_uid(info);
-			
-			if (match_words_message(search->folder, uid, words, ex))
-				g_ptr_array_add(matches, (char *)uid);
-		}
-	}
-
-	return matches;
-}
-
-static ESExpResult *
-search_body_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
-{
-	int i, j;
-	CamelException *ex = search->priv->ex;
-	struct _camel_search_words *words;
-	ESExpResult *r;
-	struct _glib_sux_donkeys lambdafoo;
-
-	if (search->current) {	
-		int truth = FALSE;
-
-		if (argc == 1 && argv[0]->value.string[0] == 0) {
-			truth = TRUE;
-		} else {
-			for (i=0;itype == ESEXP_RES_STRING) {
-					words = camel_search_words_split(argv[i]->value.string);
-					truth = TRUE;
-					if ((words->type & CAMEL_SEARCH_WORD_COMPLEX) == 0 && search->body_index) {
-						for (j=0;jlen && truth;j++)
-							truth = match_message_index(search->body_index, camel_message_info_uid(search->current), words->words[j]->word, ex);
-					} else {
-						/* TODO: cache current message incase of multiple body search terms */
-						truth = match_words_message(search->folder, camel_message_info_uid(search->current), words, ex);
-					}
-					camel_search_words_free(words);
-				}
-			}
-		}
-		r = e_sexp_result_new(f, ESEXP_RES_BOOL);
-		r->value.bool = truth;
-	} else {
-		r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
-		r->value.ptrarray = g_ptr_array_new();
-
-		if (argc == 1 && argv[0]->value.string[0] == 0) {
-			for (i=0;isummary->len;i++) {
-				CamelMessageInfo *info = g_ptr_array_index(search->summary, i);
-
-				g_ptr_array_add(r->value.ptrarray, (char *)camel_message_info_uid(info));
-			}
-		} else {
-			GHashTable *ht = g_hash_table_new(g_str_hash, g_str_equal);
-			GPtrArray *matches;
-
-			for (i=0;itype == ESEXP_RES_STRING) {
-					words = camel_search_words_split(argv[i]->value.string);
-					if ((words->type & CAMEL_SEARCH_WORD_COMPLEX) == 0 && search->body_index) {
-						matches = match_words_index(search, words, ex);
-					} else {
-						matches = match_words_messages(search, words, ex);
-					}
-					for (j=0;jlen;j++)
-						g_hash_table_insert(ht, matches->pdata[j], matches->pdata[j]);
-					g_ptr_array_free(matches, TRUE);
-					camel_search_words_free(words);
-				}
-			}
-			lambdafoo.uids = r->value.ptrarray;
-			g_hash_table_foreach(ht, (GHFunc)g_lib_sux_htor, &lambdafoo);
-			g_hash_table_destroy(ht);
-		}
-	}
-
-	return r;
-}
-
-static ESExpResult *
-search_user_flag(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
-{
-	ESExpResult *r;
-	int i;
-
-	r(printf("executing user-flag\n"));
-
-	/* are we inside a match-all? */
-	if (search->current) {
-		int truth = FALSE;
-		/* performs an OR of all words */
-		for (i=0;itype == ESEXP_RES_STRING
-			    && camel_flag_get(&search->current->user_flags, argv[i]->value.string)) {
-				truth = TRUE;
-				break;
-			}
-		}
-		r = e_sexp_result_new(f, ESEXP_RES_BOOL);
-		r->value.bool = truth;
-	} else {
-		r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
-		r->value.ptrarray = g_ptr_array_new();
-	}
-
-	return r;
-}
-
-static ESExpResult *
-search_system_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
-{
-	ESExpResult *r;
-	
-	r(printf ("executing system-flag\n"));
-	
-	if (search->current) {
-		gboolean truth = FALSE;
-		
-		if (argc == 1)
-			truth = camel_system_flag_get (search->current->flags, argv[0]->value.string);
-		
-		r = e_sexp_result_new(f, ESEXP_RES_BOOL);
-		r->value.bool = truth;
-	} else {
-		r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
-		r->value.ptrarray = g_ptr_array_new ();
-	}
-	
-	return r;
-}
-
-static ESExpResult *
-search_user_tag(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
-{
-	const char *value = NULL;
-	ESExpResult *r;
-	
-	r(printf("executing user-tag\n"));
-	
-	if (argc == 1)
-		value = camel_tag_get (&search->current->user_tags, argv[0]->value.string);
-	
-	r = e_sexp_result_new(f, ESEXP_RES_STRING);
-	r->value.string = g_strdup (value ? value : "");
-	
-	return r;
-}
-
-static ESExpResult *
-search_get_sent_date(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s)
-{
-	ESExpResult *r;
-
-	r(printf("executing get-sent-date\n"));
-
-	/* are we inside a match-all? */
-	if (s->current) {
-		r = e_sexp_result_new(f, ESEXP_RES_INT);
-
-		r->value.number = s->current->date_sent;
-	} else {
-		r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
-		r->value.ptrarray = g_ptr_array_new ();
-	}
-
-	return r;
-}
-
-static ESExpResult *
-search_get_received_date(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s)
-{
-	ESExpResult *r;
-
-	r(printf("executing get-received-date\n"));
-
-	/* are we inside a match-all? */
-	if (s->current) {
-		r = e_sexp_result_new(f, ESEXP_RES_INT);
-
-		r->value.number = s->current->date_received;
-	} else {
-		r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
-		r->value.ptrarray = g_ptr_array_new ();
-	}
-
-	return r;
-}
-
-static ESExpResult *
-search_get_current_date(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s)
-{
-	ESExpResult *r;
-
-	r(printf("executing get-current-date\n"));
-
-	r = e_sexp_result_new(f, ESEXP_RES_INT);
-	r->value.number = time (NULL);
-	return r;
-}
-
-static ESExpResult *
-search_get_size (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s)
-{
-	ESExpResult *r;
-	
-	r(printf("executing get-size\n"));
-	
-	/* are we inside a match-all? */
-	if (s->current) {
-		r = e_sexp_result_new (f, ESEXP_RES_INT);
-		r->value.number = s->current->size / 1024;
-	} else {
-		r = e_sexp_result_new (f, ESEXP_RES_ARRAY_PTR);
-		r->value.ptrarray = g_ptr_array_new ();
-	}
-	
-	return r;
-}
-
-static ESExpResult *
-search_uid(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
-{
-	ESExpResult *r;
-	int i;
-
-	r(printf("executing uid\n"));
-
-	/* are we inside a match-all? */
-	if (search->current) {
-		int truth = FALSE;
-		const char *uid = camel_message_info_uid(search->current);
-
-		/* performs an OR of all words */
-		for (i=0;itype == ESEXP_RES_STRING
-			    && !strcmp(uid, argv[i]->value.string)) {
-				truth = TRUE;
-				break;
-			}
-		}
-		r = e_sexp_result_new(f, ESEXP_RES_BOOL);
-		r->value.bool = truth;
-	} else {
-		r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
-		r->value.ptrarray = g_ptr_array_new();
-		for (i=0;itype == ESEXP_RES_STRING)
-				g_ptr_array_add(r->value.ptrarray, argv[i]->value.string);
-		}
-	}
-
-	return r;
-}
diff --git a/camel/camel-folder-search.h b/camel/camel-folder-search.h
deleted file mode 100644
index e4d2253224..0000000000
--- a/camel/camel-folder-search.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Copyright (C) 2000 Ximian Inc.
- *
- *  Authors: Michael Zucchi 
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef _CAMEL_FOLDER_SEARCH_H
-#define _CAMEL_FOLDER_SEARCH_H
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include 
-#include 
-#include 
-#include 
-
-#define CAMEL_FOLDER_SEARCH_TYPE         (camel_folder_search_get_type ())
-#define CAMEL_FOLDER_SEARCH(obj)         CAMEL_CHECK_CAST (obj, camel_folder_search_get_type (), CamelFolderSearch)
-#define CAMEL_FOLDER_SEARCH_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_folder_search_get_type (), CamelFolderSearchClass)
-#define CAMEL_IS_FOLDER_SEARCH(obj)      CAMEL_CHECK_TYPE (obj, camel_folder_search_get_type ())
-
-typedef struct _CamelFolderSearchClass CamelFolderSearchClass;
-
-struct _CamelFolderSearch {
-	CamelObject parent;
-
-	struct _CamelFolderSearchPrivate *priv;
-
-	ESExp *sexp;		/* s-exp evaluator */
-	char *last_search;	/* last searched expression */
-
-	/* these are only valid during the search, and are reset afterwards */
-	CamelFolder *folder;	/* folder for current search */
-	GPtrArray *summary;	/* summary array for current search */
-	GHashTable *summary_hash; /* hashtable of summary items */
-	CamelMessageInfo *current; /* current message info, when searching one by one */
-	CamelMimeMessage *current_message; /* cache of current message, if required */
-	CamelIndex *body_index;
-};
-
-struct _CamelFolderSearchClass {
-	CamelObjectClass parent_class;
-
-	/* general bool/comparison options, usually these wont need to be set, unless it is compiling into another language */
-	ESExpResult * (*and)(struct _ESExp *f, int argc, struct _ESExpTerm **argv, CamelFolderSearch *s);
-	ESExpResult * (*or)(struct _ESExp *f, int argc, struct _ESExpTerm **argv, CamelFolderSearch *s);
-	ESExpResult * (*not)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-	ESExpResult * (*lt)(struct _ESExp *f, int argc, struct _ESExpTerm **argv, CamelFolderSearch *s);
-	ESExpResult * (*gt)(struct _ESExp *f, int argc, struct _ESExpTerm **argv, CamelFolderSearch *s);
-	ESExpResult * (*eq)(struct _ESExp *f, int argc, struct _ESExpTerm **argv, CamelFolderSearch *s);
-
-	/* search options */
-	/* (match-all [boolean expression]) Apply match to all messages */
-	ESExpResult * (*match_all)(struct _ESExp *f, int argc, struct _ESExpTerm **argv, CamelFolderSearch *s);
-
-	/* (body-contains "string1" "string2" ...) Returns a list of matches, or true if in single-message mode */
-	ESExpResult * (*body_contains)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
-	/* (header-contains "headername" "string1" ...) List of matches, or true if in single-message mode */
-	ESExpResult * (*header_contains)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-	
-	/* (header-matches "headername" "string") */
-	ESExpResult * (*header_matches)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-	
-	/* (header-starts-with "headername" "string") */
-	ESExpResult * (*header_starts_with)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-	
-	/* (header-ends-with "headername" "string") */
-	ESExpResult * (*header_ends_with)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-	
-	/* (header-exists "headername") */
-	ESExpResult * (*header_exists)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-	
-	/* (user-flag "flagname" "flagname" ...) If one of user-flag set */
-	ESExpResult * (*user_flag)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
-	/* (user-tag "flagname") Returns the value of a user tag.  Can only be used in match-all */
-	ESExpResult * (*user_tag)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-	
-	/* (system-flag "flagname") Returns the value of a system flag.  Can only be used in match-all */
-	ESExpResult * (*system_flag)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-	
-	/* (get-sent-date) Retrieve the date that the message was sent on as a time_t */
-	ESExpResult * (*get_sent_date)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
-	/* (get-received-date) Retrieve the date that the message was received on as a time_t */
-	ESExpResult * (*get_received_date)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
-	/* (get-current-date) Retrieve 'now' as a time_t */
-	ESExpResult * (*get_current_date)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
-	/* (get-size) Retrieve message size as an int (in kilobytes) */
-	ESExpResult * (*get_size)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
-	/* (uid "uid" ...) True if the uid is in the list */
-	ESExpResult * (*uid)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-};
-
-CamelType		camel_folder_search_get_type	(void);
-CamelFolderSearch      *camel_folder_search_new	(void);
-void camel_folder_search_construct (CamelFolderSearch *search);
-
-void camel_folder_search_set_folder(CamelFolderSearch *search, CamelFolder *folder);
-void camel_folder_search_set_summary(CamelFolderSearch *search, GPtrArray *summary);
-void camel_folder_search_set_body_index(CamelFolderSearch *search, CamelIndex *index);
-GPtrArray *camel_folder_search_execute_expression(CamelFolderSearch *search, const char *expr, CamelException *ex);
-gboolean camel_folder_search_match_expression(CamelFolderSearch *search, const char *expr,
-					      const CamelMessageInfo *info, CamelException *ex);
-void camel_folder_search_free_result(CamelFolderSearch *search, GPtrArray *);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* ! _CAMEL_FOLDER_SEARCH_H */
diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c
deleted file mode 100644
index 05b3f3a056..0000000000
--- a/camel/camel-folder-summary.c
+++ /dev/null
@@ -1,2831 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Copyright (C) 2000-2003 Ximian Inc.
- *
- *  Authors: Michael Zucchi 
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-
-#include "camel-folder-summary.h"
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#include 
-
-#include "e-util/md5-utils.h"
-#include "e-util/e-memory.h"
-
-#include "camel-private.h"
-
-
-static pthread_mutex_t info_lock = PTHREAD_MUTEX_INITIALIZER;
-
-/* this lock is ONLY for the standalone messageinfo stuff */
-#define GLOBAL_INFO_LOCK(i) pthread_mutex_lock(&info_lock)
-#define GLOBAL_INFO_UNLOCK(i) pthread_mutex_unlock(&info_lock)
-
-
-/* this should probably be conditional on it existing */
-#define USE_BSEARCH
-
-#define d(x)
-#define io(x)			/* io debug */
-
-#if 0
-extern int strdup_count, malloc_count, free_count;
-#endif
-
-#define CAMEL_FOLDER_SUMMARY_VERSION (12)
-
-#define _PRIVATE(o) (((CamelFolderSummary *)(o))->priv)
-
-/* trivial lists, just because ... */
-struct _node {
-	struct _node *next;
-};
-
-static struct _node *my_list_append(struct _node **list, struct _node *n);
-static int my_list_size(struct _node **list);
-
-static int summary_header_load(CamelFolderSummary *, FILE *);
-static int summary_header_save(CamelFolderSummary *, FILE *);
-
-static CamelMessageInfo * message_info_new(CamelFolderSummary *, struct _camel_header_raw *);
-static CamelMessageInfo * message_info_new_from_parser(CamelFolderSummary *, CamelMimeParser *);
-static CamelMessageInfo * message_info_new_from_message(CamelFolderSummary *s, CamelMimeMessage *msg);
-static CamelMessageInfo * message_info_load(CamelFolderSummary *, FILE *);
-static int		  message_info_save(CamelFolderSummary *, FILE *, CamelMessageInfo *);
-static void		  message_info_free(CamelFolderSummary *, CamelMessageInfo *);
-
-static CamelMessageContentInfo * content_info_new(CamelFolderSummary *, struct _camel_header_raw *);
-static CamelMessageContentInfo * content_info_new_from_parser(CamelFolderSummary *, CamelMimeParser *);
-static CamelMessageContentInfo * content_info_new_from_message(CamelFolderSummary *s, CamelMimePart *mp);
-static CamelMessageContentInfo * content_info_load(CamelFolderSummary *, FILE *);
-static int		         content_info_save(CamelFolderSummary *, FILE *, CamelMessageContentInfo *);
-static void		         content_info_free(CamelFolderSummary *, CamelMessageContentInfo *);
-
-static char *next_uid_string(CamelFolderSummary *s);
-
-static CamelMessageContentInfo * summary_build_content_info(CamelFolderSummary *s, CamelMessageInfo *msginfo, CamelMimeParser *mp);
-static CamelMessageContentInfo * summary_build_content_info_message(CamelFolderSummary *s, CamelMessageInfo *msginfo, CamelMimePart *object);
-
-static void camel_folder_summary_class_init (CamelFolderSummaryClass *klass);
-static void camel_folder_summary_init       (CamelFolderSummary *obj);
-static void camel_folder_summary_finalize   (CamelObject *obj);
-
-static CamelObjectClass *camel_folder_summary_parent;
-
-static void
-camel_folder_summary_class_init (CamelFolderSummaryClass *klass)
-{
-	camel_folder_summary_parent = camel_type_get_global_classfuncs (camel_object_get_type ());
-
-	klass->summary_header_load = summary_header_load;
-	klass->summary_header_save = summary_header_save;
-
-	klass->message_info_new  = message_info_new;
-	klass->message_info_new_from_parser = message_info_new_from_parser;
-	klass->message_info_new_from_message = message_info_new_from_message;
-	klass->message_info_load = message_info_load;
-	klass->message_info_save = message_info_save;
-	klass->message_info_free = message_info_free;
-
-	klass->content_info_new  = content_info_new;
-	klass->content_info_new_from_parser = content_info_new_from_parser;
-	klass->content_info_new_from_message = content_info_new_from_message;
-	klass->content_info_load = content_info_load;
-	klass->content_info_save = content_info_save;
-	klass->content_info_free = content_info_free;
-
-	klass->next_uid_string = next_uid_string;
-}
-
-static void
-camel_folder_summary_init (CamelFolderSummary *s)
-{
-	struct _CamelFolderSummaryPrivate *p;
-
-	p = _PRIVATE(s) = g_malloc0(sizeof(*p));
-
-	p->filter_charset = g_hash_table_new (camel_strcase_hash, camel_strcase_equal);
-
-	s->message_info_size = sizeof(CamelMessageInfo);
-	s->content_info_size = sizeof(CamelMessageContentInfo);
-
-	s->message_info_chunks = NULL;
-	s->content_info_chunks = NULL;
-
-#if defined (DOESTRV) || defined (DOEPOOLV)
-	s->message_info_strings = CAMEL_MESSAGE_INFO_LAST;
-#endif
-
-	s->version = CAMEL_FOLDER_SUMMARY_VERSION;
-	s->flags = 0;
-	s->time = 0;
-	s->nextuid = 1;
-
-	s->messages = g_ptr_array_new();
-	s->messages_uid = g_hash_table_new(g_str_hash, g_str_equal);
-	
-	p->summary_lock = g_mutex_new();
-	p->io_lock = g_mutex_new();
-	p->filter_lock = g_mutex_new();
-	p->alloc_lock = g_mutex_new();
-	p->ref_lock = g_mutex_new();
-}
-
-static void free_o_name(void *key, void *value, void *data)
-{
-	camel_object_unref((CamelObject *)value);
-	g_free(key);
-}
-
-static void
-camel_folder_summary_finalize (CamelObject *obj)
-{
-	struct _CamelFolderSummaryPrivate *p;
-	CamelFolderSummary *s = (CamelFolderSummary *)obj;
-
-	p = _PRIVATE(obj);
-
-	camel_folder_summary_clear(s);
-	g_ptr_array_free(s->messages, TRUE);
-	g_hash_table_destroy(s->messages_uid);
-
-	g_hash_table_foreach(p->filter_charset, free_o_name, 0);
-	g_hash_table_destroy(p->filter_charset);
-
-	g_free(s->summary_path);
-
-	if (s->message_info_chunks)
-		e_memchunk_destroy(s->message_info_chunks);
-	if (s->content_info_chunks)
-		e_memchunk_destroy(s->content_info_chunks);
-
-	if (p->filter_index)
-		camel_object_unref((CamelObject *)p->filter_index);
-	if (p->filter_64)
-		camel_object_unref((CamelObject *)p->filter_64);
-	if (p->filter_qp)
-		camel_object_unref((CamelObject *)p->filter_qp);
-	if (p->filter_uu)
-		camel_object_unref((CamelObject *)p->filter_uu);
-	if (p->filter_save)
-		camel_object_unref((CamelObject *)p->filter_save);
-	if (p->filter_html)
-		camel_object_unref((CamelObject *)p->filter_html);
-
-	if (p->filter_stream)
-		camel_object_unref((CamelObject *)p->filter_stream);
-	if (p->index)
-		camel_object_unref((CamelObject *)p->index);
-	
-	g_mutex_free(p->summary_lock);
-	g_mutex_free(p->io_lock);
-	g_mutex_free(p->filter_lock);
-	g_mutex_free(p->alloc_lock);
-	g_mutex_free(p->ref_lock);
-	
-	g_free(p);
-}
-
-CamelType
-camel_folder_summary_get_type (void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-	
-	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register (camel_object_get_type (), "CamelFolderSummary",
-					    sizeof (CamelFolderSummary),
-					    sizeof (CamelFolderSummaryClass),
-					    (CamelObjectClassInitFunc) camel_folder_summary_class_init,
-					    NULL,
-					    (CamelObjectInitFunc) camel_folder_summary_init,
-					    (CamelObjectFinalizeFunc) camel_folder_summary_finalize);
-	}
-	
-	return type;
-}
-
-/**
- * camel_folder_summary_new:
- *
- * Create a new CamelFolderSummary object.
- * 
- * Return value: A new CamelFolderSummary widget.
- **/
-CamelFolderSummary *
-camel_folder_summary_new (void)
-{
-	CamelFolderSummary *new = CAMEL_FOLDER_SUMMARY ( camel_object_new (camel_folder_summary_get_type ()));	return new;
-}
-
-
-/**
- * camel_folder_summary_set_filename:
- * @s: 
- * @name: 
- * 
- * Set the filename where the summary will be loaded to/saved from.
- **/
-void camel_folder_summary_set_filename(CamelFolderSummary *s, const char *name)
-{
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-
-	g_free(s->summary_path);
-	s->summary_path = g_strdup(name);
-
-	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-}
-
-/**
- * camel_folder_summary_set_index:
- * @s: 
- * @index: 
- * 
- * Set the index used to index body content.  If the index is NULL, or
- * not set (the default), no indexing of body content will take place.
- *
- * Unlike earlier behaviour, build_content need not be set to perform indexing.
- **/
-void camel_folder_summary_set_index(CamelFolderSummary *s, CamelIndex *index)
-{
-	struct _CamelFolderSummaryPrivate *p = _PRIVATE(s);
-
-	if (p->index)
-		camel_object_unref((CamelObject *)p->index);
-
-	p->index = index;
-	if (index)
-		camel_object_ref((CamelObject *)index);
-}
-
-/**
- * camel_folder_summary_set_build_content:
- * @s: 
- * @state: 
- * 
- * Set a flag to tell the summary to build the content info summary
- * (CamelMessageInfo.content).  The default is not to build content info
- * summaries.
- **/
-void camel_folder_summary_set_build_content(CamelFolderSummary *s, gboolean state)
-{
-	s->build_content = state;
-}
-
-/**
- * camel_folder_summary_count:
- * @s: 
- * 
- * Get the number of summary items stored in this summary.
- * 
- * Return value: The number of items int he summary.
- **/
-int
-camel_folder_summary_count(CamelFolderSummary *s)
-{
-	return s->messages->len;
-}
-
-/**
- * camel_folder_summary_index:
- * @s: 
- * @i: 
- * 
- * Retrieve a summary item by index number.
- *
- * A referenced to the summary item is returned, which may be
- * ref'd or free'd as appropriate.
- * 
- * Return value: The summary item, or NULL if the index @i is out
- * of range.
- * It must be freed using camel_folder_summary_info_free().
- **/
-CamelMessageInfo *
-camel_folder_summary_index(CamelFolderSummary *s, int i)
-{
-	CamelMessageInfo *info = NULL;
-
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	CAMEL_SUMMARY_LOCK(s, ref_lock);
-
-	if (imessages->len)
-		info = g_ptr_array_index(s->messages, i);
-
-	if (info)
-		info->refcount++;
-
-	CAMEL_SUMMARY_UNLOCK(s, ref_lock);
-	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-
-	return info;
-}
-
-/**
- * camel_folder_summary_index:
- * @s: 
- * @i: 
- * 
- * Obtain a copy of the summary array.  This is done atomically,
- * so cannot contain empty entries.
- *
- * It must be freed using camel_folder_summary_array_free().
- **/
-GPtrArray *
-camel_folder_summary_array(CamelFolderSummary *s)
-{
-	CamelMessageInfo *info;
-	GPtrArray *res = g_ptr_array_new();
-	int i;
-	
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	CAMEL_SUMMARY_LOCK(s, ref_lock);
-
-	g_ptr_array_set_size(res, s->messages->len);
-	for (i=0;imessages->len;i++) {
-		info = res->pdata[i] = g_ptr_array_index(s->messages, i);
-		info->refcount++;
-	}
-
-	CAMEL_SUMMARY_UNLOCK(s, ref_lock);
-	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-
-	return res;
-}
-
-/**
- * camel_folder_summary_array_free:
- * @s: 
- * @array: 
- * 
- * Free the folder summary array.
- **/
-void
-camel_folder_summary_array_free(CamelFolderSummary *s, GPtrArray *array)
-{
-	int i;
-
-	for (i=0;ilen;i++)
-		camel_folder_summary_info_free(s, array->pdata[i]);
-
-	g_ptr_array_free(array, TRUE);
-}
-
-/**
- * camel_folder_summary_uid:
- * @s: 
- * @uid: 
- * 
- * Retrieve a summary item by uid.
- *
- * A referenced to the summary item is returned, which may be
- * ref'd or free'd as appropriate.
- * 
- * Return value: The summary item, or NULL if the uid @uid
- * is not available.
- * It must be freed using camel_folder_summary_info_free().
- **/
-CamelMessageInfo *
-camel_folder_summary_uid(CamelFolderSummary *s, const char *uid)
-{
-	CamelMessageInfo *info;
-
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	CAMEL_SUMMARY_LOCK(s, ref_lock);
-
-	info = g_hash_table_lookup(s->messages_uid, uid);
-
-	if (info)
-		info->refcount++;
-
-	CAMEL_SUMMARY_UNLOCK(s, ref_lock);
-	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-
-	return info;
-}
-
-/**
- * camel_folder_summary_next_uid:
- * @s: 
- * 
- * Generate a new unique uid value as an integer.  This
- * may be used to create a unique sequence of numbers.
- * 
- * Return value: The next unique uid value.
- **/
-guint32 camel_folder_summary_next_uid(CamelFolderSummary *s)
-{
-	guint32 uid;
-
-
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-
-	uid = s->nextuid++;
-
-	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-
-	/* FIXME: sync this to disk */
-/*	summary_header_save(s);*/
-	return uid;
-}
-
-/**
- * camel_folder_summary_set_uid:
- * @s: 
- * @uid: The next minimum uid to assign.  To avoid clashing
- * uid's, set this to the uid of a given messages + 1.
- * 
- * Set the next minimum uid available.  This can be used to
- * ensure new uid's do not clash with existing uid's.
- **/
-void camel_folder_summary_set_uid(CamelFolderSummary *s, guint32 uid)
-{
-	/* TODO: sync to disk? */
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-
-	s->nextuid = MAX(s->nextuid, uid);
-
-	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-}
-
-/**
- * camel_folder_summary_next_uid_string:
- * @s: 
- * 
- * Retrieve the next uid, but as a formatted string.
- * 
- * Return value: The next uid as an unsigned integer string.
- * This string must be freed by the caller.
- **/
-char *
-camel_folder_summary_next_uid_string(CamelFolderSummary *s)
-{
-	return ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->next_uid_string(s);
-}
-
-/* loads the content descriptions, recursively */
-static CamelMessageContentInfo *
-perform_content_info_load(CamelFolderSummary *s, FILE *in)
-{
-	int i;
-	guint32 count;
-	CamelMessageContentInfo *ci, *part;
-
-	ci = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_load(s, in);
-	if (ci == NULL)
-		return NULL;
-
-	if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500) {
-		camel_folder_summary_content_info_free(s, ci);
-		return NULL;
-	}
-
-	for (i=0;ichilds, (struct _node *)part);
-			part->parent = ci;
-		} else {
-			d(fprintf (stderr, "Summary file format messed up?"));
-			camel_folder_summary_content_info_free(s, ci);
-			return NULL;
-		}
-	}
-	return ci;
-}
-
-int
-camel_folder_summary_load(CamelFolderSummary *s)
-{
-	FILE *in;
-	int i;
-	CamelMessageInfo *mi;
-
-	if (s->summary_path == NULL)
-		return 0;
-
-	in = fopen(s->summary_path, "r");
-	if (in == NULL)
-		return -1;
-
-	CAMEL_SUMMARY_LOCK(s, io_lock);
-	if ( ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s, in) == -1)
-		goto error;
-
-	/* now read in each message ... */
-	for (i=0;isaved_count;i++) {
-		mi = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_load(s, in);
-
-		if (mi == NULL)
-			goto error;
-
-		if (s->build_content) {
-			mi->content = perform_content_info_load(s, in);
-			if (mi->content == NULL) {
-				camel_folder_summary_info_free(s, mi);
-				goto error;
-			}
-		}
-
-		camel_folder_summary_add(s, mi);
-	}
-
-	CAMEL_SUMMARY_UNLOCK(s, io_lock);
-	
-	if (fclose (in) != 0)
-		return -1;
-
-	s->flags &= ~CAMEL_SUMMARY_DIRTY;
-
-	return 0;
-
-error:
-	if (errno != EINVAL)
-		g_warning ("Cannot load summary file: `%s': %s", s->summary_path, g_strerror (errno));
-	
-	CAMEL_SUMMARY_UNLOCK(s, io_lock);
-	fclose (in);
-	s->flags |= ~CAMEL_SUMMARY_DIRTY;
-
-	return -1;
-}
-
-/* saves the content descriptions, recursively */
-static int
-perform_content_info_save(CamelFolderSummary *s, FILE *out, CamelMessageContentInfo *ci)
-{
-	CamelMessageContentInfo *part;
-
-	if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS (s)))->content_info_save (s, out, ci) == -1)
-		return -1;
-	
-	if (camel_file_util_encode_uint32 (out, my_list_size ((struct _node **)&ci->childs)) == -1)
-		return -1;
-	
-	part = ci->childs;
-	while (part) {
-		if (perform_content_info_save (s, out, part) == -1)
-			return -1;
-		part = part->next;
-	}
-	
-	return 0;
-}
-
-/**
- * camel_folder_summary_save:
- * @s: 
- * 
- * Writes the summary to disk.  The summary is only written if changes
- * have occured.
- * 
- * Return value: Returns -1 on error.
- **/
-int
-camel_folder_summary_save(CamelFolderSummary *s)
-{
-	FILE *out;
-	int fd, i;
-	guint32 count;
-	CamelMessageInfo *mi;
-	char *path;
-
-	if (s->summary_path == NULL
-	    || (s->flags & CAMEL_SUMMARY_DIRTY) == 0)
-		return 0;
-
-	path = alloca(strlen(s->summary_path)+4);
-	sprintf(path, "%s~", s->summary_path);
-	fd = open(path, O_RDWR|O_CREAT|O_TRUNC, 0600);
-	if (fd == -1)
-		return -1;
-	out = fdopen(fd, "w");
-	if (out == NULL) {
-		i = errno;
-		unlink(path);
-		close(fd);
-		errno = i;
-		return -1;
-	}
-
-	io(printf("saving header\n"));
-
-	CAMEL_SUMMARY_LOCK(s, io_lock);
-
-	if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_save(s, out) == -1)
-		goto exception;
-	
-	/* now write out each message ... */
-	/* we check ferorr when done for i/o errors */
-	count = s->messages->len;
-	for (i = 0; i < count; i++) {
-		mi = s->messages->pdata[i];
-		if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS (s)))->message_info_save (s, out, mi) == -1)
-			goto exception;
-		
-		if (s->build_content) {
-			if (perform_content_info_save (s, out, mi->content) == -1)
-				goto exception;
-		}
-	}
-	
-	if (fflush (out) != 0 || fsync (fileno (out)) == -1)
-		goto exception;
-	
-	fclose (out);
-	
-	CAMEL_SUMMARY_UNLOCK(s, io_lock);
-	
-	if (rename(path, s->summary_path) == -1) {
-		i = errno;
-		unlink(path);
-		errno = i;
-		return -1;
-	}
-	
-	s->flags &= ~CAMEL_SUMMARY_DIRTY;
-	return 0;
-	
- exception:
-	
-	i = errno;
-	
-	fclose (out);
-	
-	CAMEL_SUMMARY_UNLOCK(s, io_lock);
-	
-	unlink (path);
-	errno = i;
-	
-	return -1;
-}
-
-/**
- * camel_folder_summary_header_load:
- * @s: Summary object.
- * 
- * Only load the header information from the summary,
- * keep the rest on disk.  This should only be done on
- * a fresh summary object.
- * 
- * Return value: -1 on error.
- **/
-int camel_folder_summary_header_load(CamelFolderSummary *s)
-{
-	FILE *in;
-	int ret;
-
-	if (s->summary_path == NULL)
-		return 0;
-
-	in = fopen(s->summary_path, "r");
-	if (in == NULL)
-		return -1;
-
-	CAMEL_SUMMARY_LOCK(s, io_lock);
-	ret = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s, in);
-	CAMEL_SUMMARY_UNLOCK(s, io_lock);
-	
-	fclose(in);
-	s->flags &= ~CAMEL_SUMMARY_DIRTY;
-	return ret;
-}
-
-static int
-summary_assign_uid(CamelFolderSummary *s, CamelMessageInfo *info)
-{
-	const char *uid;
-	CamelMessageInfo *mi;
-
-	uid = camel_message_info_uid(info);
-	if (uid == NULL || uid[0] == 0) {
-		camel_message_info_set_uid(info, camel_folder_summary_next_uid_string(s));
-		uid = camel_message_info_uid(info);
-	}
-
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-
-	while ((mi = g_hash_table_lookup(s->messages_uid, uid))) {
-		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-		if (mi == info)
-			return 0;
-		d(printf ("Trying to insert message with clashing uid (%s).  new uid re-assigned", camel_message_info_uid(info)));
-		camel_message_info_set_uid(info, camel_folder_summary_next_uid_string(s));
-		uid = camel_message_info_uid(info);
-		info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
-		CAMEL_SUMMARY_LOCK(s, summary_lock);
-	}
-
-	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-	return 1;
-}
-
-/**
- * camel_folder_summary_add:
- * @s: 
- * @info: 
- * 
- * Adds a new @info record to the summary.  If @info->uid is NULL, then a new
- * uid is automatically re-assigned by calling :next_uid_string().
- *
- * The @info record should have been generated by calling one of the
- * info_new_*() functions, as it will be free'd based on the summary
- * class.  And MUST NOT be allocated directly using malloc.
- **/
-void camel_folder_summary_add(CamelFolderSummary *s, CamelMessageInfo *info)
-{
-	if (info == NULL)
-		return;
-
-	if (summary_assign_uid(s, info) == 0)
-		return;
-
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-
-/* unnecessary for pooled vectors */
-#ifdef DOESTRV
-	/* this is vitally important, and also if this is ever modified, then
-	   the hash table needs to be resynced */
-	info->strings = e_strv_pack(info->strings);
-#endif
-
-	g_ptr_array_add(s->messages, info);
-	g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info);
-	s->flags |= CAMEL_SUMMARY_DIRTY;
-
-	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-}
-
-/**
- * camel_folder_summary_add_from_header:
- * @s: 
- * @h: 
- * 
- * Build a new info record based on a set of headers, and add it to the
- * summary.
- *
- * Note that this function should not be used if build_content_info has
- * been specified for this summary.
- * 
- * Return value: The newly added record.
- **/
-CamelMessageInfo *camel_folder_summary_add_from_header(CamelFolderSummary *s, struct _camel_header_raw *h)
-{
-	CamelMessageInfo *info = camel_folder_summary_info_new_from_header(s, h);
-
-	camel_folder_summary_add(s, info);
-
-	return info;
-}
-
-/**
- * camel_folder_summary_add_from_parser:
- * @s: 
- * @mp: 
- * 
- * Build a new info record based on the current position of a CamelMimeParser.
- *
- * The parser should be positioned before the start of the message to summarise.
- * This function may be used if build_contnet_info or an index has been
- * specified for the summary.
- * 
- * Return value: The newly added record.
- **/
-CamelMessageInfo *camel_folder_summary_add_from_parser(CamelFolderSummary *s, CamelMimeParser *mp)
-{
-	CamelMessageInfo *info = camel_folder_summary_info_new_from_parser(s, mp);
-
-	camel_folder_summary_add(s, info);
-
-	return info;
-}
-
-/**
- * camel_folder_summary_add_from_message:
- * @s: 
- * @msg: 
- * 
- * Add a summary item from an existing message.
- * 
- * Return value: 
- **/
-CamelMessageInfo *camel_folder_summary_add_from_message(CamelFolderSummary *s, CamelMimeMessage *msg)
-{
-	CamelMessageInfo *info = camel_folder_summary_info_new_from_message(s, msg);
-
-	camel_folder_summary_add(s, info);
-
-	return info;
-}
-
-/**
- * camel_folder_summary_info_new_from_header:
- * @s: 
- * @h: 
- * 
- * Create a new info record from a header.
- * 
- * Return value: Guess?  This info record MUST be freed using
- * camel_folder_summary_info_free(), camel_message_info_free() will not work.
- **/
-CamelMessageInfo *camel_folder_summary_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h)
-{
-	return ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s))) -> message_info_new(s, h);
-}
-
-/**
- * camel_folder_summary_info_new_from_parser:
- * @s: 
- * @mp: 
- * 
- * Create a new info record from a parser.  If the parser cannot
- * determine a uid, then none will be assigned.
-
- * If indexing is enabled, and the parser cannot determine a new uid, then
- * one is automatically assigned.
- *
- * If indexing is enabled, then the content will be indexed based
- * on this new uid.  In this case, the message info MUST be
- * added using :add().
- *
- * Once complete, the parser will be positioned at the end of
- * the message.
- *
- * Return value: Guess?  This info record MUST be freed using
- * camel_folder_summary_info_free(), camel_message_info_free() will not work.
- **/
-CamelMessageInfo *camel_folder_summary_info_new_from_parser(CamelFolderSummary *s, CamelMimeParser *mp)
-{
-	CamelMessageInfo *info = NULL;
-	char *buffer;
-	size_t len;
-	struct _CamelFolderSummaryPrivate *p = _PRIVATE(s);
-	off_t start;
-	CamelIndexName *name = NULL;
-
-	/* should this check the parser is in the right state, or assume it is?? */
-
-	start = camel_mime_parser_tell(mp);
-	if (camel_mime_parser_step(mp, &buffer, &len) != CAMEL_MIME_PARSER_STATE_EOF) {
-		info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new_from_parser(s, mp);
-
-		camel_mime_parser_unstep(mp);
-
-		/* assign a unique uid, this is slightly 'wrong' as we do not really
-		 * know if we are going to store this in the summary, but no matter */
-		if (p->index)
-			summary_assign_uid(s, info);
-
-		CAMEL_SUMMARY_LOCK(s, filter_lock);
-
-		if (p->index) {
-			if (p->filter_index == NULL)
-				p->filter_index = camel_mime_filter_index_new_index(p->index);
-			camel_index_delete_name(p->index, camel_message_info_uid(info));
-			name = camel_index_add_name(p->index, camel_message_info_uid(info));
-			camel_mime_filter_index_set_name(p->filter_index, name);
-		}
-
-		/* always scan the content info, even if we dont save it */
-		info->content = summary_build_content_info(s, info, mp);
-
-		if (name) {
-			camel_index_write_name(p->index, name);
-			camel_object_unref((CamelObject *)name);
-			camel_mime_filter_index_set_name(p->filter_index, NULL);
-		}
-
-		CAMEL_SUMMARY_UNLOCK(s, filter_lock);
-
-		info->size = camel_mime_parser_tell(mp) - start;
-	}
-	return info;
-}
-
-/**
- * camel_folder_summary_info_new_from_message:
- * @: 
- * @: 
- * 
- * Create a summary item from a message.
- * 
- * Return value: 
- **/
-CamelMessageInfo *camel_folder_summary_info_new_from_message(CamelFolderSummary *s, CamelMimeMessage *msg)
-{
-	CamelMessageInfo *info;
-	struct _CamelFolderSummaryPrivate *p = _PRIVATE(s);
-	CamelIndexName *name = NULL;
-
-	info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new_from_message(s, msg);
-
-	/* assign a unique uid, this is slightly 'wrong' as we do not really
-	 * know if we are going to store this in the summary, but we need it set for indexing */
-	if (p->index)
-		summary_assign_uid(s, info);
-
-	CAMEL_SUMMARY_LOCK(s, filter_lock);
-
-	if (p->index) {
-		if (p->filter_index == NULL)
-			p->filter_index = camel_mime_filter_index_new_index(p->index);
-		camel_index_delete_name(p->index, camel_message_info_uid(info));
-		name = camel_index_add_name(p->index, camel_message_info_uid(info));
-		camel_mime_filter_index_set_name(p->filter_index, name);
-
-		if (p->filter_stream == NULL) {
-			CamelStream *null = camel_stream_null_new();
-
-			p->filter_stream = camel_stream_filter_new_with_stream(null);
-			camel_object_unref((CamelObject *)null);
-		}
-	}
-
-	info->content = summary_build_content_info_message(s, info, (CamelMimePart *)msg);
-
-	if (name) {
-		camel_index_write_name(p->index, name);
-		camel_object_unref((CamelObject *)name);
-		camel_mime_filter_index_set_name(p->filter_index, NULL);
-	}
-
-	CAMEL_SUMMARY_UNLOCK(s, filter_lock);
-
-	return info;
-}
-
-/**
- * camel_folder_summary_content_info_free:
- * @s: 
- * @ci: 
- * 
- * Free the content info @ci, and all associated memory.
- **/
-void
-camel_folder_summary_content_info_free(CamelFolderSummary *s, CamelMessageContentInfo *ci)
-{
-	CamelMessageContentInfo *pw, *pn;
-
-	pw = ci->childs;
-	((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_free(s, ci);
-	while (pw) {
-		pn = pw->next;
-		camel_folder_summary_content_info_free(s, pw);
-		pw = pn;
-	}
-}
-
-/**
- * camel_folder_summary_info_free:
- * @s: 
- * @mi: 
- * 
- * Unref and potentially free the message info @mi, and all associated memory.
- **/
-void camel_folder_summary_info_free(CamelFolderSummary *s, CamelMessageInfo *mi)
-{
-	CamelMessageContentInfo *ci;
-
-	g_assert(mi);
-	g_assert(s);
-
-	CAMEL_SUMMARY_LOCK(s, ref_lock);
-
-	g_assert(mi->refcount >= 1);
-
-	mi->refcount--;
-	if (mi->refcount > 0) {
-		CAMEL_SUMMARY_UNLOCK(s, ref_lock);
-		return;
-	}
-
-	CAMEL_SUMMARY_UNLOCK(s, ref_lock);
-
-	ci = mi->content;
-
-	((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_free(s, mi);		
-	if (s->build_content && ci) {
-		camel_folder_summary_content_info_free(s, ci);
-	}
-}
-
-/**
- * camel_folder_summary_info_ref:
- * @s: 
- * @mi: 
- * 
- * Add an extra reference to @mi.
- **/
-void camel_folder_summary_info_ref(CamelFolderSummary *s, CamelMessageInfo *mi)
-{
-	g_assert(mi);
-	g_assert(s);
-
-	CAMEL_SUMMARY_LOCK(s, ref_lock);
-	g_assert(mi->refcount >= 1);
-	mi->refcount++;
-	CAMEL_SUMMARY_UNLOCK(s, ref_lock);
-}
-
-/**
- * camel_folder_summary_touch:
- * @s: 
- * 
- * Mark the summary as changed, so that a save will save it.
- **/
-void
-camel_folder_summary_touch(CamelFolderSummary *s)
-{
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	s->flags |= CAMEL_SUMMARY_DIRTY;
-	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-}
-
-/**
- * camel_folder_summary_clear:
- * @s: 
- * 
- * Empty the summary contents.
- **/
-void
-camel_folder_summary_clear(CamelFolderSummary *s)
-{
-	int i;
-
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	if (camel_folder_summary_count(s) == 0) {
-		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-		return;
-	}
-
-	for (i=0;imessages->len;i++)
-		camel_folder_summary_info_free(s, s->messages->pdata[i]);
-
-	g_ptr_array_set_size(s->messages, 0);
-	g_hash_table_destroy(s->messages_uid);
-	s->messages_uid = g_hash_table_new(g_str_hash, g_str_equal);
-	s->flags |= CAMEL_SUMMARY_DIRTY;
-	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-}
-
-/**
- * camel_folder_summary_remove:
- * @s: 
- * @info: 
- * 
- * Remove a specific @info record from the summary.
- **/
-void camel_folder_summary_remove(CamelFolderSummary *s, CamelMessageInfo *info)
-{
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	g_hash_table_remove(s->messages_uid, camel_message_info_uid(info));
-	g_ptr_array_remove(s->messages, info);
-	s->flags |= CAMEL_SUMMARY_DIRTY;
-	CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-
-	camel_folder_summary_info_free(s, info);
-}
-
-/**
- * camel_folder_summary_remove_uid:
- * @s: 
- * @uid: 
- * 
- * Remove a specific info record from the summary, by @uid.
- **/
-void camel_folder_summary_remove_uid(CamelFolderSummary *s, const char *uid)
-{
-        CamelMessageInfo *oldinfo;
-        char *olduid;
-
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	CAMEL_SUMMARY_LOCK(s, ref_lock);
-        if (g_hash_table_lookup_extended(s->messages_uid, uid, (void *)&olduid, (void *)&oldinfo)) {
-		/* make sure it doesn't vanish while we're removing it */
-		oldinfo->refcount++;
-		CAMEL_SUMMARY_UNLOCK(s, ref_lock);
-		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-		camel_folder_summary_remove(s, oldinfo);
-		camel_folder_summary_info_free(s, oldinfo);
-        } else {
-		CAMEL_SUMMARY_UNLOCK(s, ref_lock);
-		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-	}
-}
-
-/**
- * camel_folder_summary_remove_index:
- * @s: 
- * @index: 
- * 
- * Remove a specific info record from the summary, by index.
- **/
-void camel_folder_summary_remove_index(CamelFolderSummary *s, int index)
-{
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	if (index < s->messages->len) {
-		CamelMessageInfo *info = s->messages->pdata[index];
-
-		g_hash_table_remove(s->messages_uid, camel_message_info_uid(info));
-		g_ptr_array_remove_index(s->messages, index);
-		s->flags |= CAMEL_SUMMARY_DIRTY;
-
-		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-		camel_folder_summary_info_free(s, info);
-	} else {
-		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-	}
-}
-
-/**
- * camel_folder_summary_remove_range:
- * @s: 
- * @start: initial index
- * @end: last index to remove
- * 
- * Removes an indexed range of info records.
- **/
-void camel_folder_summary_remove_range(CamelFolderSummary *s, int start, int end)
-{
-	if (end < start)
-		return;
-
-	CAMEL_SUMMARY_LOCK(s, summary_lock);
-	if (start < s->messages->len) {
-		CamelMessageInfo **infos;
-		int i;
-
-		end = MIN(end+1, s->messages->len);
-		infos = g_malloc((end-start)*sizeof(infos[0]));
-
-		for (i=start;imessages->pdata[i];
-
-			infos[i-start] = info;
-			g_hash_table_remove(s->messages_uid, camel_message_info_uid(info));
-		}
-
-		memmove(s->messages->pdata+start, s->messages->pdata+end, (s->messages->len-end)*sizeof(s->messages->pdata[0]));
-		g_ptr_array_set_size(s->messages, s->messages->len - (end - start));
-		s->flags |= CAMEL_SUMMARY_DIRTY;
-
-		CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-
-		for (i=start;i=32 string, length = n-32
-*/
-
-#ifdef USE_BSEARCH
-static int
-token_search_cmp(char *key, char **index)
-{
-	d(printf("comparing '%s' to '%s'\n", key, *index));
-	return strcmp(key, *index);
-}
-#endif
-
-/**
- * camel_folder_summary_encode_token:
- * @out: 
- * @str: 
- * 
- * Encode a string value, but use tokenisation and compression
- * to reduce the size taken for common mailer words.  This
- * can still be used to encode normal strings as well.
- * 
- * Return value: -1 on error.
- **/
-int
-camel_folder_summary_encode_token(FILE *out, const char *str)
-{
-	io(printf("Encoding token: '%s'\n", str));
-
-	if (str == NULL) {
-		return camel_file_util_encode_uint32(out, 0);
-	} else {
-		int len = strlen(str);
-		int i, token=-1;
-
-		if (len <= 16) {
-			char lower[32];
-			char **match;
-
-			for (i=0;i 10240) {
-		io(printf ("Got broken string header length: %d bytes", len));
-		*str = NULL;
-		return -1;
-	} else {
-		len -= 32;
-		ret = g_malloc(len+1);
-		if (fread(ret, len, 1, in) != 1) {
-			g_free(ret);
-			*str = NULL;
-			return -1;
-		}
-		ret[len]=0;
-	}
-
-	io(printf("Token = '%s'\n", ret));
-
-	*str = ret;
-	return 0;
-}
-
-static struct _node *
-my_list_append(struct _node **list, struct _node *n)
-{
-	struct _node *ln = (struct _node *)list;
-	while (ln->next)
-		ln = ln->next;
-	n->next = 0;
-	ln->next = n;
-	return n;
-}
-
-static int
-my_list_size(struct _node **list)
-{
-	int len = 0;
-	struct _node *ln = (struct _node *)list;
-	while (ln->next) {
-		ln = ln->next;
-		len++;
-	}
-	return len;
-}
-
-static int
-summary_header_load(CamelFolderSummary *s, FILE *in)
-{
-	gint32 version, flags, nextuid, count;
-	time_t time;
-
-	fseek(in, 0, SEEK_SET);
-
-	io(printf("Loading header\n"));
-
-	if (camel_file_util_decode_fixed_int32(in, &version) == -1
-	    || camel_file_util_decode_fixed_int32(in, &flags) == -1
-	    || camel_file_util_decode_fixed_int32(in, &nextuid) == -1
-	    || camel_file_util_decode_time_t(in, &time) == -1
-	    || camel_file_util_decode_fixed_int32(in, &count) == -1) {
-		return -1;
-	}
-
-	s->nextuid = nextuid;
-	s->flags = flags;
-	s->time = time;
-	s->saved_count = count;
-	if (s->version != version) {
-		d(printf ("Summary header version mismatch"));
-		errno = EINVAL;
-		return -1;
-	}
-	return 0;
-}
-
-static int
-summary_header_save(CamelFolderSummary *s, FILE *out)
-{
-	fseek(out, 0, SEEK_SET);
-
-	io(printf("Savining header\n"));
-
-	camel_file_util_encode_fixed_int32(out, s->version);
-	camel_file_util_encode_fixed_int32(out, s->flags);
-	camel_file_util_encode_fixed_int32(out, s->nextuid);
-	camel_file_util_encode_time_t(out, s->time);
-	return camel_file_util_encode_fixed_int32(out, camel_folder_summary_count(s));
-}
-
-/* are these even useful for anything??? */
-static CamelMessageInfo * message_info_new_from_parser(CamelFolderSummary *s, CamelMimeParser *mp)
-{
-	CamelMessageInfo *mi = NULL;
-	int state;
-
-	state = camel_mime_parser_state(mp);
-	switch (state) {
-	case CAMEL_MIME_PARSER_STATE_HEADER:
-	case CAMEL_MIME_PARSER_STATE_MESSAGE:
-	case CAMEL_MIME_PARSER_STATE_MULTIPART:
-		mi = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new(s, camel_mime_parser_headers_raw(mp));
-		break;
-	default:
-		g_error("Invalid parser state");
-	}
-
-	return mi;
-}
-
-static CamelMessageContentInfo * content_info_new_from_parser(CamelFolderSummary *s, CamelMimeParser *mp)
-{
-	CamelMessageContentInfo *ci = NULL;
-
-	switch (camel_mime_parser_state(mp)) {
-	case CAMEL_MIME_PARSER_STATE_HEADER:
-	case CAMEL_MIME_PARSER_STATE_MESSAGE:
-	case CAMEL_MIME_PARSER_STATE_MULTIPART:
-		ci = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new(s, camel_mime_parser_headers_raw(mp));
-		if (ci) {
-			ci->type = camel_mime_parser_content_type(mp);
-			camel_content_type_ref(ci->type);
-		}
-		break;
-	default:
-		g_error("Invalid parser state");
-	}
-
-	return ci;
-}
-
-static CamelMessageInfo * message_info_new_from_message(CamelFolderSummary *s, CamelMimeMessage *msg)
-{
-	CamelMessageInfo *mi;
-
-	mi = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new(s, ((CamelMimePart *)msg)->headers);
-
-	return mi;
-}
-
-static CamelMessageContentInfo * content_info_new_from_message(CamelFolderSummary *s, CamelMimePart *mp)
-{
-	CamelMessageContentInfo *ci;
-
-	ci = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new(s, mp->headers);
-
-	return ci;
-}
-
-static char *
-summary_format_address(struct _camel_header_raw *h, const char *name, const char *charset)
-{
-	struct _camel_header_address *addr;
-	const char *text;
-	char *ret;
-
-	text = camel_header_raw_find (&h, name, NULL);
-	addr = camel_header_address_decode (text, charset);
-	if (addr) {
-		ret = camel_header_address_list_format (addr);
-		camel_header_address_list_clear (&addr);
-	} else {
-		ret = g_strdup (text);
-	}
-	
-	return ret;
-}
-
-static char *
-summary_format_string (struct _camel_header_raw *h, const char *name, const char *charset)
-{
-	const char *text;
-	
-	text = camel_header_raw_find (&h, name, NULL);
-	if (text) {
-		while (isspace ((unsigned) *text))
-			text++;
-		return camel_header_decode_string (text, charset);
-	} else {
-		return NULL;
-	}
-}
-
-/**
- * camel_folder_summary_info_new:
- * @s: 
- * 
- * Allocate a new camel message info, suitable for adding
- * to this summary.
- * 
- * Return value: 
- **/
-CamelMessageInfo *
-camel_folder_summary_info_new(CamelFolderSummary *s)
-{
-	CamelMessageInfo *mi;
-
-	CAMEL_SUMMARY_LOCK(s, alloc_lock);
-	if (s->message_info_chunks == NULL)
-		s->message_info_chunks = e_memchunk_new(32, s->message_info_size);
-	mi = e_memchunk_alloc(s->message_info_chunks);
-	CAMEL_SUMMARY_UNLOCK(s, alloc_lock);
-
-	memset(mi, 0, s->message_info_size);
-#ifdef DOEPOOLV
-	mi->strings = e_poolv_new (s->message_info_strings);
-#endif
-#ifdef DOESTRV
-	mi->strings = e_strv_new(s->message_info_strings);
-#endif
-	mi->refcount = 1;
-	return mi;
-}
-
-/**
- * camel_folder_summary_content_info_new:
- * @s: 
- * 
- * Allocate a new camel message content info, suitable for adding
- * to this summary.
- * 
- * Return value: 
- **/
-CamelMessageContentInfo *
-camel_folder_summary_content_info_new(CamelFolderSummary *s)
-{
-	CamelMessageContentInfo *ci;
-
-	CAMEL_SUMMARY_LOCK(s, alloc_lock);
-	if (s->content_info_chunks == NULL)
-		s->content_info_chunks = e_memchunk_new(32, s->content_info_size);
-	ci = e_memchunk_alloc(s->content_info_chunks);
-	CAMEL_SUMMARY_UNLOCK(s, alloc_lock);
-
-	memset(ci, 0, s->content_info_size);
-	return ci;
-}
-
-static CamelMessageInfo *
-message_info_new(CamelFolderSummary *s, struct _camel_header_raw *h)
-{
-	CamelMessageInfo *mi;
-	const char *received;
-	guchar digest[16];
-	struct _camel_header_references *refs, *irt, *scan;
-	char *msgid;
-	int count;
-	char *subject, *from, *to, *cc, *mlist;
-	CamelContentType *ct = NULL;
-	const char *content, *charset = NULL;
-
-	mi = camel_folder_summary_info_new(s);
-
-	if ((content = camel_header_raw_find(&h, "Content-Type", NULL))
-	     && (ct = camel_content_type_decode(content))
-	     && (charset = camel_content_type_param(ct, "charset"))
-	     && (strcasecmp(charset, "us-ascii") == 0))
-		charset = NULL;
-	
-	charset = charset ? e_iconv_charset_name (charset) : NULL;
-	
-	subject = summary_format_string(h, "subject", charset);
-	from = summary_format_address(h, "from", charset);
-	to = summary_format_address(h, "to", charset);
-	cc = summary_format_address(h, "cc", charset);
-	mlist = camel_header_raw_check_mailing_list(&h);
-
-	if (ct)
-		camel_content_type_unref(ct);
-
-#ifdef DOEPOOLV
-	e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_SUBJECT, subject, TRUE);
-	e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_FROM, from, TRUE);
-	e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_TO, to, TRUE);
-	e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_CC, cc, TRUE);
-	e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_MLIST, mlist, TRUE);
-#elif defined (DOESTRV)
-	e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_SUBJECT, subject);
-	e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_FROM, from);
-	e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_TO, to);
-	e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_CC, cc);
-	e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_MLIST, mlist);
-#else
-	mi->subject = subject;
-	mi->from = from;
-	mi->to = to;
-	mi->cc = cc;
-	mi->mlist = mlist;
-#endif
-
-	mi->user_flags = NULL;
-	mi->user_tags = NULL;
-	mi->date_sent = camel_header_decode_date(camel_header_raw_find(&h, "date", NULL), NULL);
-	received = camel_header_raw_find(&h, "received", NULL);
-	if (received)
-		received = strrchr(received, ';');
-	if (received)
-		mi->date_received = camel_header_decode_date(received + 1, NULL);
-	else
-		mi->date_received = 0;
-
-	msgid = camel_header_msgid_decode(camel_header_raw_find(&h, "message-id", NULL));
-	if (msgid) {
-		md5_get_digest(msgid, strlen(msgid), digest);
-		memcpy(mi->message_id.id.hash, digest, sizeof(mi->message_id.id.hash));
-		g_free(msgid);
-	}
-	
-	/* decode our references and in-reply-to headers */
-	refs = camel_header_references_decode (camel_header_raw_find (&h, "references", NULL));
-	irt = camel_header_references_inreplyto_decode (camel_header_raw_find (&h, "in-reply-to", NULL));
-	if (refs || irt) {
-		if (irt) {
-			/* The References field is populated from the ``References'' and/or ``In-Reply-To''
-			   headers. If both headers exist, take the first thing in the In-Reply-To header
-			   that looks like a Message-ID, and append it to the References header. */
-			
-			if (refs)
-				irt->next = refs;
-			
-			refs = irt;
-		}
-		
-		count = camel_header_references_list_size(&refs);
-		mi->references = g_malloc(sizeof(*mi->references) + ((count-1) * sizeof(mi->references->references[0])));
-		count = 0;
-		scan = refs;
-		while (scan) {
-			md5_get_digest(scan->id, strlen(scan->id), digest);
-			memcpy(mi->references->references[count].id.hash, digest, sizeof(mi->message_id.id.hash));
-			count++;
-			scan = scan->next;
-		}
-		mi->references->size = count;
-		camel_header_references_list_clear(&refs);
-	}
-
-	return mi;
-}
-
-
-static CamelMessageInfo *
-message_info_load(CamelFolderSummary *s, FILE *in)
-{
-	CamelMessageInfo *mi;
-	guint count;
-	int i;
-	char *subject, *from, *to, *cc, *mlist, *uid;;
-
-	mi = camel_folder_summary_info_new(s);
-
-	io(printf("Loading message info\n"));
-
-	camel_file_util_decode_string(in, &uid);
-	camel_file_util_decode_uint32(in, &mi->flags);
-	camel_file_util_decode_uint32(in, &mi->size);
-	camel_file_util_decode_time_t(in, &mi->date_sent);
-	camel_file_util_decode_time_t(in, &mi->date_received);
-	camel_file_util_decode_string(in, &subject);
-	camel_file_util_decode_string(in, &from);
-	camel_file_util_decode_string(in, &to);
-	camel_file_util_decode_string(in, &cc);
-	camel_file_util_decode_string(in, &mlist);
-
-#ifdef DOEPOOLV
-	e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_UID, uid, TRUE);
-	e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_SUBJECT, subject, TRUE);
-	e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_FROM, from, TRUE);
-	e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_TO, to, TRUE);
-	e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_CC, cc, TRUE);
-	e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_MLIST, mlist, TRUE);
-#elif defined (DOESTRV)
-	e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_UID, uid);
-	e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_SUBJECT, subject);
-	e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_FROM, from);
-	e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_TO, to);
-	e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_CC, cc);
-	e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_MLIST, mlist);
-#else
-	mi->uid = uid;
-	mi->subject = subject;
-	mi->from = from;
-	mi->to = to;
-	mi->cc = cc;
-	mi->mlist = mlist;
-#endif
-
-	mi->content = NULL;
-
-	camel_file_util_decode_fixed_int32(in, &mi->message_id.id.part.hi);
-	camel_file_util_decode_fixed_int32(in, &mi->message_id.id.part.lo);
-
-	if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500)
-		goto error;
-
-	if (count > 0) {
-		mi->references = g_malloc(sizeof(*mi->references) + ((count-1) * sizeof(mi->references->references[0])));
-		mi->references->size = count;
-		for (i=0;ireferences->references[i].id.part.hi);
-			camel_file_util_decode_fixed_int32(in, &mi->references->references[i].id.part.lo);
-		}
-	}
-
-	if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500)
-		goto error;
-
-	for (i=0;iuser_flags, name, TRUE);
-		g_free(name);
-	}
-
-	if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500)
-		goto error;
-
-	for (i=0;iuser_tags, name, value);
-		g_free(name);
-		g_free(value);
-	}
-
-	if (!ferror(in))
-		return mi;
-
-error:
-	camel_folder_summary_info_free(s, mi);
-
-	return NULL;
-}
-
-static int
-message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *mi)
-{
-	guint32 count;
-	CamelFlag *flag;
-	CamelTag *tag;
-	int i;
-
-	io(printf("Saving message info\n"));
-
-	camel_file_util_encode_string(out, camel_message_info_uid(mi));
-	camel_file_util_encode_uint32(out, mi->flags);
-	camel_file_util_encode_uint32(out, mi->size);
-	camel_file_util_encode_time_t(out, mi->date_sent);
-	camel_file_util_encode_time_t(out, mi->date_received);
-	camel_file_util_encode_string(out, camel_message_info_subject(mi));
-	camel_file_util_encode_string(out, camel_message_info_from(mi));
-	camel_file_util_encode_string(out, camel_message_info_to(mi));
-	camel_file_util_encode_string(out, camel_message_info_cc(mi));
-	camel_file_util_encode_string(out, camel_message_info_mlist(mi));
-
-	camel_file_util_encode_fixed_int32(out, mi->message_id.id.part.hi);
-	camel_file_util_encode_fixed_int32(out, mi->message_id.id.part.lo);
-
-	if (mi->references) {
-		camel_file_util_encode_uint32(out, mi->references->size);
-		for (i=0;ireferences->size;i++) {
-			camel_file_util_encode_fixed_int32(out, mi->references->references[i].id.part.hi);
-			camel_file_util_encode_fixed_int32(out, mi->references->references[i].id.part.lo);
-		}
-	} else {
-		camel_file_util_encode_uint32(out, 0);
-	}
-
-	count = camel_flag_list_size(&mi->user_flags);
-	camel_file_util_encode_uint32(out, count);
-	flag = mi->user_flags;
-	while (flag) {
-		camel_file_util_encode_string(out, flag->name);
-		flag = flag->next;
-	}
-
-	count = camel_tag_list_size(&mi->user_tags);
-	camel_file_util_encode_uint32(out, count);
-	tag = mi->user_tags;
-	while (tag) {
-		camel_file_util_encode_string(out, tag->name);
-		camel_file_util_encode_string(out, tag->value);
-		tag = tag->next;
-	}
-
-	return ferror(out);
-}
-
-static void
-message_info_free(CamelFolderSummary *s, CamelMessageInfo *mi)
-{
-#ifdef DOEPOOLV
-	e_poolv_destroy(mi->strings);
-#elif defined (DOESTRV)
-	e_strv_destroy(mi->strings);
-#else
-	g_free(mi->uid);
-	g_free(mi->subject);
-	g_free(mi->from);
-	g_free(mi->to);
-	g_free(mi->cc);
-	g_free(mi->mlist);
-#endif
-	g_free(mi->references);
-	camel_flag_list_free(&mi->user_flags);
-	camel_tag_list_free(&mi->user_tags);
-	e_memchunk_free(s->message_info_chunks, mi);
-}
-
-static CamelMessageContentInfo *
-content_info_new (CamelFolderSummary *s, struct _camel_header_raw *h)
-{
-	CamelMessageContentInfo *ci;
-	const char *charset;
-	
-	ci = camel_folder_summary_content_info_new (s);
-	
-	charset = e_iconv_locale_charset ();
-	ci->id = camel_header_msgid_decode (camel_header_raw_find (&h, "content-id", NULL));
-	ci->description = camel_header_decode_string (camel_header_raw_find (&h, "content-description", NULL), NULL);
-	ci->encoding = camel_content_transfer_encoding_decode (camel_header_raw_find (&h, "content-transfer-encoding", NULL));
-	
-	return ci;
-}
-
-static CamelMessageContentInfo *
-content_info_load(CamelFolderSummary *s, FILE *in)
-{
-	CamelMessageContentInfo *ci;
-	char *type, *subtype;
-	guint32 count, i;
-	CamelContentType *ct;
-
-	io(printf("Loading content info\n"));
-
-	ci = camel_folder_summary_content_info_new(s);
-	
-	camel_folder_summary_decode_token(in, &type);
-	camel_folder_summary_decode_token(in, &subtype);
-	ct = camel_content_type_new(type, subtype);
-	g_free(type);		/* can this be removed? */
-	g_free(subtype);
-	if (camel_file_util_decode_uint32(in, &count) == -1 || count > 500)
-		goto error;
-	
-	for (i=0;itype = ct;
-
-	camel_folder_summary_decode_token(in, &ci->id);
-	camel_folder_summary_decode_token(in, &ci->description);
-	camel_folder_summary_decode_token(in, &ci->encoding);
-
-	camel_file_util_decode_uint32(in, &ci->size);
-
-	ci->childs = NULL;
-
-	if (!ferror(in))
-		return ci;
-
- error:
-	camel_folder_summary_content_info_free(s, ci);
-	return NULL;
-}
-
-static int
-content_info_save(CamelFolderSummary *s, FILE *out, CamelMessageContentInfo *ci)
-{
-	CamelContentType *ct;
-	struct _camel_header_param *hp;
-
-	io(printf("Saving content info\n"));
-
-	ct = ci->type;
-	if (ct) {
-		camel_folder_summary_encode_token(out, ct->type);
-		camel_folder_summary_encode_token(out, ct->subtype);
-		camel_file_util_encode_uint32(out, my_list_size((struct _node **)&ct->params));
-		hp = ct->params;
-		while (hp) {
-			camel_folder_summary_encode_token(out, hp->name);
-			camel_folder_summary_encode_token(out, hp->value);
-			hp = hp->next;
-		}
-	} else {
-		camel_folder_summary_encode_token(out, NULL);
-		camel_folder_summary_encode_token(out, NULL);
-		camel_file_util_encode_uint32(out, 0);
-	}
-	camel_folder_summary_encode_token(out, ci->id);
-	camel_folder_summary_encode_token(out, ci->description);
-	camel_folder_summary_encode_token(out, ci->encoding);
-	return camel_file_util_encode_uint32(out, ci->size);
-}
-
-static void
-content_info_free(CamelFolderSummary *s, CamelMessageContentInfo *ci)
-{
-	camel_content_type_unref(ci->type);
-	g_free(ci->id);
-	g_free(ci->description);
-	g_free(ci->encoding);
-	e_memchunk_free(s->content_info_chunks, ci);
-}
-
-static char *
-next_uid_string(CamelFolderSummary *s)
-{
-	return g_strdup_printf("%u", camel_folder_summary_next_uid(s));
-}
-
-/*
-  OK
-  Now this is where all the "smarts" happen, where the content info is built,
-  and any indexing and what not is performed
-*/
-
-/* must have filter_lock before calling this function */
-static CamelMessageContentInfo *
-summary_build_content_info(CamelFolderSummary *s, CamelMessageInfo *msginfo, CamelMimeParser *mp)
-{
-	int state;
-	size_t len;
-	char *buffer;
-	CamelMessageContentInfo *info = NULL;
-	CamelContentType *ct;
-	int body;
-	int enc_id = -1, chr_id = -1, html_id = -1, idx_id = -1;
-	struct _CamelFolderSummaryPrivate *p = _PRIVATE(s);
-	CamelMimeFilterCharset *mfc;
-	CamelMessageContentInfo *part;
-
-	d(printf("building content info\n"));
-
-	/* start of this part */
-	state = camel_mime_parser_step(mp, &buffer, &len);
-	body = camel_mime_parser_tell(mp);
-
-	if (s->build_content)
-		info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new_from_parser(s, mp);
-
-	switch(state) {
-	case CAMEL_MIME_PARSER_STATE_HEADER:
-		/* check content type for indexing, then read body */
-		ct = camel_mime_parser_content_type(mp);
-		/* update attachments flag as we go */
-		if (!camel_content_type_is(ct, "text", "*"))
-			msginfo->flags |= CAMEL_MESSAGE_ATTACHMENTS;
-
-		if (p->index && camel_content_type_is(ct, "text", "*")) {
-			char *encoding;
-			const char *charset;
-
-			d(printf("generating index:\n"));
-			
-			encoding = camel_content_transfer_encoding_decode(camel_mime_parser_header(mp, "content-transfer-encoding", NULL));
-			if (encoding) {
-				if (!strcasecmp(encoding, "base64")) {
-					d(printf(" decoding base64\n"));
-					if (p->filter_64 == NULL)
-						p->filter_64 = camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_BASE64_DEC);
-					else
-						camel_mime_filter_reset((CamelMimeFilter *)p->filter_64);
-					enc_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_64);
-				} else if (!strcasecmp(encoding, "quoted-printable")) {
-					d(printf(" decoding quoted-printable\n"));
-					if (p->filter_qp == NULL)
-						p->filter_qp = camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_QP_DEC);
-					else
-						camel_mime_filter_reset((CamelMimeFilter *)p->filter_qp);
-					enc_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_qp);
-				} else if (!strcasecmp (encoding, "x-uuencode")) {
-					d(printf(" decoding x-uuencode\n"));
-					if (p->filter_uu == NULL)
-						p->filter_uu = camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_UU_DEC);
-					else
-						camel_mime_filter_reset((CamelMimeFilter *)p->filter_uu);
-					enc_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_uu);
-				} else {
-					d(printf(" ignoring encoding %s\n", encoding));
-				}
-				g_free(encoding);
-			}
-
-			charset = camel_content_type_param(ct, "charset");
-			if (charset!=NULL
-			    && !(strcasecmp(charset, "us-ascii")==0
-				 || strcasecmp(charset, "utf-8")==0)) {
-				d(printf(" Adding conversion filter from %s to UTF-8\n", charset));
-				mfc = g_hash_table_lookup(p->filter_charset, charset);
-				if (mfc == NULL) {
-					mfc = camel_mime_filter_charset_new_convert(charset, "UTF-8");
-					if (mfc)
-						g_hash_table_insert(p->filter_charset, g_strdup(charset), mfc);
-				} else {
-					camel_mime_filter_reset((CamelMimeFilter *)mfc);
-				}
-				if (mfc) {
-					chr_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)mfc);
-				} else {
-					g_warning("Cannot convert '%s' to 'UTF-8', message index may be corrupt", charset);
-				}
-			}
-
-			/* we do charset conversions before this filter, which isn't strictly correct,
-			   but works in most cases */
-			if (camel_content_type_is(ct, "text", "html")) {
-				if (p->filter_html == NULL)
-					p->filter_html = camel_mime_filter_html_new();
-				else
-					camel_mime_filter_reset((CamelMimeFilter *)p->filter_html);
-				html_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_html);
-			}
-			
-			/* and this filter actually does the indexing */
-			idx_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_index);
-		}
-		/* and scan/index everything */
-		while (camel_mime_parser_step(mp, &buffer, &len) != CAMEL_MIME_PARSER_STATE_BODY_END)
-			;
-		/* and remove the filters */
-		camel_mime_parser_filter_remove(mp, enc_id);
-		camel_mime_parser_filter_remove(mp, chr_id);
-		camel_mime_parser_filter_remove(mp, html_id);
-		camel_mime_parser_filter_remove(mp, idx_id);
-		break;
-	case CAMEL_MIME_PARSER_STATE_MULTIPART:
-		d(printf("Summarising multipart\n"));
-		/* update attachments flag as we go */
-		ct = camel_mime_parser_content_type(mp);
-		if (camel_content_type_is(ct, "multipart", "mixed"))
-			msginfo->flags |= CAMEL_MESSAGE_ATTACHMENTS;
-
-		while (camel_mime_parser_step(mp, &buffer, &len) != CAMEL_MIME_PARSER_STATE_MULTIPART_END) {
-			camel_mime_parser_unstep(mp);
-			part = summary_build_content_info(s, msginfo, mp);
-			if (part) {
-				part->parent = info;
-				my_list_append((struct _node **)&info->childs, (struct _node *)part);
-			}
-		}
-		break;
-	case CAMEL_MIME_PARSER_STATE_MESSAGE:
-		d(printf("Summarising message\n"));
-		/* update attachments flag as we go */
-		msginfo->flags |= CAMEL_MESSAGE_ATTACHMENTS;
-
-		part = summary_build_content_info(s, msginfo, mp);
-		if (part) {
-			part->parent = info;
-			my_list_append((struct _node **)&info->childs, (struct _node *)part);
-		}
-		state = camel_mime_parser_step(mp, &buffer, &len);
-		if (state != CAMEL_MIME_PARSER_STATE_MESSAGE_END) {
-			g_error("Bad parser state: Expecing MESSAGE_END or MESSAGE_EOF, got: %d", state);
-			camel_mime_parser_unstep(mp);
-		}
-		break;
-	}
-
-	d(printf("finished building content info\n"));
-
-	return info;
-}
-
-/* build the content-info, from a message */
-/* this needs the filter lock since it uses filters to perform indexing */
-static CamelMessageContentInfo *
-summary_build_content_info_message(CamelFolderSummary *s, CamelMessageInfo *msginfo, CamelMimePart *object)
-{
-	CamelDataWrapper *containee;
-	int parts, i;
-	struct _CamelFolderSummaryPrivate *p = _PRIVATE(s);
-	CamelMessageContentInfo *info = NULL, *child;
-
-	if (s->build_content)
-		info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new_from_message(s, object);
-	
-	containee = camel_medium_get_content_object(CAMEL_MEDIUM(object));
-
-	if (containee == NULL)
-		return info;
-
-	/* TODO: I find it odd that get_part and get_content_object do not
-	   add a reference, probably need fixing for multithreading */
-
-	/* check for attachments */
-	if (camel_content_type_is(CAMEL_DATA_WRAPPER(containee)->mime_type, "multipart", "*")) {
-		if (camel_content_type_is(CAMEL_DATA_WRAPPER(containee)->mime_type, "multipart", "mixed"))
-			msginfo->flags |= CAMEL_MESSAGE_ATTACHMENTS;
-	} else if (!camel_content_type_is(CAMEL_DATA_WRAPPER(containee)->mime_type, "text", "*"))
-		msginfo->flags |= CAMEL_MESSAGE_ATTACHMENTS;
-
-	/* using the object types is more accurate than using the mime/types */
-	if (CAMEL_IS_MULTIPART(containee)) {
-		parts = camel_multipart_get_number(CAMEL_MULTIPART(containee));
-		for (i=0;iparent = info;
-				my_list_append((struct _node **)&info->childs, (struct _node *)child);
-			}
-		}
-	} else if (CAMEL_IS_MIME_MESSAGE(containee)) {
-		/* for messages we only look at its contents */
-		child = summary_build_content_info_message(s, msginfo, (CamelMimePart *)containee);
-		if (child) {
-			child->parent = info;
-			my_list_append((struct _node **)&info->childs, (struct _node *)child);
-		}
-	} else if (p->filter_stream
-		   && camel_content_type_is(CAMEL_DATA_WRAPPER(containee)->mime_type, "text", "*")) {
-		int html_id = -1, idx_id = -1;
-
-		/* pre-attach html filter if required, otherwise just index filter */
-		if (camel_content_type_is(CAMEL_DATA_WRAPPER(containee)->mime_type, "text", "html")) {
-			if (p->filter_html == NULL)
-				p->filter_html = camel_mime_filter_html_new();
-			else
-				camel_mime_filter_reset((CamelMimeFilter *)p->filter_html);
-			html_id = camel_stream_filter_add(p->filter_stream, (CamelMimeFilter *)p->filter_html);
-		}
-		idx_id = camel_stream_filter_add(p->filter_stream, (CamelMimeFilter *)p->filter_index);
-
-		camel_data_wrapper_decode_to_stream(containee, (CamelStream *)p->filter_stream);
-		camel_stream_flush((CamelStream *)p->filter_stream);
-
-		camel_stream_filter_remove(p->filter_stream, idx_id);
-		camel_stream_filter_remove(p->filter_stream, html_id);
-	}
-
-	return info;
-}
-
-/**
- * camel_flag_get:
- * @list: 
- * @name: 
- * 
- * Find the state of the flag @name in @list.
- * 
- * Return value: The state of the flag (TRUE or FALSE).
- **/
-gboolean
-camel_flag_get(CamelFlag **list, const char *name)
-{
-	CamelFlag *flag;
-	flag = *list;
-	while (flag) {
-		if (!strcmp(flag->name, name))
-			return TRUE;
-		flag = flag->next;
-	}
-	return FALSE;
-}
-
-/**
- * camel_flag_set:
- * @list: 
- * @name: 
- * @value: 
- * 
- * Set the state of a flag @name in the list @list to @value.
- *
- * Return value: Whether or not it changed.
- **/
-gboolean
-camel_flag_set(CamelFlag **list, const char *name, gboolean value)
-{
-	CamelFlag *flag, *tmp;
-
-	/* this 'trick' works because flag->next is the first element */
-	flag = (CamelFlag *)list;
-	while (flag->next) {
-		tmp = flag->next;
-		if (!strcmp(flag->next->name, name)) {
-			if (!value) {
-				flag->next = tmp->next;
-				g_free(tmp);
-			}
-			return !value;
-		}
-		flag = tmp;
-	}
-
-	if (value) {
-		tmp = g_malloc(sizeof(*tmp) + strlen(name));
-		strcpy(tmp->name, name);
-		tmp->next = 0;
-		flag->next = tmp;
-	}
-	return value;
-}
-
-/**
- * camel_flag_list_size:
- * @list: 
- * 
- * Get the length of the flag list.
- * 
- * Return value: The number of TRUE flags in the list.
- **/
-int
-camel_flag_list_size(CamelFlag **list)
-{
-	int count=0;
-	CamelFlag *flag;
-
-	flag = *list;
-	while (flag) {
-		count++;
-		flag = flag->next;
-	}
-	return count;
-}
-
-/**
- * camel_flag_list_free:
- * @list: 
- * 
- * Free the memory associated with the flag list @list.
- **/
-void
-camel_flag_list_free(CamelFlag **list)
-{
-	CamelFlag *flag, *tmp;
-	flag = *list;
-	while (flag) {
-		tmp = flag->next;
-		g_free(flag);
-		flag = tmp;
-	}
-	*list = NULL;
-}
-
-/**
- * camel_flag_list_copy:
- * @to: 
- * @from: 
- * 
- * Copy a flag list, return true if the destination list @to changed.
- * 
- * Return value: 
- **/
-gboolean
-camel_flag_list_copy(CamelFlag **to, CamelFlag **from)
-{
-	CamelFlag *flag, *tmp;
-	int changed = FALSE;
-
-	if (*to == NULL && from == NULL)
-		return FALSE;
-
-	/* Remove any now-missing flags */
-	flag = (CamelFlag *)to;
-	while (flag->next) {
-		tmp = flag->next;
-		if (!camel_flag_get(from, tmp->name)) {
-			flag->next = tmp->next;
-			g_free(tmp);
-			changed = TRUE;
-		} else {
-			flag = tmp;
-		}
-	}
-
-	/* Add any new flags */
-	flag = *from;
-	while (flag) {
-		changed |= camel_flag_set(to, flag->name, TRUE);
-		flag = flag->next;
-	}
-
-	return changed;
-}
-
-const char *
-camel_tag_get(CamelTag **list, const char *name)
-{
-	CamelTag *tag;
-
-	tag = *list;
-	while (tag) {
-		if (!strcmp(tag->name, name))
-			return (const char *)tag->value;
-		tag = tag->next;
-	}
-	return NULL;
-}
-
-/**
- * camel_tag_set:
- * @list: 
- * @name: 
- * @value: 
- * 
- * Set the tag @name in the tag list @list to @value.
- *
- * Return value: whether or not it changed
- **/
-gboolean
-camel_tag_set(CamelTag **list, const char *name, const char *value)
-{
-	CamelTag *tag, *tmp;
-
-	/* this 'trick' works because tag->next is the first element */
-	tag = (CamelTag *)list;
-	while (tag->next) {
-		tmp = tag->next;
-		if (!strcmp(tmp->name, name)) {
-			if (value == NULL) { /* clear it? */
-				tag->next = tmp->next;
-				g_free(tmp->value);
-				g_free(tmp);
-				return TRUE;
-			} else if (strcmp(tmp->value, value)) { /* has it changed? */
-				g_free(tmp->value);
-				tmp->value = g_strdup(value);
-				return TRUE;
-			}
-			return FALSE;
-		}
-		tag = tmp;
-	}
-
-	if (value) {
-		tmp = g_malloc(sizeof(*tmp)+strlen(name));
-		strcpy(tmp->name, name);
-		tmp->value = g_strdup(value);
-		tmp->next = 0;
-		tag->next = tmp;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-/**
- * camel_tag_list_size:
- * @list: 
- * 
- * Get the number of tags present in the tag list @list.
- * 
- * Return value: The number of tags.
- **/
-int		camel_tag_list_size(CamelTag **list)
-{
-	int count=0;
-	CamelTag *tag;
-
-	tag = *list;
-	while (tag) {
-		count++;
-		tag = tag->next;
-	}
-	return count;
-}
-
-static void
-rem_tag(char *key, char *value, CamelTag **to)
-{
-	camel_tag_set(to, key, NULL);
-}
-
-/**
- * camel_tag_list_copy:
- * @to: 
- * @from: 
- * 
- * Copy a list of tags.
- * 
- * Return value: 
- **/
-gboolean
-camel_tag_list_copy(CamelTag **to, CamelTag **from)
-{
-	int changed = FALSE;
-	CamelTag *tag;
-	GHashTable *left;
-
-	if (*to == NULL && from == NULL)
-		return FALSE;
-
-	left = g_hash_table_new(g_str_hash, g_str_equal);
-	tag = *to;
-	while (tag) {
-		g_hash_table_insert(left, tag->name, tag);
-		tag = tag->next;
-	}
-
-	tag = *from;
-	while (tag) {
-		changed |= camel_tag_set(to, tag->name, tag->value);
-		g_hash_table_remove(left, tag->name);
-		tag = tag->next;
-	}
-
-	if (g_hash_table_size(left)>0) {
-		g_hash_table_foreach(left, (GHFunc)rem_tag, to);
-		changed = TRUE;
-	}
-	g_hash_table_destroy(left);
-
-	return changed;
-}
-
-/**
- * camel_tag_list_free:
- * @list: 
- * 
- * Free the tag list @list.
- **/
-void		camel_tag_list_free(CamelTag **list)
-{
-	CamelTag *tag, *tmp;
-	tag = *list;
-	while (tag) {
-		tmp = tag->next;
-		g_free(tag->value);
-		g_free(tag);
-		tag = tmp;
-	}
-	*list = NULL;
-}
-
-struct flag_names_t {
-	char *name;
-	guint32 value;
-} flag_names[] = {
-	{ "answered", CAMEL_MESSAGE_ANSWERED },
-	{ "deleted", CAMEL_MESSAGE_DELETED },
-	{ "draft", CAMEL_MESSAGE_DELETED },
-	{ "flagged", CAMEL_MESSAGE_FLAGGED },
-	{ "seen", CAMEL_MESSAGE_SEEN },
-	{ "attachments", CAMEL_MESSAGE_ATTACHMENTS },
-	{ "junk", CAMEL_MESSAGE_JUNK },
-	{ NULL, 0 }
-};
-
-/**
- * camel_system_flag:
- * @name: 
- * 
- * Returns the integer value of the flag string.
- **/
-guint32
-camel_system_flag (const char *name)
-{
-	struct flag_names_t *flag;
-	
-	g_return_val_if_fail (name != NULL, 0);
-	
-	for (flag = flag_names; *flag->name; flag++)
-		if (!strcasecmp (name, flag->name))
-			return flag->value;
-	
-	return 0;
-}
-
-/**
- * camel_system_flag_get:
- * @flags: 
- * @name: 
- * 
- * Find the state of the flag @name in @flags.
- * 
- * Return value: The state of the flag (TRUE or FALSE).
- **/
-gboolean
-camel_system_flag_get (guint32 flags, const char *name)
-{
-	g_return_val_if_fail (name != NULL, FALSE);
-	
-	return flags & camel_system_flag (name);
-}
-
-
-/**
- * camel_message_info_new:
- *
- * Returns a new CamelMessageInfo structure.
- **/
-CamelMessageInfo *
-camel_message_info_new (void)
-{
-	CamelMessageInfo *info;
-	
-	info = g_malloc0(sizeof(*info));
-#ifdef DOEPOOLV
-	info->strings = e_poolv_new(CAMEL_MESSAGE_INFO_LAST);
-#endif
-#ifdef DOESTRV
-	info->strings = e_strv_new (CAMEL_MESSAGE_INFO_LAST);
-#endif
-	info->refcount = 1;
-
-	return info;
-}
-
-/**
- * camel_message_info_ref:
- * @info: 
- * 
- * Reference an info.
- *
- * NOTE: This interface is not MT-SAFE, like the others.
- **/
-void camel_message_info_ref(CamelMessageInfo *info)
-{
-	GLOBAL_INFO_LOCK(info);
-	info->refcount++;
-	GLOBAL_INFO_UNLOCK(info);
-}
-
-/**
- * camel_message_info_new_from_header:
- * @header: raw header
- *
- * Returns a new CamelMessageInfo structure populated by the header.
- **/
-CamelMessageInfo *
-camel_message_info_new_from_header (struct _camel_header_raw *header)
-{
-	CamelMessageInfo *info;
-	char *subject, *from, *to, *cc, *mlist;
-	CamelContentType *ct = NULL;
-	const char *content, *date, *charset = NULL;
-	
-	if ((content = camel_header_raw_find(&header, "Content-Type", NULL))
-	    && (ct = camel_content_type_decode(content))
-	    && (charset = camel_content_type_param(ct, "charset"))
-	    && (strcasecmp(charset, "us-ascii") == 0))
-		charset = NULL;
-	
-	charset = charset ? e_iconv_charset_name (charset) : NULL;
-	
-	subject = summary_format_string(header, "subject", charset);
-	from = summary_format_address(header, "from", charset);
-	to = summary_format_address(header, "to", charset);
-	cc = summary_format_address(header, "cc", charset);
-	date = camel_header_raw_find(&header, "date", NULL);
-	mlist = camel_header_raw_check_mailing_list(&header);
-
-	if (ct)
-		camel_content_type_unref(ct);
-
-	info = camel_message_info_new();
-
-	camel_message_info_set_subject(info, subject);
-	camel_message_info_set_from(info, from);
-	camel_message_info_set_to(info, to);
-	camel_message_info_set_cc(info, cc);
-	camel_message_info_set_mlist(info, mlist);
-	
-	if (date)
-		info->date_sent = camel_header_decode_date (date, NULL);
-	else
-		info->date_sent = time (NULL);
-	
-	date = camel_header_raw_find (&header, "received", NULL);
-	if (date && (date = strrchr (date, ';')))
-		date++;
-	
-	if (date)
-		info->date_received = camel_header_decode_date (date, NULL);
-	else
-		info->date_received = time (NULL);
-	
-	return info;
-}
-
-/**
- * camel_message_info_dup_to:
- * @from: source message info
- * @to: destination message info
- *
- * Duplicates the contents of one CamelMessageInfo structure into another.
- * (The destination is assumed to be empty: its contents are not freed.)
- * The slightly odd interface is to allow this to be used to initialize
- * "subclasses" of CamelMessageInfo.
- **/
-void
-camel_message_info_dup_to(const CamelMessageInfo *from, CamelMessageInfo *to)
-{
-	CamelFlag *flag;
-	CamelTag *tag;
-
-	/* Copy numbers */
-	to->flags = from->flags;
-	to->size = from->size;
-	to->date_sent = from->date_sent;
-	to->date_received = from->date_received;
-	to->refcount = 1;
-
-	/* Copy strings */
-#ifdef DOEPOOLV
-	to->strings = e_poolv_cpy (to->strings, from->strings);
-#elif defined (DOESTRV)
-	/* to->strings = e_strv_new(CAMEL_MESSAGE_INFO_LAST); */
-	e_strv_set(to->strings, CAMEL_MESSAGE_INFO_SUBJECT, camel_message_info_subject(from));
-	e_strv_set(to->strings, CAMEL_MESSAGE_INFO_FROM, camel_message_info_from(from));
-	e_strv_set(to->strings, CAMEL_MESSAGE_INFO_TO, camel_message_info_to(from));
-	e_strv_set(to->strings, CAMEL_MESSAGE_INFO_CC, camel_message_info_cc(from));
-	e_strv_set(to->strings, CAMEL_MESSAGE_INFO_UID, camel_message_info_uid(from));
-	e_strv_set(to->strings, CAMEL_MESSAGE_INFO_UID, camel_message_info_mlist(from));
-#else
-	to->subject = g_strdup(from->subject);
-	to->from = g_strdup(from->from);
-	to->to = g_strdup(from->to);
-	to->cc = g_strdup(from->cc);
-	to->uid = g_strdup(from->uid);
-	to->mlist = g_strdup(from->mlist);
-#endif
-	memcpy(&to->message_id, &from->message_id, sizeof(from->message_id));
-
-	/* Copy structures */
-	if (from->references) {
-		int len = sizeof(*from->references) + ((from->references->size-1) * sizeof(from->references->references[0]));
-
-		to->references = g_malloc(len);
-		memcpy(to->references, from->references, len);
-	} else {
-		to->references = NULL;
-	}
-
-	flag = from->user_flags;
-	while (flag) {
-		camel_flag_set(&to->user_flags, flag->name, TRUE);
-		flag = flag->next;
-	}
-
-	tag = from->user_tags;
-	while (tag) {
-		camel_tag_set(&to->user_tags, tag->name, tag->value);
-		tag = tag->next;
-	}
-
-	/* No, this is impossible without knowing the class of summary we came from */
-	/* FIXME some day */
-	to->content = NULL;
-}
-
-/**
- * camel_message_info_free:
- * @mi: the message info
- *
- * Unref's and potentially frees a CamelMessageInfo and its contents.
- *
- * Can only be used to free CamelMessageInfo's created with
- * camel_message_info_dup_to.
- *
- * NOTE: This interface is not MT-SAFE, like the others.
- *
- **/
-void
-camel_message_info_free(CamelMessageInfo *mi)
-{
-	g_return_if_fail(mi != NULL);
-
-	GLOBAL_INFO_LOCK(info);
-	mi->refcount--;
-	if (mi->refcount > 0) {
-		GLOBAL_INFO_UNLOCK(info);
-		return;
-	}
-	GLOBAL_INFO_UNLOCK(info);
-
-#ifdef DOEPOOLV
-	e_poolv_destroy(mi->strings);
-#elif defined (DOESTRV)
-	e_strv_destroy(mi->strings);
-#else
-	g_free(mi->uid);
-	g_free(mi->subject);
-	g_free(mi->from);
-	g_free(mi->to);
-	g_free(mi->cc);
-	g_free(mi->mlist);
-#endif
-	g_free(mi->references);
-	camel_flag_list_free(&mi->user_flags);
-	camel_tag_list_free(&mi->user_tags);
-	/* FIXME: content info? */
-	g_free(mi);
-}
-
-#if defined (DOEPOOLV) || defined (DOESTRV)
-const char *
-camel_message_info_string (const CamelMessageInfo *mi, int type)
-{
-	g_assert (mi != NULL);
-	
-	if (mi->strings == NULL)
-		return "";
-#ifdef DOEPOOLV
-	return e_poolv_get (mi->strings, type);
-#else
-	return e_strv_get (mi->strings, type);
-#endif
-}
-
-void
-camel_message_info_set_string (CamelMessageInfo *mi, int type, char *str)
-{
-	g_assert (mi != NULL);
-	g_assert (mi->strings != NULL);
-#ifdef DOEPOOLV
-	e_poolv_set (mi->strings, type, str, TRUE);
-#else
-	mi->strings = e_strv_set_ref_free (mi->strings, type, str);
-#endif
-}
-#endif
-
-
-void
-camel_content_info_dump (CamelMessageContentInfo *ci, int depth)
-{
-	char *p;
-	
-	p = alloca (depth * 4 + 1);
-	memset (p, ' ', depth * 4);
-	p[depth * 4] = 0;
-	
-	if (ci == NULL) {
-		printf ("%s\n", p);
-		return;
-	}
-	
-	if (ci->type)
-		printf ("%scontent-type: %s/%s\n", p, ci->type->type ? ci->type->type : "(null)",
-			ci->type->subtype ? ci->type->subtype : "(null)");
-	else
-		printf ("%scontent-type: \n", p);
-	printf ("%scontent-transfer-encoding: %s\n", p, ci->encoding ? ci->encoding : "(null)");
-	printf ("%scontent-description: %s\n", p, ci->description ? ci->description : "(null)");
-	printf ("%ssize: %lu\n", p, (unsigned long) ci->size);
-	ci = ci->childs;
-	while (ci) {
-		camel_content_info_dump (ci, depth + 1);
-		ci = ci->next;
-	}
-}
-
-void
-camel_message_info_dump (CamelMessageInfo *mi)
-{
-	if (mi == NULL) {
-		printf("No message?\n");
-		return;
-	}
-
-	printf("Subject: %s\n", camel_message_info_subject(mi));
-	printf("To: %s\n", camel_message_info_to(mi));
-	printf("Cc: %s\n", camel_message_info_cc(mi));
-	printf("mailing list: %s\n", camel_message_info_mlist(mi));
-	printf("From: %s\n", camel_message_info_from(mi));
-	printf("UID: %s\n", camel_message_info_uid(mi));
-	printf("Flags: %04x\n", mi->flags & 0xffff);
-	camel_content_info_dump(mi->content, 0);
-}
diff --git a/camel/camel-folder-summary.h b/camel/camel-folder-summary.h
deleted file mode 100644
index e57be75ae1..0000000000
--- a/camel/camel-folder-summary.h
+++ /dev/null
@@ -1,350 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Copyright (C) 2000 Ximian Inc.
- *
- *  Authors: Michael Zucchi 
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef _CAMEL_FOLDER_SUMMARY_H
-#define _CAMEL_FOLDER_SUMMARY_H
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#define CAMEL_FOLDER_SUMMARY(obj)         CAMEL_CHECK_CAST (obj, camel_folder_summary_get_type (), CamelFolderSummary)
-#define CAMEL_FOLDER_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_folder_summary_get_type (), CamelFolderSummaryClass)
-#define CAMEL_IS_FOLDER_SUMMARY(obj)      CAMEL_CHECK_TYPE (obj, camel_folder_summary_get_type ())
-
-/*typedef struct _CamelFolderSummary      CamelFolderSummary;*/
-typedef struct _CamelFolderSummaryClass CamelFolderSummaryClass;
-
-/* A tree of message content info structures
-   describe the content structure of the message (if it has any) */
-struct _CamelMessageContentInfo {
-	struct _CamelMessageContentInfo *next;
-	
-	struct _CamelMessageContentInfo *childs;
-	struct _CamelMessageContentInfo *parent;
-	
-	CamelContentType *type;
-	char *id;
-	char *description;
-	char *encoding;		/* this should be an enum?? */
-	guint32 size;
-};
-
-/* system flag bits */
-enum _CamelMessageFlags {
-	CAMEL_MESSAGE_ANSWERED = 1<<0,
-	CAMEL_MESSAGE_DELETED = 1<<1,
-	CAMEL_MESSAGE_DRAFT = 1<<2,
-	CAMEL_MESSAGE_FLAGGED = 1<<3,
-	CAMEL_MESSAGE_SEEN = 1<<4,
-	CAMEL_MESSAGE_ATTACHMENTS = 1<<5,
-	CAMEL_MESSAGE_ANSWERED_ALL = 1<<6,
-	CAMEL_MESSAGE_JUNK = 1<<7,
-
-	/* following flags are for the folder, and are not really permanent flags */
-	CAMEL_MESSAGE_FOLDER_FLAGGED = 1<<16, /* for use by the folder implementation */
-	CAMEL_MESSAGE_USER = 1<<31 /* supports user flags */
-};
-
-typedef struct _CamelFlag {
-	struct _CamelFlag *next;
-	char name[1];		/* name allocated as part of the structure */
-} CamelFlag;
-
-typedef struct _CamelTag {
-	struct _CamelTag *next;
-	char *value;
-	char name[1];		/* name allocated as part of the structure */
-} CamelTag;
-
-/* a summary messageid is a 64 bit identifier (partial md5 hash) */
-typedef struct _CamelSummaryMessageID {
-	union {
-		guint64 id;
-		unsigned char hash[8];
-		struct {
-			guint32 hi;
-			guint32 lo;
-		} part;
-	} id;
-} CamelSummaryMessageID;
-
-/* summary references is a fixed size array of references */
-typedef struct _CamelSummaryReferences {
-	int size;
-	CamelSummaryMessageID references[1];
-} CamelSummaryReferences;
-
-/* #define DOESTRV */
-#define DOEPOOLV
-
-#if defined (DOEPOOLV) || defined (DOESTRV)
-
-/* string array indices */
-enum {
-	CAMEL_MESSAGE_INFO_UID,
-	CAMEL_MESSAGE_INFO_SUBJECT,
-	CAMEL_MESSAGE_INFO_FROM,
-	CAMEL_MESSAGE_INFO_TO,
-	CAMEL_MESSAGE_INFO_CC,
-	CAMEL_MESSAGE_INFO_MLIST,
-	CAMEL_MESSAGE_INFO_LAST,
-};
-#endif
-
-/* information about a given object */
-struct _CamelMessageInfo {
-	/* public fields */
-#ifdef DOEPOOLV
-	struct _EPoolv *strings;
-#elif defined (DOESTRV)
-	struct _EStrv *strings;		/* all strings packed into a single compact array */
-#else
-	char *subject;
-	char *from;
-	char *to;
-	char *cc;
-	char *mlist;
-
-	char *uid;
-#endif /* DOEPOOLV */
-	guint32 flags;
-	guint32 size;
-	guint32 refcount;
-
-	time_t date_sent;
-	time_t date_received;
-
-	CamelSummaryMessageID message_id;/* for this message */
-	CamelSummaryReferences *references;/* from parent to root */
-
-	struct _CamelFlag *user_flags;
-	struct _CamelTag *user_tags;
-
-	/* tree of content description - NULL if it is not available */
-	CamelMessageContentInfo *content;
-};
-
-enum _CamelFolderSummaryFlags {
-	CAMEL_SUMMARY_DIRTY = 1<<0,
-};
-
-struct _CamelFolderSummary {
-	CamelObject parent;
-
-	struct _CamelFolderSummaryPrivate *priv;
-
-	/* header info */
-	guint32 version;	/* version of file required, should be set by implementors */
-	guint32 flags;		/* flags */
-	guint32 nextuid;	/* next uid? */
-	guint32 saved_count;	/* how many were saved/loaded */
-	time_t time;		/* timestamp for this summary (for implementors to use) */
-
-	/* sizes of memory objects */
-	guint32 message_info_size;
-	guint32 content_info_size;
-
-#if defined (DOEPOOLV) || defined (DOESTRV)
-	guint32 message_info_strings;
-#endif	
-	/* memory allocators (setup automatically) */
-	struct _EMemChunk *message_info_chunks;
-	struct _EMemChunk *content_info_chunks;
-
-	char *summary_path;
-	gboolean build_content;	/* do we try and parse/index the content, or not? */
-
-	GPtrArray *messages;	/* CamelMessageInfo's */
-	GHashTable *messages_uid; /* CamelMessageInfo's by uid */
-};
-
-struct _CamelFolderSummaryClass {
-	CamelObjectClass parent_class;
-
-	/* load/save the global info */
-	int (*summary_header_load)(CamelFolderSummary *, FILE *);
-	int (*summary_header_save)(CamelFolderSummary *, FILE *);
-
-	/* create/save/load an individual message info */
-	CamelMessageInfo * (*message_info_new)(CamelFolderSummary *, struct _camel_header_raw *);
-	CamelMessageInfo * (*message_info_new_from_parser)(CamelFolderSummary *, CamelMimeParser *);
-	CamelMessageInfo * (*message_info_new_from_message)(CamelFolderSummary *, CamelMimeMessage *);
-	CamelMessageInfo * (*message_info_load)(CamelFolderSummary *, FILE *);
-	int		   (*message_info_save)(CamelFolderSummary *, FILE *, CamelMessageInfo *);
-	void		   (*message_info_free)(CamelFolderSummary *, CamelMessageInfo *);
-
-	/* save/load individual content info's */
-	CamelMessageContentInfo * (*content_info_new)(CamelFolderSummary *, struct _camel_header_raw *);
-	CamelMessageContentInfo * (*content_info_new_from_parser)(CamelFolderSummary *, CamelMimeParser *);
-	CamelMessageContentInfo * (*content_info_new_from_message)(CamelFolderSummary *, CamelMimePart *);
-	CamelMessageContentInfo * (*content_info_load)(CamelFolderSummary *, FILE *);
-	int		          (*content_info_save)(CamelFolderSummary *, FILE *, CamelMessageContentInfo *);
-	void		          (*content_info_free)(CamelFolderSummary *, CamelMessageContentInfo *);
-
-	/* get the next uid */
-	char *(*next_uid_string)(CamelFolderSummary *);
-};
-
-CamelType			 camel_folder_summary_get_type	(void);
-CamelFolderSummary      *camel_folder_summary_new	(void);
-
-void camel_folder_summary_set_filename(CamelFolderSummary *, const char *);
-void camel_folder_summary_set_index(CamelFolderSummary *, CamelIndex *);
-void camel_folder_summary_set_build_content(CamelFolderSummary *, gboolean state);
-
-guint32  camel_folder_summary_next_uid        (CamelFolderSummary *s);
-char    *camel_folder_summary_next_uid_string (CamelFolderSummary *s);
-void 	 camel_folder_summary_set_uid	      (CamelFolderSummary *s, guint32 uid);
-
-/* load/save the summary in its entirety */
-int camel_folder_summary_load(CamelFolderSummary *);
-int camel_folder_summary_save(CamelFolderSummary *);
-
-/* only load the header */
-int camel_folder_summary_header_load(CamelFolderSummary *);
-
-/* set the dirty bit on the summary */
-void camel_folder_summary_touch(CamelFolderSummary *s);
-
-/* add a new raw summary item */
-void camel_folder_summary_add(CamelFolderSummary *, CamelMessageInfo *info);
-
-/* build/add raw summary items */
-CamelMessageInfo *camel_folder_summary_add_from_header(CamelFolderSummary *, struct _camel_header_raw *);
-CamelMessageInfo *camel_folder_summary_add_from_parser(CamelFolderSummary *, CamelMimeParser *);
-CamelMessageInfo *camel_folder_summary_add_from_message(CamelFolderSummary *, CamelMimeMessage *);
-
-/* Just build raw summary items */
-CamelMessageInfo *camel_folder_summary_info_new(CamelFolderSummary *s);
-CamelMessageInfo *camel_folder_summary_info_new_from_header(CamelFolderSummary *, struct _camel_header_raw *);
-CamelMessageInfo *camel_folder_summary_info_new_from_parser(CamelFolderSummary *, CamelMimeParser *);
-CamelMessageInfo *camel_folder_summary_info_new_from_message(CamelFolderSummary *, CamelMimeMessage *);
-
-void camel_folder_summary_info_ref(CamelFolderSummary *, CamelMessageInfo *);
-void camel_folder_summary_info_free(CamelFolderSummary *, CamelMessageInfo *);
-
-CamelMessageContentInfo *camel_folder_summary_content_info_new(CamelFolderSummary *s);
-void camel_folder_summary_content_info_free(CamelFolderSummary *s, CamelMessageContentInfo *ci);
-
-/* removes a summary item, doesn't fix content offsets */
-void camel_folder_summary_remove(CamelFolderSummary *s, CamelMessageInfo *info);
-void camel_folder_summary_remove_uid(CamelFolderSummary *s, const char *uid);
-void camel_folder_summary_remove_index(CamelFolderSummary *s, int);
-void camel_folder_summary_remove_range(CamelFolderSummary *s, int start, int end);
-/* remove all items */
-void camel_folder_summary_clear(CamelFolderSummary *s);
-
-/* lookup functions */
-int camel_folder_summary_count(CamelFolderSummary *);
-CamelMessageInfo *camel_folder_summary_index(CamelFolderSummary *, int);
-CamelMessageInfo *camel_folder_summary_uid(CamelFolderSummary *, const char *uid);
-GPtrArray *camel_folder_summary_array(CamelFolderSummary *s);
-void camel_folder_summary_array_free(CamelFolderSummary *s, GPtrArray *array);
-
-/* summary formatting utils */
-char *camel_folder_summary_format_address(struct _camel_header_raw *h, const char *name);
-char *camel_folder_summary_format_string(struct _camel_header_raw *h, const char *name);
-
-/* basically like strings, but certain keywords can be compressed and de-cased */
-int camel_folder_summary_encode_token(FILE *, const char *);
-int camel_folder_summary_decode_token(FILE *, char **);
-
-/* message flag operations */
-gboolean	camel_flag_get(CamelFlag **list, const char *name);
-gboolean	camel_flag_set(CamelFlag **list, const char *name, gboolean state);
-gboolean	camel_flag_list_copy(CamelFlag **to, CamelFlag **from);
-int		camel_flag_list_size(CamelFlag **list);
-void		camel_flag_list_free(CamelFlag **list);
-
-guint32         camel_system_flag (const char *name);
-gboolean        camel_system_flag_get (guint32 flags, const char *name);
-
-/* message tag operations */
-const char	*camel_tag_get(CamelTag **list, const char *name);
-gboolean	camel_tag_set(CamelTag **list, const char *name, const char *value);
-gboolean	camel_tag_list_copy(CamelTag **to, CamelTag **from);
-int		camel_tag_list_size(CamelTag **list);
-void		camel_tag_list_free(CamelTag **list);
-
-/* message info utils for working with pseudo-messageinfo structures
-   NOTE: These cannot be added to a real summary object, but suffice for all
-   other external interfaces that use message info's */
-CamelMessageInfo *camel_message_info_new(void);
-void camel_message_info_ref(CamelMessageInfo *info);
-CamelMessageInfo *camel_message_info_new_from_header(struct _camel_header_raw *header);
-void camel_message_info_dup_to(const CamelMessageInfo *from, CamelMessageInfo *to);
-void camel_message_info_free(CamelMessageInfo *mi);
-
-/* accessors */
-#if defined (DOEPOOLV) || defined (DOESTRV)
-const char *camel_message_info_string(const CamelMessageInfo *mi, int type);
-#define camel_message_info_subject(x) camel_message_info_string((const CamelMessageInfo *)(x), CAMEL_MESSAGE_INFO_SUBJECT)
-#define camel_message_info_from(x) camel_message_info_string((const CamelMessageInfo *)(x), CAMEL_MESSAGE_INFO_FROM)
-#define camel_message_info_to(x) camel_message_info_string((const CamelMessageInfo *)(x), CAMEL_MESSAGE_INFO_TO)
-#define camel_message_info_cc(x) camel_message_info_string((const CamelMessageInfo *)(x), CAMEL_MESSAGE_INFO_CC)
-#define camel_message_info_uid(x) camel_message_info_string((const CamelMessageInfo *)(x), CAMEL_MESSAGE_INFO_UID)
-#define camel_message_info_mlist(x) camel_message_info_string((const CamelMessageInfo *)(x), CAMEL_MESSAGE_INFO_MLIST)
-
-void camel_message_info_set_string(CamelMessageInfo *mi, int type, char *str);
-#define camel_message_info_set_subject(x, s) camel_message_info_set_string(x, CAMEL_MESSAGE_INFO_SUBJECT, s)
-#define camel_message_info_set_from(x, s) camel_message_info_set_string(x, CAMEL_MESSAGE_INFO_FROM, s)
-#define camel_message_info_set_to(x, s) camel_message_info_set_string(x, CAMEL_MESSAGE_INFO_TO, s)
-#define camel_message_info_set_cc(x, s) camel_message_info_set_string(x, CAMEL_MESSAGE_INFO_CC, s)
-#define camel_message_info_set_uid(x, s) camel_message_info_set_string(x, CAMEL_MESSAGE_INFO_UID, s)
-#define camel_message_info_set_mlist(x, s) camel_message_info_set_string(x, CAMEL_MESSAGE_INFO_MLIST, s)
-
-#else
-
-#define camel_message_info_subject(x) (((CamelMessageInfo *)(x))->subject?((CamelMessageInfo *)(x))->subject:"")
-#define camel_message_info_from(x) (((CamelMessageInfo *)(x))->from?((CamelMessageInfo *)(x))->from:"")
-#define camel_message_info_to(x) (((CamelMessageInfo *)(x))->to?((CamelMessageInfo *)(x))->to:"")
-#define camel_message_info_cc(x) (((CamelMessageInfo *)(x))->cc?((CamelMessageInfo *)(x))->cc:"")
-#define camel_message_info_uid(x) (((CamelMessageInfo *)(x))->uid?((CamelMessageInfo *)(x))->uid:"")
-#define camel_message_info_mlist(x) (((CamelMessageInfo *)(x))->mlist?((CamelMessageInfo *)(x))->mlist:"")
-
-#define camel_message_info_set_subject(x, s) (g_free(((CamelMessageInfo *)(x))->subject),((CamelMessageInfo *)(x))->subject = (s))
-#define camel_message_info_set_from(x, s) (g_free(((CamelMessageInfo *)(x))->from),((CamelMessageInfo *)(x))->from = (s))
-#define camel_message_info_set_to(x, s) (g_free(((CamelMessageInfo *)(x))->to),((CamelMessageInfo *)(x))->to = (s))
-#define camel_message_info_set_cc(x, s) (g_free(((CamelMessageInfo *)(x))->cc),((CamelMessageInfo *)(x))->cc = (s))
-#define camel_message_info_set_uid(x, s) (g_free(((CamelMessageInfo *)(x))->uid),((CamelMessageInfo *)(x))->uid = (s))
-#define camel_message_info_set_mlist(x, s) (g_free(((CamelMessageInfo *)(x))->mlist),((CamelMessageInfo *)(x))->mlist = (s))
-#endif
-
-
-/* debugging functions */
-
-void camel_content_info_dump (CamelMessageContentInfo *ci, int depth);
-
-void camel_message_info_dump (CamelMessageInfo *mi);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* ! _CAMEL_FOLDER_SUMMARY_H */
diff --git a/camel/camel-folder-thread.c b/camel/camel-folder-thread.c
deleted file mode 100644
index a67ab5d5b2..0000000000
--- a/camel/camel-folder-thread.c
+++ /dev/null
@@ -1,861 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Copyright (C) 2000 Ximian Inc.
- *
- *  Authors: Michael Zucchi 
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/* TODO: This could probably be made a camel object, but it isn't really required */
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "camel-folder-thread.h"
-#include "e-util/e-memory.h"
-
-#define d(x)
-
-/*#define TIMEIT*/
-
-#ifdef TIMEIT
-#include 
-#include 
-#endif
-
-static void
-container_add_child(CamelFolderThreadNode *node, CamelFolderThreadNode *child)
-{
-	d(printf("\nAdding child %p to parent %p \n", child, node));
-	child->next = node->child;
-	node->child = child;
-	child->parent = node;
-}
-
-static void
-container_parent_child(CamelFolderThreadNode *parent, CamelFolderThreadNode *child)
-{
-	CamelFolderThreadNode *c, *node;
-
-	/* are we already the right parent? */
-	if (child->parent == parent)
-		return;
-
-	/* would this create a loop? */
-	node = parent->parent;
-	while (node) {
-		if (node == child)
-			return;
-		node = node->parent;
-	}
-
-	/* are we unparented? */
-	if (child->parent == NULL) {
-		container_add_child(parent, child);
-		return;
-	}
-
-	/* else remove child from its existing parent, and reparent */
-	node = child->parent;
-	c = (CamelFolderThreadNode *)&node->child;
-	d(printf("scanning children:\n"));
-	while (c->next) {
-		d(printf(" %p\n", c));
-	        if (c->next==child) {
-			d(printf("found node %p\n", child));
-			c->next = c->next->next;
-			child->parent = NULL;
-			container_add_child(parent, child);
-			return;
-		}
-		c = c->next;
-	}
-
-	printf("DAMN, we shouldn't  be here!\n");
-}
-
-static void
-prune_empty(CamelFolderThread *thread, CamelFolderThreadNode **cp)
-{
-	CamelFolderThreadNode *child, *next, *c, *lastc;
-
-	/* yes, this is intentional */
-	lastc = (CamelFolderThreadNode *)cp;
-	while (lastc->next) {
-		c = lastc->next;
-
-		d(printf("checking message %p %p (%08x%08x)\n", c,
-			 c->message, c->message?c->message->message_id.id.part.hi:0,
-			 c->message?c->message->message_id.id.part.lo:0));
-		if (c->message == NULL) {
-			if (c->child == NULL) {
-				d(printf("removing empty node\n"));
-				lastc->next = c->next;
-				e_memchunk_free(thread->node_chunks, c);
-				continue;
-			}
-			if (c->parent || c->child->next==0) {
-				d(printf("promoting child\n"));
-				lastc->next = c->next; /* remove us */
-				child = c->child;
-				while (child) {
-					next = child->next;
-
-					child->parent = c->parent;
-					child->next = lastc->next;
-					lastc->next = child;
-
-					child = next;
-				}
-				continue;
-			}
-		}
-		prune_empty(thread, &c->child);
-		lastc = c;
-	}
-}
-
-static void
-hashloop(void *key, void *value, void *data)
-{
-	CamelFolderThreadNode *c = value;
-	CamelFolderThreadNode *tail = data;
-
-	if (c->parent == NULL) {
-		c->next = tail->next;
-		tail->next = c;
-	}
-}
-
-static char *
-get_root_subject(CamelFolderThreadNode *c, int *re)
-{
-	char *s, *p;
-	CamelFolderThreadNode *scan;
-	
-	s = NULL;
-	*re = FALSE;
-	if (c->message)
-		s = (char *)camel_message_info_subject(c->message);
-	else {
-		/* one of the children will always have a message */
-		scan = c->child;
-		while (scan) {
-			if (scan->message) {
-				s = (char *)camel_message_info_subject(scan->message);
-				break;
-			}
-			scan = scan->next;
-		}
-	}
-	if (s != NULL) {
-		while (*s) {
-			while (isspace(*s))
-				s++;
-			if (s[0] == 0)
-				break;
-			if ((s[0] == 'r' || s[0]=='R')
-			    && (s[1] == 'e' || s[1]=='E')) {
-				p = s+2;
-				while (isdigit(*p) || (ispunct(*p) && (*p != ':')))
-					p++;
-				if (*p==':') {
-					*re = TRUE;
-					s = p+1;
-				} else
-					break;
-			} else
-				break;
-		}
-		if (*s)
-			return s;
-	}
-	return NULL;
-}
-
-/* this can be pretty slow, but not used often */
-/* clast cannot be null */
-static void
-remove_node(CamelFolderThreadNode **list, CamelFolderThreadNode *node, CamelFolderThreadNode **clast)
-{
-	CamelFolderThreadNode *c;
-
-	/* this is intentional, even if it looks funny */
-	/* if we have a parent, then we should remove it from the parent list,
-	   otherwise we remove it from the root list */
-	if (node->parent) {
-		c = (CamelFolderThreadNode *)&node->parent->child;
-	} else {
-		c = (CamelFolderThreadNode *)list;
-	}
-	while (c->next) {
-		if (c->next == node) {
-			if (*clast == c->next)
-				*clast = c;
-			c->next = c->next->next;
-			return;
-		}
-		c = c->next;
-	}
-
-	printf("ERROR: removing node %p failed\n", node);
-}
-
-static void
-group_root_set(CamelFolderThread *thread, CamelFolderThreadNode **cp)
-{
-	GHashTable *subject_table = g_hash_table_new(g_str_hash, g_str_equal);
-	CamelFolderThreadNode *c, *clast, *scan, *container;
-
-	/* gather subject lines */ 
-	d(printf("gathering subject lines\n"));
-	clast = (CamelFolderThreadNode *)cp;
-	c = clast->next;
-	while (c) {
-		c->root_subject = get_root_subject(c, &c->re);
-		if (c->root_subject) {
-			container = g_hash_table_lookup(subject_table, c->root_subject);
-			if (container == NULL
-			    || (container->message == NULL && c->message)
-			    || (container->re == TRUE && !c->re)) {
-				g_hash_table_insert(subject_table, c->root_subject, c);
-			}
-		}
-		c = c->next;
-	}
-
-	/* merge common subjects? */
-	clast = (CamelFolderThreadNode *)cp;
-	while (clast->next) {
-		c = clast->next;
-		d(printf("checking %p %s\n", c, c->root_subject));
-		if (c->root_subject
-		    && (container = g_hash_table_lookup(subject_table, c->root_subject))
-		    && (container != c)) {
-			d(printf(" matching %p %s\n", container, container->root_subject));
-			if (c->message == NULL && container->message == NULL) {
-				d(printf("merge containers children\n"));
-				/* steal the children from c onto container, and unlink c */
-				scan = (CamelFolderThreadNode *)&container->child;
-				while (scan->next)
-					scan = scan->next;
-				scan->next = c->child;
-				clast->next = c->next;
-				e_memchunk_free(thread->node_chunks, c);
-				continue;
-			} if (c->message == NULL && container->message != NULL) {
-				d(printf("container is non-empty parent\n"));
-				remove_node(cp, container, &clast);
-				container_add_child(c, container);
-			} else if (c->message != NULL && container->message == NULL) {
-				d(printf("container is empty child\n"));
-				clast->next = c->next;
-				container_add_child(container, c);
-				continue;
-			} else if (c->re && !container->re) {
-				d(printf("container is re\n"));
-				clast->next = c->next;
-				container_add_child(container, c);
-				continue;
-			} else if (!c->re && container->re) {
-				d(printf("container is not re\n"));
-				remove_node(cp, container, &clast);
-				container_add_child(c, container);
-			} else if (c->re && container->re) {
-				d(printf("subjects are common %p and %p\n", c, container));
-
-				/* build a phantom node */
-				remove_node(cp, container, &clast);
-				remove_node(cp, c, &clast);
-
-				scan = e_memchunk_alloc0(thread->node_chunks);
-
-				scan->root_subject = c->root_subject;
-				scan->re = c->re && container->re;
-				scan->next = c->next;
-				clast->next = scan;
-				container_add_child(scan, c);
-				container_add_child(scan, container);
-				clast = scan;
-				g_hash_table_insert(subject_table, scan->root_subject, scan);
-				continue;
-			}
-		}
-		clast = c;
-	}
-	g_hash_table_destroy(subject_table);
-}
-
-struct _tree_info {
-	GHashTable *visited;
-};
-
-static int
-dump_tree_rec(struct _tree_info *info, CamelFolderThreadNode *c, int depth)
-{
-	char *p;
-	int count=0;
-
-	p = alloca(depth*2+1);
-	memset(p, ' ', depth*2);
-	p[depth*2] = 0;
-
-	while (c) {
-		if (g_hash_table_lookup(info->visited, c)) {
-			printf("WARNING: NODE REVISITED: %p\n", c);
-		} else {
-			g_hash_table_insert(info->visited, c, c);
-		}
-		if (c->message) {
-			printf("%s %p Subject: %s <%.8s>\n", p, c, camel_message_info_subject(c->message), c->message->message_id.id.hash);
-			count += 1;
-		} else {
-			printf("%s %p \n", p, c);
-		}
-		if (c->child)
-			count += dump_tree_rec(info, c->child, depth+1);
-		c = c->next;
-	}
-	return count;
-}
-
-int
-camel_folder_threaded_messages_dump(CamelFolderThreadNode *c)
-{
-	int count;
-	struct _tree_info info;
-
-	info.visited = g_hash_table_new(g_direct_hash, g_direct_equal);
-	count = dump_tree_rec(&info, c, 0);
-	g_hash_table_destroy(info.visited);
-	return count;
-}
-
-static int
-sort_node(const void *a, const void *b)
-{
-	const CamelFolderThreadNode *a1 = ((CamelFolderThreadNode **)a)[0];
-	const CamelFolderThreadNode *b1 = ((CamelFolderThreadNode **)b)[0];
-
-	/* if we have no message, it must be a dummy node, which 
-	   also means it must have a child, just use that as the
-	   sort data (close enough?) */
-	if (a1->message == NULL)
-		a1 = a1->child;
-	if (b1->message == NULL)
-		b1 = b1->child;
-	if (a1->order == b1->order)
-		return 0;
-	if (a1->order < b1->order)
-		return -1;
-	else
-		return 1;
-}
-
-static void
-sort_thread(CamelFolderThreadNode **cp)
-{
-	CamelFolderThreadNode *c, *head, **carray;
-	int size=0;
-
-	c = *cp;
-	while (c) {
-		/* sort the children while we're at it */
-		if (c->child)
-			sort_thread(&c->child);
-		size++;
-		c = c->next;
-	}
-	if (size<2)
-		return;
-	carray = alloca(size*sizeof(CamelFolderThreadNode *));
-	c = *cp;
-	size=0;
-	while (c) {
-		carray[size] = c;
-		c = c->next;
-		size++;
-	}
-	qsort(carray, size, sizeof(CamelFolderThreadNode *), sort_node);
-	size--;
-	head = carray[size];
-	head->next = NULL;
-	size--;
-	do {
-		c = carray[size];
-		c->next = head;
-		head = c;
-		size--;
-	} while (size>=0);
-	*cp = head;
-}
-
-static guint id_hash(void *key)
-{
-	CamelSummaryMessageID *id = (CamelSummaryMessageID *)key;
-
-	return id->id.part.lo;
-}
-
-static gint id_equal(void *a, void *b)
-{
-	return ((CamelSummaryMessageID *)a)->id.id == ((CamelSummaryMessageID *)b)->id.id;
-}
-
-/* perform actual threading */
-static void
-thread_summary(CamelFolderThread *thread, GPtrArray *summary)
-{
-	GHashTable *id_table, *no_id_table;
-	int i;
-	CamelFolderThreadNode *c, *child, *head;
-#ifdef TIMEIT
-	struct timeval start, end;
-	unsigned long diff;
-
-	gettimeofday(&start, NULL);
-#endif
-
-	id_table = g_hash_table_new((GHashFunc)id_hash, (GCompareFunc)id_equal);
-	no_id_table = g_hash_table_new(NULL, NULL);
-	for (i=0;ilen;i++) {
-		CamelMessageInfo *mi = summary->pdata[i];
-
-		if (mi->message_id.id.id) {
-			c = g_hash_table_lookup(id_table, &mi->message_id);
-			/* check for duplicate messages */
-			if (c && c->order) {
-				/* if duplicate, just make out it is a no-id message,  but try and insert it
-				   into the right spot in the tree */
-				d(printf("doing: (duplicate message id)\n"));
-				c = e_memchunk_alloc0(thread->node_chunks);
-				g_hash_table_insert(no_id_table, (void *)mi, c);
-			} else if (!c) {
-				d(printf("doing : %08x%08x (%s)\n", mi->message_id.id.part.hi, mi->message_id.id.part.lo, camel_message_info_subject(mi)));
-				c = e_memchunk_alloc0(thread->node_chunks);
-				g_hash_table_insert(id_table, (void *)&mi->message_id, c);
-			}
-		} else {
-			d(printf("doing : (no message id)\n"));
-			c = e_memchunk_alloc0(thread->node_chunks);
-			g_hash_table_insert(no_id_table, (void *)mi, c);
-		}
-
-		c->message = mi;
-		c->order = i+1;
-		child = c;
-		if (mi->references) {
-			int j;
-
-			d(printf("references:\n"));
-			for (j=0;jreferences->size;j++) {
-				/* should never be empty, but just incase */
-				if (mi->references->references[j].id.id == 0)
-					continue;
-
-				c = g_hash_table_lookup(id_table, &mi->references->references[j]);
-				if (c == NULL) {
-					d(printf("not found\n"));
-					c = e_memchunk_alloc0(thread->node_chunks);
-					g_hash_table_insert(id_table, &mi->references->references[j], c);
-				}
-				if (c!=child)
-					container_parent_child(c, child);
-				child = c;
-			}
-		}
-	}
-
-	d(printf("\n\n"));
-	/* build a list of root messages (no parent) */
-	head = NULL;
-	g_hash_table_foreach(id_table, hashloop, &head);
-	g_hash_table_foreach(no_id_table, hashloop, &head);
-
-	g_hash_table_destroy(id_table);
-	g_hash_table_destroy(no_id_table);
-
-	/* remove empty parent nodes */
-	prune_empty(thread, &head);
-	
-	/* find any siblings which missed out - but only if we are allowing threading by subject */
-	if (thread->subject)
-		group_root_set (thread, &head);
-
-#if 0
-	printf("finished\n");
-	i = camel_folder_thread_messages_dump(head);
-	printf("%d count, %d items in tree\n", uids->len, i);
-#endif
-
-	sort_thread(&head);
-
-	/* remove any phantom nodes, this could possibly be put in group_root_set()? */
-	c = (CamelFolderThreadNode *)&head;
-	while (c && c->next) {
-		CamelFolderThreadNode *scan, *newtop;
-
-		child = c->next;
-		if (child->message == NULL) {
-			newtop = child->child;
-			/* unlink pseudo node */
-			c->next = newtop;
-
-			/* link its siblings onto the end of its children */
-			scan = (CamelFolderThreadNode *)&newtop->child;
-			while (scan->next)
-				scan = scan->next;
-			scan->next = newtop->next;
-			/* and link the now 'real' node into the list */
-			newtop->next = child->next;
-			c = newtop;
-			e_memchunk_free(thread->node_chunks, child);
-		} else {
-			c = child;
-		}
-	}
-
-	/* this is only debug assertion stuff */
-	c = (CamelFolderThreadNode *)&head;
-	while (c->next) {
-		c = c->next;
-		if (c->message == NULL)
-			g_warning("threading missed removing a pseudo node: %s\n", c->root_subject);
-	}
-
-	thread->tree = head;
-
-#ifdef TIMEIT
-	gettimeofday(&end, NULL);
-	diff = end.tv_sec * 1000 + end.tv_usec/1000;
-	diff -= start.tv_sec * 1000 + start.tv_usec/1000;
-	printf("Message threading %d messages took %ld.%03ld seconds\n",
-	       summary->len, diff / 1000, diff % 1000);
-#endif
-}
-
-/**
- * camel_folder_thread_messages_new:
- * @folder: 
- * @uids: The subset of uid's to thread.  If NULL. then thread all
- * uid's in @folder.
- * @thread_subject: thread based on subject also
- * 
- * Thread a (subset) of the messages in a folder.  And sort the result
- * in summary order.
- *
- * If @thread_subject is %TRUE, messages with
- * related subjects will also be threaded. The default behaviour is to
- * only thread based on message-id.
- * 
- * This function is probably to be removed soon.
- *
- * Return value: A CamelFolderThread contianing a tree of CamelFolderThreadNode's
- * which represent the threaded structure of the messages.
- **/
-CamelFolderThread *
-camel_folder_thread_messages_new (CamelFolder *folder, GPtrArray *uids, gboolean thread_subject)
-{
-	CamelFolderThread *thread;
-	GHashTable *wanted = NULL;
-	GPtrArray *summary;
-	GPtrArray *fsummary;
-	int i;
-
-	thread = g_malloc(sizeof(*thread));
-	thread->refcount = 1;
-	thread->subject = thread_subject;
-	thread->tree = NULL;
-	thread->node_chunks = e_memchunk_new(32, sizeof(CamelFolderThreadNode));
-	thread->folder = folder;
-	camel_object_ref((CamelObject *)folder);
-
-	/* get all of the summary items of interest in summary order */
-	if (uids) {
-		wanted = g_hash_table_new(g_str_hash, g_str_equal);
-		for (i=0;ilen;i++)
-			g_hash_table_insert(wanted, uids->pdata[i], uids->pdata[i]);
-	}
-
-	fsummary = camel_folder_get_summary(folder);
-	thread->summary = summary = g_ptr_array_new();
-
-	for (i=0;ilen;i++) {
-		CamelMessageInfo *info = fsummary->pdata[i];
-
-		if (wanted == NULL || g_hash_table_lookup(wanted, camel_message_info_uid(info)) != NULL) {
-			camel_folder_ref_message_info(folder, info);
-			g_ptr_array_add(summary, info);
-		}
-	}
-
-	camel_folder_free_summary(folder, fsummary);
-
-	thread_summary(thread, summary);
-
-	g_hash_table_destroy(wanted);
-
-	return thread;
-}
-
-/* add any still there, in the existing order */
-static void
-add_present_rec(CamelFolderThread *thread, GHashTable *have, GPtrArray *summary, CamelFolderThreadNode *node)
-{
-	while (node) {
-		const char *uid = camel_message_info_uid(node->message);
-
-		if (g_hash_table_lookup(have, (char *)uid)) {
-			g_hash_table_remove(have, (char *)camel_message_info_uid(node->message));
-			g_ptr_array_add(summary, (void *) node->message);
-		} else {
-			camel_folder_free_message_info(thread->folder, (CamelMessageInfo *)node->message);
-		}
-
-		if (node->child)
-			add_present_rec(thread, have, summary, node->child);
-		node = node->next;
-	}
-}
-
-void
-camel_folder_thread_messages_apply(CamelFolderThread *thread, GPtrArray *uids)
-{
-	int i;
-	GPtrArray *all;
-	GHashTable *table;
-	CamelMessageInfo *info;
-
-	all = g_ptr_array_new();
-	table = g_hash_table_new(g_str_hash, g_str_equal);
-	for (i=0;ilen;i++)
-		g_hash_table_insert(table, uids->pdata[i], uids->pdata[i]);
-
-	add_present_rec(thread, table, all, thread->tree);
-
-	/* add any new ones, in supplied order */
-	for (i=0;ilen;i++)
-		if (g_hash_table_lookup(table, uids->pdata[i]) && (info = camel_folder_get_message_info(thread->folder, uids->pdata[i])))
-			g_ptr_array_add(all, info);
-
-	g_hash_table_destroy(table);
-
-	thread->tree = NULL;
-	e_memchunk_destroy(thread->node_chunks);
-	thread->node_chunks = e_memchunk_new(32, sizeof(CamelFolderThreadNode));
-	thread_summary(thread, all);
-
-	g_ptr_array_free(thread->summary, TRUE);
-	thread->summary = all;
-}
-
-void
-camel_folder_thread_messages_ref(CamelFolderThread *thread)
-{
-	thread->refcount++;
-}
-
-/**
- * camel_folder_thread_messages_unref:
- * @thread: 
- * 
- * Free all memory associated with the thread descriptor @thread.
- **/
-void
-camel_folder_thread_messages_unref(CamelFolderThread *thread)
-{
-	if (thread->refcount > 1) {
-		thread->refcount--;
-		return;
-	}
-
-	if (thread->folder) {
-		int i;
-
-		for (i=0;isummary->len;i++)
-			camel_folder_free_message_info(thread->folder, thread->summary->pdata[i]);
-		g_ptr_array_free(thread->summary, TRUE);
-		camel_object_unref((CamelObject *)thread->folder);
-	}
-	e_memchunk_destroy(thread->node_chunks);
-	g_free(thread);
-}
-
-#if 0
-/**
- * camel_folder_thread_messages_new_summary:
- * @summary: Array of CamelMessageInfo's to thread.
- * 
- * Thread a list of MessageInfo's.  The summary must remain valid for the
- * life of the CamelFolderThread created by this function, and it is upto the
- * caller to ensure this.
- * 
- * Return value: A CamelFolderThread contianing a tree of CamelFolderThreadNode's
- * which represent the threaded structure of the messages.
- **/
-CamelFolderThread *
-camel_folder_thread_messages_new_summary(GPtrArray *summary)
-{
-	CamelFolderThread *thread;
-
-#ifdef TIMEIT
-	struct timeval start, end;
-	unsigned long diff;
-
-	gettimeofday(&start, NULL);
-#endif
-
-	thread = g_malloc(sizeof(*thread));
-	thread->refcount = 1;
-	thread->tree = NULL;
-	thread->node_chunks = e_memchunk_new(32, sizeof(CamelFolderThreadNode));
-	thread->folder = NULL;
-	thread->summary = NULL;
-
-	thread_summary(thread, summary);
-
-	return thread;
-}
-
-/* scan the list in depth-first fashion */
-static void
-build_summary_rec(GHashTable *have, GPtrArray *summary, CamelFolderThreadNode *node)
-{
-	while (node) {
-		if (node->message)
-			g_hash_table_insert(have, (char *)camel_message_info_uid(node->message), node->message);
-		g_ptr_array_add(summary, node);
-		if (node->child)
-			build_summary_rec(have, summary, node->child);
-		node = node->next;
-	}
-}
-
-void
-camel_folder_thread_messages_add(CamelFolderThread *thread, GPtrArray *summary)
-{
-	GPtrArray *all;
-	int i;
-	GHashTable *table;
-
-	/* Instead of working out all the complex in's and out's of
-	   trying to do an incremental summary generation, just redo the whole
-	   thing with the summary in the current order - so it comes out
-	   in the same order */
-
-	all = g_ptr_array_new();
-	table = g_hash_table_new(g_str_hash, g_str_equal);
-	build_summary_rec(table, all, thread->tree);
-	for (i=0;ilen;i++) {
-		CamelMessageInfo *info = summary->pdata[i];
-
-		/* check its not already there, we dont want duplicates */
-		if (g_hash_table_lookup(table, camel_message_info_uid(info)) == NULL)
-			g_ptr_array_add(all, info);
-	}
-	g_hash_table_destroy(table);
-
-	/* reset the tree, and rebuild fully */
-	thread->tree = NULL;
-	e_memchunk_empty(thread->node_chunks);
-	thread_summary(thread, all);
-}
-
-static void
-remove_uid_node_rec(CamelFolderThread *thread, GHashTable *table, CamelFolderThreadNode **list, CamelFolderThreadNode *parent)
-{
-	CamelFolderThreadNode *prev = NULL;
-	CamelFolderThreadNode *node, *next, *child, *rest;
-
-	node = (CamelFolderThreadNode *)list;
-	next = node->next;
-	while (next) {
-
-		if (next->child)
-			remove_uid_node_rec(thread, table, &next->child, next);
-
-		/* do we have a node to remove? */
-		if (next->message && g_hash_table_lookup(table, (char *)camel_message_info_uid(node->message))) {
-			child = next->child;
-			if (child) {
-				/*
-				  node
-				  next
-				   child
-				   lchild
-				  rest
-
-				  becomes:
-				  node
-				  child
-				  lchild
-				  rest
-				*/
-
-				rest = next->next;
-				node->next = child;
-				e_memchunk_free(thread->node_chunks, next);
-				next = child;
-				do {
-					lchild = child;
-					child->parent = parent;
-					child = child->next;
-				} while (child);
-				lchild->next = rest;
-			} else {
-				/*
-				  node
-				  next
-				  rest
-				  becomes:
-				  node
-				  rest */
-				node->next = next->next;
-				e_memchunk_free(thread->node_chunks, next);
-				next = node->next;
-			}
-		} else {
-			node = next;
-			next = node->next;
-		}
-	}
-}
-
-void
-camel_folder_thread_messages_remove(CamelFolderThread *thread, GPtrArray *uids)
-{
-	GHashTable *table;
-	int i;
-
-	table = g_hash_table_new(g_str_hash, g_str_equal);
-	for (i=0;ilen;i++)
-		g_hash_table_insert(table, uids->pdata[i], uids->pdata[i]);
-
-	remove_uid_node_rec(thread, table, &thread->tree, NULL);
-	g_hash_table_destroy(table);
-}
-
-#endif
diff --git a/camel/camel-folder-thread.h b/camel/camel-folder-thread.h
deleted file mode 100644
index 8bb78e27a0..0000000000
--- a/camel/camel-folder-thread.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Copyright (C) 2000 Ximian Inc.
- *
- *  Authors: Michael Zucchi 
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef _CAMEL_FOLDER_THREAD_H
-#define _CAMEL_FOLDER_THREAD_H
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include 
-#include 
-
-typedef struct _CamelFolderThreadNode {
-	struct _CamelFolderThreadNode *next,
-		*parent,
-		*child;
-	const CamelMessageInfo *message;
-	char *root_subject;	/* cached root equivalent subject */
-	int re;			/* re version of subject? */
-	int order;
-} CamelFolderThreadNode;
-
-typedef struct _CamelFolderThread {
-	guint32 refcount  : 31;
-	guint32 subject   : 1;
-	
-	struct _CamelFolderThreadNode *tree;
-	struct _EMemChunk *node_chunks;
-	CamelFolder *folder;
-	GPtrArray *summary;
-} CamelFolderThread;
-
-/* interface 1: using uid's */
-CamelFolderThread *camel_folder_thread_messages_new(CamelFolder *folder, GPtrArray *uids, gboolean thread_subject);
-void camel_folder_thread_messages_apply(CamelFolderThread *thread, GPtrArray *uids);
-
-/* interface 2: using messageinfo's.  Currently disabled. */
-#if 0
-/* new improved interface */
-CamelFolderThread *camel_folder_thread_messages_new_summary(GPtrArray *summary);
-void camel_folder_thread_messages_add(CamelFolderThread *thread, GPtrArray *summary);
-void camel_folder_thread_messages_remove(CamelFolderThread *thread, GPtrArray *uids);
-#endif
-
-void camel_folder_thread_messages_ref(CamelFolderThread *threads);
-void camel_folder_thread_messages_unref(CamelFolderThread *threads);
-
-/* debugging function only */
-int camel_folder_threaded_messages_dump(CamelFolderThreadNode *c);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* !_CAMEL_FOLDER_THREAD_H */
diff --git a/camel/camel-folder.c b/camel/camel-folder.c
deleted file mode 100644
index 08fd816d97..0000000000
--- a/camel/camel-folder.c
+++ /dev/null
@@ -1,2161 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-folder.c: Abstract class for an email folder */
-
-/*
- * Author:
- *  Bertrand Guiheneuf 
- *
- * Copyright 1999-2003 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-
-#include "camel-folder.h"
-#include "camel-exception.h"
-#include "camel-store.h"
-#include "camel-mime-message.h"
-
-#include "e-util/e-memory.h"
-#include "camel-operation.h"
-
-#include "camel-session.h"
-#include "camel-filter-driver.h"
-#include "camel-private.h"
-#include "camel-vtrash-folder.h"
-#include "filter/filter-rule.h"
-
-#define d(x) 
-#define w(x)
-
-static CamelObjectClass *parent_class = NULL;
-
-/* Returns the class for a CamelFolder */
-#define CF_CLASS(so) ((CamelFolderClass *)((CamelObject *)(so))->klass)
-
-static void camel_folder_finalize (CamelObject *object);
-
-static void refresh_info (CamelFolder *folder, CamelException *ex);
-
-static void folder_sync (CamelFolder *folder, gboolean expunge,
-			 CamelException *ex);
-
-static const gchar *get_name (CamelFolder *folder);
-static const gchar *get_full_name (CamelFolder *folder);
-static CamelStore *get_parent_store   (CamelFolder *folder);
-
-static guint32 get_permanent_flags (CamelFolder *folder);
-static guint32 get_message_flags (CamelFolder *folder, const char *uid);
-static void set_message_flags (CamelFolder *folder, const char *uid,
-			       guint32 flags, guint32 set);
-static gboolean get_message_user_flag (CamelFolder *folder, const char *uid, const char *name);
-static void set_message_user_flag (CamelFolder *folder, const char *uid,
-				   const char *name, gboolean value);
-static const char *get_message_user_tag(CamelFolder *folder, const char *uid, const char *name);
-static void set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value);
-
-static gint get_message_count (CamelFolder *folder);
-static gint get_unread_message_count (CamelFolder *folder);
-
-static void expunge             (CamelFolder *folder,
-				 CamelException *ex);
-static int folder_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args);
-static void folder_free(CamelObject *o, guint32 tag, void *val);
-
-
-static void append_message (CamelFolder *folder, CamelMimeMessage *message,
-			    const CamelMessageInfo *info, char **appended_uid,
-			    CamelException *ex);
-
-
-static GPtrArray        *get_uids            (CamelFolder *folder);
-static void              free_uids           (CamelFolder *folder,
-					      GPtrArray *array);
-static GPtrArray        *get_summary         (CamelFolder *folder);
-static void              free_summary        (CamelFolder *folder,
-					      GPtrArray *array);
-
-static CamelMimeMessage *get_message         (CamelFolder *folder, const gchar *uid, CamelException *ex);
-
-static CamelMessageInfo *get_message_info    (CamelFolder *folder, const char *uid);
-static void		 free_message_info   (CamelFolder *folder, CamelMessageInfo *info);
-static void		 ref_message_info    (CamelFolder *folder, CamelMessageInfo *info);
-
-static GPtrArray      *search_by_expression  (CamelFolder *folder, const char *exp, CamelException *ex);
-static GPtrArray      *search_by_uids	     (CamelFolder *folder, const char *exp, GPtrArray *uids, CamelException *ex);
-static void            search_free           (CamelFolder * folder, GPtrArray *result);
-
-static void            transfer_messages_to  (CamelFolder *source, GPtrArray *uids, CamelFolder *dest,
-					      GPtrArray **transferred_uids, gboolean delete_originals, CamelException *ex);
-
-static void            delete                (CamelFolder *folder);
-static void            folder_rename         (CamelFolder *folder, const char *new);
-
-static void            freeze                (CamelFolder *folder);
-static void            thaw                  (CamelFolder *folder);
-static gboolean        is_frozen             (CamelFolder *folder);
-
-static gboolean        folder_changed        (CamelObject *object,
-					      gpointer event_data);
-static gboolean        message_changed       (CamelObject *object,
-					      /*const char *uid*/gpointer event_data);
-
-static void
-camel_folder_class_init (CamelFolderClass *camel_folder_class)
-{
-	CamelObjectClass *camel_object_class = CAMEL_OBJECT_CLASS (camel_folder_class);
-
-	parent_class = camel_type_get_global_classfuncs (camel_object_get_type ());
-
-	/* virtual method definition */
-	camel_folder_class->sync = folder_sync;
-	camel_folder_class->refresh_info = refresh_info;
-	camel_folder_class->get_name = get_name;
-	camel_folder_class->get_full_name = get_full_name;
-	camel_folder_class->get_parent_store = get_parent_store;
-	camel_folder_class->expunge = expunge;
-	camel_folder_class->get_message_count = get_message_count;
-	camel_folder_class->get_unread_message_count = get_unread_message_count;
-	camel_folder_class->append_message = append_message;
-	camel_folder_class->get_permanent_flags = get_permanent_flags;
-	camel_folder_class->get_message_flags = get_message_flags;
-	camel_folder_class->set_message_flags = set_message_flags;
-	camel_folder_class->get_message_user_flag = get_message_user_flag;
-	camel_folder_class->set_message_user_flag = set_message_user_flag;
-	camel_folder_class->get_message_user_tag = get_message_user_tag;
-	camel_folder_class->set_message_user_tag = set_message_user_tag;
-	camel_folder_class->get_message = get_message;
-	camel_folder_class->get_uids = get_uids;
-	camel_folder_class->free_uids = free_uids;
-	camel_folder_class->get_summary = get_summary;
-	camel_folder_class->free_summary = free_summary;
-	camel_folder_class->search_by_expression = search_by_expression;
-	camel_folder_class->search_by_uids = search_by_uids;
-	camel_folder_class->search_free = search_free;
-	camel_folder_class->get_message_info = get_message_info;
-	camel_folder_class->ref_message_info = ref_message_info;
-	camel_folder_class->free_message_info = free_message_info;
-	camel_folder_class->transfer_messages_to = transfer_messages_to;
-	camel_folder_class->delete = delete;
-	camel_folder_class->rename = folder_rename;
-	camel_folder_class->freeze = freeze;
-	camel_folder_class->thaw = thaw;
-	camel_folder_class->is_frozen = is_frozen;
-
-	/* virtual method overload */
-	camel_object_class->getv = folder_getv;
-	camel_object_class->free = folder_free;
-
-	/* events */
-	camel_object_class_add_event(camel_object_class, "folder_changed", folder_changed);
-	camel_object_class_add_event(camel_object_class, "message_changed", message_changed);
-	camel_object_class_add_event(camel_object_class, "deleted", NULL);
-	camel_object_class_add_event(camel_object_class, "renamed", NULL);
-}
-
-static void
-camel_folder_init (gpointer object, gpointer klass)
-{
-	CamelFolder *folder = object;
-
-	folder->priv = g_malloc0(sizeof(*folder->priv));
-	folder->priv->frozen = 0;
-	folder->priv->changed_frozen = camel_folder_change_info_new();
-	folder->priv->lock = e_mutex_new(E_MUTEX_REC);
-	folder->priv->change_lock = e_mutex_new(E_MUTEX_SIMPLE);
-}
-
-static void
-camel_folder_finalize (CamelObject *object)
-{
-	CamelFolder *camel_folder = CAMEL_FOLDER (object);
-	struct _CamelFolderPrivate *p = camel_folder->priv;
-
-	g_free(camel_folder->name);
-	g_free(camel_folder->full_name);
-	g_free(camel_folder->description);
-
-	if (camel_folder->parent_store)
-		camel_object_unref (camel_folder->parent_store);
-
-	if (camel_folder->summary)
-		camel_object_unref (camel_folder->summary);
-
-	camel_folder_change_info_free(p->changed_frozen);
-	
-	e_mutex_destroy(p->lock);
-	e_mutex_destroy(p->change_lock);
-	
-	g_free(p);
-}
-
-CamelType
-camel_folder_get_type (void)
-{
-	static CamelType camel_folder_type = CAMEL_INVALID_TYPE;
-
-	if (camel_folder_type == CAMEL_INVALID_TYPE)	{
-		camel_folder_type = camel_type_register (CAMEL_OBJECT_TYPE, "CamelFolder",
-							 sizeof (CamelFolder),
-							 sizeof (CamelFolderClass),
-							 (CamelObjectClassInitFunc) camel_folder_class_init,
-							 NULL,
-							 (CamelObjectInitFunc) camel_folder_init,
-							 (CamelObjectFinalizeFunc) camel_folder_finalize );
-	}
-
-	return camel_folder_type;
-}
-
-
-/**
- * camel_folder_construct:
- * @folder: folder object to construct
- * @parent_store: parent store object of the folder
- * @full_name: full name of the folder
- * @name: short name of the folder
- *
- * Initalizes the folder by setting the parent store and name.
- **/
-void
-camel_folder_construct (CamelFolder *folder, CamelStore *parent_store,
-			const char *full_name, const char *name)
-{
-	g_return_if_fail (CAMEL_IS_FOLDER (folder));
-	g_return_if_fail (CAMEL_IS_STORE (parent_store));
-	g_return_if_fail (folder->parent_store == NULL);
-	g_return_if_fail (folder->name == NULL);
-
-	folder->parent_store = parent_store;
-	if (parent_store)
-		camel_object_ref(parent_store);
-
-	folder->name = g_strdup (name);
-	folder->full_name = g_strdup (full_name);
-}
-
-
-static void
-folder_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
-{
-	w(g_warning ("CamelFolder::sync not implemented for `%s'",
-		     camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder))));
-}
-
-/**
- * camel_folder_sync:
- * @folder: The folder object
- * @expunge: whether or not to expunge deleted messages
- * @ex: exception object
- *
- * Sync changes made to a folder to its backing store, possibly expunging
- * deleted messages as well.
- **/
-void
-camel_folder_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
-{
-	g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
-	CAMEL_FOLDER_LOCK(folder, lock);
-	
-	if (!(folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED))
-		CF_CLASS (folder)->sync (folder, expunge, ex);
-	
-	CAMEL_FOLDER_UNLOCK(folder, lock);
-}
-
-
-static void
-refresh_info (CamelFolder *folder, CamelException *ex)
-{
-	/* No op */
-}
-
-/**
- * camel_folder_refresh_info:
- * @folder: The folder object
- * @ex: exception object
- *
- * Updates a folder's summary to be in sync with its backing store.
- **/
-void
-camel_folder_refresh_info (CamelFolder *folder, CamelException *ex)
-{
-	g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
-	CAMEL_FOLDER_LOCK(folder, lock);
-
-	CF_CLASS (folder)->refresh_info (folder, ex);
-
-	CAMEL_FOLDER_UNLOCK(folder, lock);
-}
-
-static int
-folder_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args)
-{
-	CamelFolder *folder = (CamelFolder *)object;
-	int i;
-	guint32 tag;
-
-	for (i=0;iargc;i++) {
-		CamelArgGet *arg = &args->argv[i];
-
-		tag = arg->tag;
-
-		switch (tag & CAMEL_ARG_TAG) {
-			/* CamelObject args */
-		case CAMEL_OBJECT_ARG_DESCRIPTION:
-			if (folder->description == NULL)
-				folder->description = g_strdup_printf("%s", folder->full_name);
-			*arg->ca_str = folder->description;
-			break;
-
-			/* CamelFolder args */
-		case CAMEL_FOLDER_ARG_NAME:
-			*arg->ca_str = folder->name;
-			break;
-		case CAMEL_FOLDER_ARG_FULL_NAME:
-			*arg->ca_str = folder->full_name;
-			break;
-		case CAMEL_FOLDER_ARG_STORE:
-			*arg->ca_object = folder->parent_store;
-			break;
-		case CAMEL_FOLDER_ARG_PERMANENTFLAGS:
-			*arg->ca_int = folder->permanent_flags;
-			break;
-		case CAMEL_FOLDER_ARG_TOTAL:
-			*arg->ca_int = camel_folder_summary_count(folder->summary);
-			break;
-		case CAMEL_FOLDER_ARG_UNREAD: {
-			int j, unread = 0, count;
-			CamelMessageInfo *info;
-
-			count = camel_folder_summary_count(folder->summary);
-			for (j=0; jsummary, j))) {
-					if (!(info->flags & CAMEL_MESSAGE_SEEN))
-						unread++;
-					camel_folder_summary_info_free(folder->summary, info);
-				}
-			}
-
-			*arg->ca_int = unread;
-			break; }
-		case CAMEL_FOLDER_ARG_UID_ARRAY: {
-			int j, count;
-			CamelMessageInfo *info;
-			GPtrArray *array;
-
-			count = camel_folder_summary_count(folder->summary);
-			array = g_ptr_array_new();
-			g_ptr_array_set_size(array, count);
-			for (j=0; jsummary, j))) {
-					array->pdata[i] = g_strdup(camel_message_info_uid(info));
-					camel_folder_summary_info_free(folder->summary, info);
-				}
-			}
-			*arg->ca_ptr = array;
-			break; }
-		case CAMEL_FOLDER_ARG_INFO_ARRAY:
-			*arg->ca_ptr = camel_folder_summary_array(folder->summary);
-			break;
-		case CAMEL_FOLDER_ARG_PROPERTIES:
-			*arg->ca_ptr = NULL;
-			break;
-		default:
-			continue;
-		}
-
-		arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE;
-	}
-
-	return parent_class->getv(object, ex, args);
-}
-
-static void
-folder_free(CamelObject *o, guint32 tag, void *val)
-{
-	CamelFolder *folder = (CamelFolder *)o;
-
-	switch (tag & CAMEL_ARG_TAG) {
-	case CAMEL_FOLDER_ARG_UID_ARRAY: {
-		GPtrArray *array = val;
-		int i;
-
-		for (i=0; ilen; i++)
-			g_free(array->pdata[i]);
-		g_ptr_array_free(array, TRUE);
-		break; }
-	case CAMEL_FOLDER_ARG_INFO_ARRAY:
-		camel_folder_summary_array_free(folder->summary, val);
-		break;
-	case CAMEL_FOLDER_ARG_PROPERTIES:
-		g_slist_free(val);
-		break;
-	default:
-		parent_class->free(o, tag, val);
-	}
-}
-
-static const char *
-get_name (CamelFolder *folder)
-{
-	return folder->name;
-}
-
-/**
- * camel_folder_get_name:
- * @folder: a folder
- *
- * Get the (short) name of the folder. The fully qualified name
- * can be obtained with the get_full_name method.
- *
- * Return value: name of the folder
- **/
-const char *
-camel_folder_get_name (CamelFolder * folder)
-{
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
-
-	return CF_CLASS (folder)->get_name (folder);
-}
-
-
-static const char *
-get_full_name (CamelFolder *folder)
-{
-	return folder->full_name;
-}
-
-/**
- * camel_folder_get_full_name:
- * @folder: a folder
- *
- * Get the (full) name of the folder.
- *
- * Return value: full name of the folder
- **/
-const char *
-camel_folder_get_full_name (CamelFolder *folder)
-{
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
-
-	return CF_CLASS (folder)->get_full_name (folder);
-}
-
-
-static CamelStore *
-get_parent_store (CamelFolder * folder)
-{
-	return folder->parent_store;
-}
-
-/**
- * camel_folder_get_parent_store:
- * @folder: folder to get the parent of
- *
- * Return value: the parent store of the folder.
- **/
-CamelStore *
-camel_folder_get_parent_store (CamelFolder *folder)
-{
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
-
-	return CF_CLASS (folder)->get_parent_store (folder);
-}
-
-
-static void
-expunge (CamelFolder *folder, CamelException *ex)
-{
-	w(g_warning ("CamelFolder::expunge not implemented for `%s'",
-		     camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder))));
-}
-
-
-/**
- * camel_folder_expunge:
- * @folder: the folder
- * @ex: a CamelException
- *
- * Delete messages which have been marked as "DELETED"
- **/
-void
-camel_folder_expunge (CamelFolder *folder, CamelException *ex)
-{
-	g_return_if_fail (CAMEL_IS_FOLDER (folder));
-	
-	CAMEL_FOLDER_LOCK(folder, lock);
-	
-	if (!(folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED))
-		CF_CLASS (folder)->expunge (folder, ex);
-	
-	CAMEL_FOLDER_UNLOCK(folder, lock);
-}
-
-static int
-get_message_count (CamelFolder *folder)
-{
-	g_return_val_if_fail(folder->summary != NULL, -1);
-
-	return camel_folder_summary_count(folder->summary);
-}
-
-/**
- * camel_folder_get_message_count:
- * @folder: A CamelFolder object
- *
- * Return value: the number of messages in the folder, or -1 if unknown.
- **/
-int
-camel_folder_get_message_count (CamelFolder *folder)
-{
-	int ret;
-
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), -1);
-
-	ret = CF_CLASS (folder)->get_message_count (folder);
-
-	return ret;
-}
-
-static int
-get_unread_message_count(CamelFolder *folder)
-{
-	int i, count, unread=0;
-
-	g_return_val_if_fail(folder->summary != NULL, -1);
-
-	count = camel_folder_summary_count(folder->summary);
-	for (i=0; isummary, i);
-
-		if (info) {
-			if (!(info->flags & CAMEL_MESSAGE_SEEN) && (!(info->flags & CAMEL_MESSAGE_JUNK) || (folder->folder_flags & CAMEL_FOLDER_IS_JUNK)))
-				unread++;
-			camel_folder_summary_info_free(folder->summary, info);
-		}
-	}
-
-	return unread;
-}
-
-/**
- * camel_folder_unread_get_message_count:
- * @folder: A CamelFolder object
- *
- * Return value: the number of unread messages in the folder, or -1 if unknown.
- **/
-int
-camel_folder_get_unread_message_count (CamelFolder *folder)
-{
-	int ret;
-
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), -1);
-	
-	ret = CF_CLASS (folder)->get_unread_message_count (folder);
-
-	return ret;
-}
-
-static void
-append_message (CamelFolder *folder, CamelMimeMessage *message,
-		const CamelMessageInfo *info, char **appended_uid,
-		CamelException *ex)
-{
-	camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID,
-			      _("Unsupported operation: append message: for %s"),
-			      camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder)));
-	
-	w(g_warning ("CamelFolder::append_message not implemented for `%s'",
-		     camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder))));
-	
-	return;
-
-}
-
-/**
- * camel_folder_append_message: add a message to a folder
- * @folder: folder object to add the message to
- * @message: message object
- * @info: message info with additional flags/etc to set on
- * new message, or %NULL
- * @appended_uid: if non-%NULL, the UID of the appended message will
- * be returned here, if it is known.
- * @ex: exception object
- *
- * Add a message to a folder. Only the flag and tag data from @info
- * is used. If @info is %NULL, no flags or tags will be set.
- **/
-void
-camel_folder_append_message (CamelFolder *folder, CamelMimeMessage *message,
-			     const CamelMessageInfo *info, char **appended_uid,
-			     CamelException *ex)
-{
-	g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
-	CAMEL_FOLDER_LOCK(folder, lock);
-
-	CF_CLASS (folder)->append_message (folder, message, info, appended_uid, ex);
-
-	CAMEL_FOLDER_UNLOCK(folder, lock);
-}
-
-
-static guint32
-get_permanent_flags (CamelFolder *folder)
-{
-	return folder->permanent_flags;
-}
-
-/**
- * camel_folder_get_permanent_flags:
- * @folder: a CamelFolder
- *
- * Return value: the set of CamelMessageFlags that can be permanently
- * stored on a message between sessions. If it includes %CAMEL_FLAG_USER,
- * then user-defined flags will be remembered.
- **/
-guint32
-camel_folder_get_permanent_flags (CamelFolder *folder)
-{
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
-
-	return CF_CLASS (folder)->get_permanent_flags (folder);
-}
-
-static guint32
-get_message_flags(CamelFolder *folder, const char *uid)
-{
-	CamelMessageInfo *info;
-	guint32 flags;
-
-	g_return_val_if_fail(folder->summary != NULL, 0);
-
-	info = camel_folder_summary_uid(folder->summary, uid);
-	if (info == NULL)
-		return 0;
-
-	flags = info->flags;
-	camel_folder_summary_info_free(folder->summary, info);
-
-	return flags;
-}
-
-/**
- * camel_folder_get_message_flags:
- * @folder: a CamelFolder
- * @uid: the UID of a message in @folder
- *
- * Return value: the CamelMessageFlags that are set on the indicated
- * message.
- **/
-guint32
-camel_folder_get_message_flags (CamelFolder *folder, const char *uid)
-{
-	guint32 ret;
-
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
-
-	ret = CF_CLASS (folder)->get_message_flags (folder, uid);
-
-	return ret;
-}
-
-static void
-set_message_flags(CamelFolder *folder, const char *uid, guint32 flags, guint32 set)
-{
-	CamelMessageInfo *info;
-	guint32 new;
-
-	g_return_if_fail(folder->summary != NULL);
-
-	info = camel_folder_summary_uid(folder->summary, uid);
-	if (info == NULL)
-		return;
-
-	new = (info->flags & ~flags) | (set & flags);
-	if (new == info->flags) {
-		camel_folder_summary_info_free(folder->summary, info);
-		return;
-	}
-	
-	info->flags = new | CAMEL_MESSAGE_FOLDER_FLAGGED;
-	camel_folder_summary_touch(folder->summary);
-	camel_folder_summary_info_free(folder->summary, info);
-
-	camel_object_trigger_event (folder, "message_changed", (char *) uid);
-}
-
-/**
- * camel_folder_set_message_flags:
- * @folder: a CamelFolder
- * @uid: the UID of a message in @folder
- * @flags: a set of CamelMessageFlag values to set
- * @set: the mask of values in @flags to use.
- *
- * Sets those flags specified by @set to the values specified by @flags
- * on the indicated message. (This may or may not persist after the
- * folder or store is closed. See camel_folder_get_permanent_flags().)
- **/
-void
-camel_folder_set_message_flags (CamelFolder *folder, const char *uid,
-				guint32 flags, guint32 set)
-{
-	g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
-	CF_CLASS (folder)->set_message_flags (folder, uid, flags, set);
-}
-
-
-static gboolean
-get_message_user_flag(CamelFolder *folder, const char *uid, const char *name)
-{
-	CamelMessageInfo *info;
-	gboolean ret;
-
-	g_return_val_if_fail(folder->summary != NULL, FALSE);
-
-	info = camel_folder_summary_uid(folder->summary, uid);
-	if (info == NULL)
-		return FALSE;
-
-	ret = camel_flag_get(&info->user_flags, name);
-	camel_folder_summary_info_free(folder->summary, info);
-
-	return ret;
-}
-
-/**
- * camel_folder_get_message_user_flag:
- * @folder: a CamelFolder
- * @uid: the UID of a message in @folder
- * @name: the name of a user flag
- *
- * Return value: whether or not the given user flag is set on the message.
- **/
-gboolean
-camel_folder_get_message_user_flag (CamelFolder *folder, const char *uid,
-				    const char *name)
-{
-	gboolean ret;
-
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
-
-	ret = CF_CLASS (folder)->get_message_user_flag (folder, uid, name);
-
-	return ret;
-}
-
-static void
-set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value)
-{
-	CamelMessageInfo *info;
-
-	g_return_if_fail(folder->summary != NULL);
-
-	info = camel_folder_summary_uid(folder->summary, uid);
-	if (info == NULL)
-		return;
-
-	if (camel_flag_set(&info->user_flags, name, value)) {
-		info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
-		camel_folder_summary_touch(folder->summary);
-		camel_object_trigger_event (folder, "message_changed", (char *) uid);
-	}
-	camel_folder_summary_info_free(folder->summary, info);
-}
-
-/**
- * camel_folder_set_message_user_flag:
- * @folder: a CamelFolder
- * @uid: the UID of a message in @folder
- * @name: the name of the user flag to set
- * @value: the value to set it to
- *
- * Sets the user flag specified by @name to the value specified by @value
- * on the indicated message. (This may or may not persist after the
- * folder or store is closed. See camel_folder_get_permanent_flags().)
- **/
-void
-camel_folder_set_message_user_flag (CamelFolder *folder, const char *uid,
-				    const char *name, gboolean value)
-{
-	g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
-	CF_CLASS (folder)->set_message_user_flag (folder, uid, name, value);
-}
-
-static const char *
-get_message_user_tag(CamelFolder *folder, const char *uid, const char *name)
-{
-	CamelMessageInfo *info;
-	const char *ret;
-
-	g_return_val_if_fail(folder->summary != NULL, NULL);
-
-	info = camel_folder_summary_uid(folder->summary, uid);
-	if (info == NULL)
-		return NULL;
-
-	/* FIXME: Need to duplicate tag string */
-
-	ret = camel_tag_get(&info->user_tags, name);
-	camel_folder_summary_info_free(folder->summary, info);
-
-	return ret;
-}
-
-/**
- * camel_folder_get_message_user_tag:
- * @folder: a CamelFolder
- * @uid: the UID of a message in @folder
- * @name: the name of a user tag
- *
- * Return value: Returns the value of the user tag.
- **/
-const char *
-camel_folder_get_message_user_tag (CamelFolder *folder, const char *uid,  const char *name)
-{
-	const char *ret;
-
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
-
-	/* FIXME: should duplicate string */
-	ret = CF_CLASS (folder)->get_message_user_tag (folder, uid, name);
-
-	return ret;
-}
-
-static void
-set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value)
-{
-	CamelMessageInfo *info;
-
-	g_return_if_fail(folder->summary != NULL);
-
-	info = camel_folder_summary_uid(folder->summary, uid);
-	if (info == NULL)
-		return;
-
-	if (camel_tag_set(&info->user_tags, name, value)) {
-		info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
-		camel_folder_summary_touch(folder->summary);
-		camel_object_trigger_event (folder, "message_changed", (char *) uid);
-	}
-	camel_folder_summary_info_free(folder->summary, info);
-}
-
-/**
- * camel_folder_set_message_user_tag:
- * @folder: a CamelFolder
- * @uid: the UID of a message in @folder
- * @name: the name of the user tag to set
- * @value: the value to set it to
- *
- * Sets the user tag specified by @name to the value specified by @value
- * on the indicated message. (This may or may not persist after the
- * folder or store is closed. See camel_folder_get_permanent_flags().)
- **/
-void
-camel_folder_set_message_user_tag (CamelFolder *folder, const char *uid, const char *name, const char *value)
-{
-	g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
-	CF_CLASS (folder)->set_message_user_tag (folder, uid, name, value);
-}
-
-static CamelMessageInfo *
-get_message_info (CamelFolder *folder, const char *uid)
-{
-	g_return_val_if_fail(folder->summary != NULL, NULL);
-
-	return camel_folder_summary_uid(folder->summary, uid);
-}
-
-/**
- * camel_folder_get_message_info:
- * @folder: a CamelFolder
- * @uid: the uid of a message
- *
- * Retrieve the CamelMessageInfo for the specified @uid.  This return
- * must be freed using free_message_info().
- *
- * Return value: the summary information for the indicated message, or NULL
- * if the uid does not exist.
- **/
-CamelMessageInfo *
-camel_folder_get_message_info (CamelFolder *folder, const char *uid)
-{
-	CamelMessageInfo *ret;
-
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
-	g_return_val_if_fail (uid != NULL, NULL);
-
-	ret = CF_CLASS (folder)->get_message_info (folder, uid);
-
-	return ret;
-}
-
-static void
-free_message_info (CamelFolder *folder, CamelMessageInfo *info)
-{
-	g_return_if_fail(folder->summary != NULL);
-
-	camel_folder_summary_info_free(folder->summary, info);
-}
-
-/**
- * camel_folder_free_message_info:
- * @folder: 
- * @info: 
- * 
- * Free (unref) a CamelMessageInfo, previously obtained with get_message_info().
- **/
-void
-camel_folder_free_message_info(CamelFolder *folder, CamelMessageInfo *info)
-{
-	g_return_if_fail(CAMEL_IS_FOLDER (folder));
-	g_return_if_fail(info != NULL);
-
-	CF_CLASS (folder)->free_message_info(folder, info);
-}
-
-static void
-ref_message_info (CamelFolder *folder, CamelMessageInfo *info)
-{
-	g_return_if_fail(folder->summary != NULL);
-
-	camel_folder_summary_info_ref(folder->summary, info);
-}
-
-/**
- * camel_folder_ref_message_info:
- * @folder: 
- * @info: 
- * 
- * Ref a CamelMessageInfo, previously obtained with get_message_info().
- **/
-void
-camel_folder_ref_message_info(CamelFolder *folder, CamelMessageInfo *info)
-{
-	g_return_if_fail(CAMEL_IS_FOLDER (folder));
-	g_return_if_fail(info != NULL);
-
-	CF_CLASS (folder)->ref_message_info(folder, info);
-}
-
-/* TODO: is this function required anyway? */
-gboolean
-camel_folder_has_summary_capability (CamelFolder *folder)
-{
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
-
-	return folder->folder_flags & CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY;
-}
-
-
-/* UIDs stuff */
-
-static CamelMimeMessage *
-get_message (CamelFolder *folder, const gchar *uid, CamelException *ex)
-{
-	w(g_warning ("CamelFolder::get_message not implemented for `%s'",
-		     camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder))));
-	
-	return NULL;
-}
-
-/**
- * camel_folder_get_message:
- * @folder: the folder object
- * @uid: the UID
- * @ex: a CamelException
- *
- * Get a message from its UID in the folder. Messages are cached
- * within a folder, that is, asking twice for the same UID returns the
- * same message object. (FIXME: is this true?)
- *
- * Return value: Message corresponding to the UID
- **/
-CamelMimeMessage *
-camel_folder_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex)
-{
-	CamelMimeMessage *ret;
-
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
-
-	CAMEL_FOLDER_LOCK(folder, lock);
-
-	ret = CF_CLASS (folder)->get_message (folder, uid, ex);
-
-	CAMEL_FOLDER_UNLOCK(folder, lock);
-
-	return ret;
-}
-
-static GPtrArray *
-get_uids(CamelFolder *folder)
-{
-	GPtrArray *array;
-	int i, j, count;
-
-	array = g_ptr_array_new();
-
-	g_return_val_if_fail(folder->summary != NULL, array);
-
-	count = camel_folder_summary_count(folder->summary);
-	g_ptr_array_set_size(array, count);
-	for (i = 0, j = 0; i < count; i++) {
-		CamelMessageInfo *info = camel_folder_summary_index(folder->summary, i);
-		
-		if (info) {
-			array->pdata[j++] = g_strdup (camel_message_info_uid (info));
-			camel_folder_summary_info_free(folder->summary, info);
-		}
-	}
-	
-	g_ptr_array_set_size (array, j);
-	
-	return array;
-}
-
-/**
- * camel_folder_get_uids:
- * @folder: folder object
- *
- * Get the list of UIDs available in a folder. This routine is useful
- * for finding what messages are available when the folder does not
- * support summaries. The returned array shoudl not be modified, and
- * must be freed by passing it to camel_folder_free_uids().
- *
- * Return value: GPtrArray of UIDs corresponding to the messages
- * available in the folder.
- **/
-GPtrArray *
-camel_folder_get_uids (CamelFolder *folder)
-{
-	GPtrArray *ret;
-
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
-
-	ret = CF_CLASS (folder)->get_uids (folder);
-
-	return ret;
-}
-
-static void
-free_uids (CamelFolder *folder, GPtrArray *array)
-{
-	int i;
-
-	for (i=0; ilen; i++)
-		g_free(array->pdata[i]);
-	g_ptr_array_free(array, TRUE);
-}
-
-/**
- * camel_folder_free_uids:
- * @folder: folder object
- * @array: the array of uids to free
- *
- * Frees the array of UIDs returned by camel_folder_get_uids().
- **/
-void
-camel_folder_free_uids (CamelFolder *folder, GPtrArray *array)
-{
-	g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
-	CF_CLASS (folder)->free_uids (folder, array);
-}
-
-static GPtrArray *
-get_summary(CamelFolder *folder)
-{
-	g_assert(folder->summary != NULL);
-
-	return camel_folder_summary_array(folder->summary);
-}
-
-/**
- * camel_folder_get_summary:
- * @folder: a folder object
- *
- * This returns the summary information for the folder. This array
- * should not be modified, and must be freed with
- * camel_folder_free_summary().
- *
- * Return value: an array of CamelMessageInfo
- **/
-GPtrArray *
-camel_folder_get_summary (CamelFolder *folder)
-{
-	GPtrArray *ret;
-
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
-
-	ret = CF_CLASS (folder)->get_summary (folder);
-
-	return ret;
-}
-
-static void
-free_summary(CamelFolder *folder, GPtrArray *summary)
-{
-	g_assert(folder->summary != NULL);
-
-	camel_folder_summary_array_free(folder->summary, summary);
-}
-
-/**
- * camel_folder_free_summary:
- * @folder: folder object
- * @array: the summary array to free
- *
- * Frees the summary array returned by camel_folder_get_summary().
- **/
-void camel_folder_free_summary(CamelFolder * folder, GPtrArray * array)
-{
-	g_return_if_fail(CAMEL_IS_FOLDER(folder));
-
-	CF_CLASS(folder)->free_summary(folder, array);
-}
-
-/**
- * camel_folder_has_search_capability:
- * @folder: Folder object
- *
- * Checks if a folder supports searching.
- *
- * Return value: %TRUE if the folder supports searching
- **/
-gboolean
-camel_folder_has_search_capability (CamelFolder *folder)
-{
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
-
-	return folder->folder_flags & CAMEL_FOLDER_HAS_SEARCH_CAPABILITY;
-}
-
-static GPtrArray *
-search_by_expression (CamelFolder *folder, const char *expression,
-		      CamelException *ex)
-{
-	camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID,
-			      _("Unsupported operation: search by expression: for %s"),
-			      camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder)));
-	
-	w(g_warning ("CamelFolder::search_by_expression not implemented for "
-		     "`%s'", camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder))));
-	
-	return NULL;
-}
-
-/**
- * camel_folder_search_by_expression:
- * @folder: Folder object
- * @expression: a search expression
- * @ex: a CamelException
- *
- * Searches the folder for messages matching the given search expression.
- *
- * Return value: a list of uids of matching messages. The caller must
- * free the list and each of the elements when it is done.
- **/
-GPtrArray *
-camel_folder_search_by_expression (CamelFolder *folder, const char *expression,
-				   CamelException *ex)
-{
-	GPtrArray *ret;
-
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
-	g_return_val_if_fail (folder->folder_flags & CAMEL_FOLDER_HAS_SEARCH_CAPABILITY, NULL);
-
-	/* NOTE: that it is upto the callee to lock */
-
-	ret = CF_CLASS (folder)->search_by_expression (folder, expression, ex);
-
-	return ret;
-}
-
-static GPtrArray *
-search_by_uids(CamelFolder *folder, const char *exp, GPtrArray *uids, CamelException *ex)
-{
-	camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID,
-			      _("Unsupported operation: search by uids: for %s"),
-			      camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder)));
-	
-	w(g_warning ("CamelFolder::search_by_expression not implemented for "
-		     "`%s'", camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder))));
-	
-	return NULL;
-}
-
-/**
- * camel_folder_search_by_uids:
- * @folder: 
- * @expr: 
- * @uids: array of uid's to match against.
- * @ex: 
- * 
- * Search a subset of uid's for an expression match.
- * 
- * Return value: 
- **/
-GPtrArray *
-camel_folder_search_by_uids(CamelFolder *folder, const char *expr, GPtrArray *uids, CamelException *ex)
-{
-	GPtrArray *ret;
-
-	g_return_val_if_fail(CAMEL_IS_FOLDER (folder), NULL);
-	g_return_val_if_fail(folder->folder_flags & CAMEL_FOLDER_HAS_SEARCH_CAPABILITY, NULL);
-
-	/* NOTE: that it is upto the callee to lock */
-
-	ret = CF_CLASS(folder)->search_by_uids(folder, expr, uids, ex);
-
-	return ret;
-}
-
-static void
-search_free (CamelFolder *folder, GPtrArray *result)
-{
-	int i;
-
-	for (i = 0; i < result->len; i++)
-		g_free (g_ptr_array_index (result, i));
-	g_ptr_array_free (result, TRUE);
-}
-
-/**
- * camel_folder_search_free:
- * @folder: 
- * @result: 
- * 
- * Free the result of a search.
- **/
-void 
-camel_folder_search_free (CamelFolder *folder, GPtrArray *result)
-{
-	g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
-	/* NOTE: upto the callee to lock */
-	CF_CLASS (folder)->search_free (folder, result);
-}
-
-
-static void
-transfer_message_to (CamelFolder *source, const char *uid, CamelFolder *dest,
-		     char **transferred_uid, gboolean delete_original,
-		     CamelException *ex)
-{
-	CamelMimeMessage *msg;
-	CamelMessageInfo *info = NULL;
-	
-	/* Default implementation. */
-	
-	/* we alredy have the lock, dont deadlock */
-	msg = CF_CLASS (source)->get_message (source, uid, ex);
-	if (!msg)
-		return;
-	
-	if (source->folder_flags & CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY)
-		info = CF_CLASS (source)->get_message_info (source, uid);
-	else
-		info = camel_message_info_new_from_header (((CamelMimePart *)msg)->headers);
-	
-	/* we don't want to retain the deleted flag */
-	if (info && info->flags & CAMEL_MESSAGE_DELETED) {
-		info->flags = info->flags & ~CAMEL_MESSAGE_DELETED;
-		delete_original = TRUE;
-	}
-	
-	camel_folder_append_message (dest, msg, info, transferred_uid, ex);
-	camel_object_unref (msg);
-	
-	if (delete_original && !camel_exception_is_set (ex))
-		camel_folder_set_message_flags (source, uid, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN, ~0);
-	
-	if (info) {
-		if (source->folder_flags & CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY)
-			CF_CLASS (source)->free_message_info (source, info);
-		else
-			camel_message_info_free (info);
-	}
-}
-
-static void
-transfer_messages_to (CamelFolder *source, GPtrArray *uids, CamelFolder *dest, GPtrArray **transferred_uids, gboolean delete_originals, CamelException *ex)
-{
-	CamelException local;
-	char **ret_uid = NULL;
-	int i;
-
-	if (transferred_uids) {
-		*transferred_uids = g_ptr_array_new ();
-		g_ptr_array_set_size (*transferred_uids, uids->len);
-	}
-
-	camel_exception_init(&local);
-	if (ex == NULL)
-		ex = &local;
-
-	camel_operation_start(NULL, delete_originals ? _("Moving messages") : _("Copying messages"));
-
-	if (uids->len > 1) {
-		camel_folder_freeze(dest);
-		if (delete_originals)
-			camel_folder_freeze(source);
-	}
-	for (i = 0; i < uids->len && !camel_exception_is_set (ex); i++) {
-		if (transferred_uids)
-			ret_uid = (char **)&((*transferred_uids)->pdata[i]);
-		transfer_message_to (source, uids->pdata[i], dest, ret_uid, delete_originals, ex);
-		camel_operation_progress(NULL, i * 100 / uids->len);
-	}
-	if (uids->len > 1) {
-		camel_folder_thaw(dest);
-		if (delete_originals)
-			camel_folder_thaw(source);
-	}
-
-	camel_operation_end(NULL);
-	camel_exception_clear(&local);
-}
-
-/**
- * camel_folder_transfer_messages_to:
- * @source: source folder
- * @uids: message UIDs in @source
- * @dest: destination folder
- * @transferred_uids: if non-%NULL, the UIDs of the resulting messages
- * in @dest will be stored here, if known.
- * @delete_originals: whether or not to delete the original messages
- * @ex: a CamelException
- *
- * This copies or moves messages from one folder to another. If the
- * @source and @dest folders have the same parent_store, this may be
- * more efficient than using camel_folder_append_message().
- **/
-void
-camel_folder_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
-				   CamelFolder *dest, GPtrArray **transferred_uids,
-				   gboolean delete_originals, CamelException *ex)
-{
-	g_return_if_fail (CAMEL_IS_FOLDER (source));
-	g_return_if_fail (CAMEL_IS_FOLDER (dest));
-	g_return_if_fail (uids != NULL);
-	
-	if (source == dest || uids->len == 0) {
-		/* source and destination folders are the same, or no work to do, do nothing. */
-		return;
-	}
-	
-	CAMEL_FOLDER_LOCK(source, lock);
-	
-	if (source->parent_store == dest->parent_store) {
-		/* If either folder is a vtrash, we need to use the
-		 * vtrash transfer method.
-		 */
-		if (CAMEL_IS_VTRASH_FOLDER (dest))
-			CF_CLASS (dest)->transfer_messages_to (source, uids, dest, transferred_uids, delete_originals, ex);
-		else
-			CF_CLASS (source)->transfer_messages_to (source, uids, dest, transferred_uids, delete_originals, ex);
-	} else
-		transfer_messages_to (source, uids, dest, transferred_uids, delete_originals, ex);
-	
-	CAMEL_FOLDER_UNLOCK(source, lock);
-}
-
-static void
-delete (CamelFolder *folder)
-{
-	if (folder->summary)
-		camel_folder_summary_clear (folder->summary);
-}
-
-/**
- * camel_folder_delete:
- * @folder: folder
- *
- * Marks a folder object as deleted and performs any required cleanup.
- **/
-void
-camel_folder_delete (CamelFolder *folder)
-{
-	g_return_if_fail (CAMEL_IS_FOLDER (folder));
-	
-	CAMEL_FOLDER_LOCK (folder, lock);
-	if (folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED) {
-		CAMEL_FOLDER_UNLOCK (folder, lock);
-		return;
-	}
-	
-	folder->folder_flags |= CAMEL_FOLDER_HAS_BEEN_DELETED;
-	
-	CF_CLASS (folder)->delete (folder);
-
-	CAMEL_FOLDER_UNLOCK (folder, lock);
-
-	camel_object_trigger_event (folder, "deleted", NULL);
-}
-
-static void
-folder_rename (CamelFolder *folder, const char *new)
-{
-	char *tmp;
-
-	printf("CamelFolder:rename('%s')\n", new);
-
-	g_free(folder->full_name);
-	folder->full_name = g_strdup(new);
-	g_free(folder->name);
-	tmp = strrchr(new, folder->parent_store->dir_sep);
-	folder->name = g_strdup(tmp?tmp+1:new);
-}
-
-/**
- * camel_folder_rename:
- * @folder: 
- * @new: 
- * 
- * Mark an active folder object as renamed.
- *
- * NOTE: This is an internal function used by camel stores, no locking
- * is performed on the folder.
- **/
-void
-camel_folder_rename(CamelFolder *folder, const char *new)
-{
-	char *old;
-
-	old = g_strdup(folder->full_name);
-
-	CF_CLASS (folder)->rename(folder, new);
-
-	camel_object_trigger_event (folder, "renamed", old);
-	g_free(old);
-}
-
-static void
-freeze (CamelFolder *folder)
-{
-	CAMEL_FOLDER_LOCK(folder, change_lock);
-
-	g_assert(folder->priv->frozen >= 0);
-
-	folder->priv->frozen++;
-
-	d(printf ("freeze(%p '%s') = %d\n", folder, folder->full_name, folder->priv->frozen));
-	CAMEL_FOLDER_UNLOCK(folder, change_lock);
-}
-
-/**
- * camel_folder_freeze:
- * @folder: a folder
- *
- * Freezes the folder so that a series of operation can be performed
- * without "message_changed" and "folder_changed" signals being emitted.
- * When the folder is later thawed with camel_folder_thaw(), the
- * suppressed signals will be emitted.
- **/
-void
-camel_folder_freeze (CamelFolder * folder)
-{
-	g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
-	CF_CLASS (folder)->freeze (folder);
-}
-
-static void
-thaw (CamelFolder * folder)
-{
-	CamelFolderChangeInfo *info = NULL;
-
-	CAMEL_FOLDER_LOCK(folder, change_lock);
-
-	g_assert(folder->priv->frozen > 0);
-
-	folder->priv->frozen--;
-
-	d(printf ("thaw(%p '%s') = %d\n", folder, folder->full_name, folder->priv->frozen));
-
-	if (folder->priv->frozen == 0
-	    && camel_folder_change_info_changed(folder->priv->changed_frozen)) {
-		info = folder->priv->changed_frozen;
-		folder->priv->changed_frozen = camel_folder_change_info_new();
-	}
-	
-	CAMEL_FOLDER_UNLOCK(folder, change_lock);
-
-	if (info) {
-		camel_object_trigger_event (folder, "folder_changed", info);
-		camel_folder_change_info_free(info);
-	}
-}
-
-/**
- * camel_folder_thaw:
- * @folder: a folder
- *
- * Thaws the folder and emits any pending folder_changed or
- * message_changed signals.
- **/
-void
-camel_folder_thaw (CamelFolder *folder)
-{
-	g_return_if_fail (CAMEL_IS_FOLDER (folder));
-	g_return_if_fail (folder->priv->frozen != 0);
-
-	CF_CLASS (folder)->thaw (folder);
-}
-
-static gboolean
-is_frozen (CamelFolder *folder)
-{
-	return folder->priv->frozen != 0;
-}
-
-/**
- * camel_folder_is_frozen:
- * @folder: a folder
- *
- * Return value: whether or not the folder is frozen.
- **/
-gboolean
-camel_folder_is_frozen (CamelFolder *folder)
-{
-	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
-
-	return CF_CLASS (folder)->is_frozen (folder);
-}
-
-
-struct _folder_filter_msg {
-	CamelSessionThreadMsg msg;
-
-	GPtrArray *recents;
-	CamelFolder *folder;
-	CamelFilterDriver *driver;
-	CamelException ex;
-};
-
-static void
-filter_filter(CamelSession *session, CamelSessionThreadMsg *msg)
-{
-	struct _folder_filter_msg *m = (struct _folder_filter_msg *)msg;
-	CamelMessageInfo *info;
-	int i, status = 0;
-	CamelURL *uri;
-	char *source_url;
-	CamelException ex;
-
-	camel_operation_start(NULL, _("Filtering new message(s)"));
-
-	source_url = camel_service_get_url((CamelService *)m->folder->parent_store);
-	uri = camel_url_new(source_url, NULL);
-	g_free(source_url);
-	if (m->folder->full_name && m->folder->full_name[0] != '/') {
-		char *tmp = alloca(strlen(m->folder->full_name)+2);
-
-		sprintf(tmp, "/%s", m->folder->full_name);
-		camel_url_set_path(uri, tmp);
-	} else
-		camel_url_set_path(uri, m->folder->full_name);
-	source_url = camel_url_to_string(uri, CAMEL_URL_HIDE_ALL);
-	camel_url_free(uri);
-
-	for (i=0;status == 0 && irecents->len;i++) {
-		char *uid = m->recents->pdata[i];
-		int pc = 100 * i / m->recents->len;
-
-		camel_operation_progress(NULL, pc);
-
-		info = camel_folder_get_message_info(m->folder, uid);
-		if (info == NULL) {
-			g_warning("uid %s vanished from folder: %s", uid, source_url);
-			continue;
-		}
-
-		status = camel_filter_driver_filter_message(m->driver, NULL, info, uid, m->folder, source_url, source_url, &m->ex);
-
-		camel_folder_free_message_info(m->folder, info);
-	}
-
-	camel_exception_init(&ex);
-	camel_filter_driver_flush(m->driver, &ex);
-	if (!camel_exception_is_set(&m->ex))
-		camel_exception_xfer(&m->ex, &ex);
-
-	g_free(source_url);
-
-	camel_operation_end(NULL);
-}
-
-static void
-filter_free(CamelSession *session, CamelSessionThreadMsg *msg)
-{
-	struct _folder_filter_msg *m = (struct _folder_filter_msg *)msg;
-	int i;
-
-	camel_folder_thaw(m->folder);
-	camel_object_unref((CamelObject *)m->folder);
-	camel_object_unref((CamelObject *)m->driver);
-	for (i=0;irecents->len;i++)
-		g_free(m->recents->pdata[i]);
-	g_ptr_array_free(m->recents, TRUE);
-}
-
-static CamelSessionThreadOps filter_ops = {
-	filter_filter,
-	filter_free,
-};
-
-
-/* Event hooks that block emission when frozen */
-static gboolean
-folder_changed (CamelObject *obj, gpointer event_data)
-{
-	CamelFolder *folder = CAMEL_FOLDER (obj);
-	CamelFolderChangeInfo *changed = event_data;
-	gboolean ret = TRUE;
-
-	d(printf ("folder_changed(%p, %p), frozen=%d\n", obj, event_data, folder->priv->frozen));
-	d(printf(" added %d remoded %d changed %d recent %d\n",
-		 changed->uid_added->len, changed->uid_removed->len,
-		 changed->uid_changed->len, changed->uid_recent->len));
-
-	if (changed != NULL) {
-		CamelSession *session = ((CamelService *)folder->parent_store)->session;
-		CamelFilterDriver *driver = NULL;
-
-		if (((folder->folder_flags & CAMEL_FOLDER_FILTER_RECENT) || camel_session_check_junk (session))
-		    && changed->uid_recent->len > 0)
-			driver = camel_session_get_filter_driver(session,
-								 (folder->folder_flags & CAMEL_FOLDER_FILTER_RECENT) ? FILTER_SOURCE_INCOMING : FILTER_SOURCE_JUNKTEST, NULL);
-		
-		CAMEL_FOLDER_LOCK(folder, change_lock);
-
-		if (driver) {
-			GPtrArray *recents = g_ptr_array_new();
-			int i;
-			struct _folder_filter_msg *msg;
-			
-			d(printf("** Have '%d' recent messages, launching thread to process them\n", changed->uid_recent->len));
-
-			folder->priv->frozen++;
-			msg = camel_session_thread_msg_new(session, &filter_ops, sizeof(*msg));
-			for (i=0;iuid_recent->len;i++)
-				g_ptr_array_add(recents, g_strdup(changed->uid_recent->pdata[i]));
-			msg->recents = recents;
-			msg->folder = folder;
-			camel_object_ref((CamelObject *)folder);
-			msg->driver = driver;
-			camel_exception_init(&msg->ex);
-			camel_session_thread_queue(session, &msg->msg, 0);
-			
-			/* zero out the recent list so we dont reprocess */
-			/* this pokes past abstraction, but changeinfo is our structure anyway */
-			/* the only other alternative is to recognise when trigger is called from	
-			   thaw(), but thats a pita */
-			g_ptr_array_set_size(changed->uid_recent, 0);
-		}
-		
-		if (folder->priv->frozen) {
-			camel_folder_change_info_cat(folder->priv->changed_frozen, changed);
-			ret = FALSE;
-		}
-		CAMEL_FOLDER_UNLOCK(folder, change_lock);
-	} else {
-			w(g_warning ("Class %s is passing NULL to folder_changed event",
-				     camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder))));
-	}
-
-	return ret;
-}
-
-static gboolean
-message_changed (CamelObject *obj, /*const char *uid*/gpointer event_data)
-{
-	CamelFolder *folder = CAMEL_FOLDER (obj);
-	gboolean ret = TRUE;
-
-	d(printf ("message_changed(%p, %p), frozen=%d\n", folder, event_data, folder->priv->frozen));
-
-	if (folder->priv->frozen) {
-		CAMEL_FOLDER_LOCK(folder, change_lock);
-	
-		camel_folder_change_info_change_uid(folder->priv->changed_frozen, (char *)event_data);
-		ret = FALSE;
-
-		CAMEL_FOLDER_UNLOCK(folder, change_lock);
-	}
-
-	return ret;
-}
-
-
-/**
- * camel_folder_free_nop:
- * @folder: a folder
- * @array: an array of uids or CamelMessageInfo
- *
- * "Frees" the provided array by doing nothing. Used by CamelFolder
- * subclasses as an implementation for free_uids, or free_summary when
- * the returned array is "static" information and should not be freed.
- **/
-void
-camel_folder_free_nop (CamelFolder *folder, GPtrArray *array)
-{
-	;
-}
-
-/**
- * camel_folder_free_shallow:
- * @folder: a folder
- * @array: an array of uids or CamelMessageInfo
- *
- * Frees the provided array but not its contents. Used by CamelFolder
- * subclasses as an implementation for free_uids or free_summary when
- * the returned array needs to be freed but its contents come from
- * "static" information.
- **/
-void
-camel_folder_free_shallow (CamelFolder *folder, GPtrArray *array)
-{
-	g_ptr_array_free (array, TRUE);
-}
-
-/**
- * camel_folder_free_deep:
- * @folder: a folder
- * @array: an array of uids
- *
- * Frees the provided array and its contents. Used by CamelFolder
- * subclasses as an implementation for free_uids when the provided
- * information was created explicitly by the corresponding get_ call.
- **/
-void
-camel_folder_free_deep (CamelFolder *folder, GPtrArray *array)
-{
-	int i;
-
-	for (i = 0; i < array->len; i++)
-		g_free (array->pdata[i]);
-	g_ptr_array_free (array, TRUE);
-}
-
-struct _CamelFolderChangeInfoPrivate {
-	GHashTable *uid_stored;	/* what we have stored, which array they're in */
-	GHashTable *uid_source;	/* used to create unique lists */
-	struct _EMemPool *uid_pool;	/* pool used to store copies of uid strings */
-};
-
-/**
- * camel_folder_change_info_new:
- * @void: 
- * 
- * Create a new folder change info structure.
- *
- * Change info structures are not MT-SAFE and must be
- * locked for exclusive access externally.
- * 
- * Return value: 
- **/
-CamelFolderChangeInfo *
-camel_folder_change_info_new(void)
-{
-	CamelFolderChangeInfo *info;
-
-	info = g_malloc(sizeof(*info));
-	info->uid_added = g_ptr_array_new();
-	info->uid_removed = g_ptr_array_new();
-	info->uid_changed = g_ptr_array_new();
-	info->uid_recent = g_ptr_array_new();
-	info->priv = g_malloc0(sizeof(*info->priv));
-	info->priv->uid_stored = g_hash_table_new(g_str_hash, g_str_equal);
-	info->priv->uid_source = NULL;
-	info->priv->uid_pool = e_mempool_new(512, 256, E_MEMPOOL_ALIGN_BYTE);
-
-	return info;
-}
-
-/**
- * camel_folder_change_info_add_source:
- * @info: 
- * @uid: 
- * 
- * Add a source uid for generating a changeset.
- **/
-void
-camel_folder_change_info_add_source(CamelFolderChangeInfo *info, const char *uid)
-{
-	struct _CamelFolderChangeInfoPrivate *p;
-	
-	g_assert(info != NULL);
-	
-	p = info->priv;
-	
-	if (p->uid_source == NULL)
-		p->uid_source = g_hash_table_new(g_str_hash, g_str_equal);
-
-	if (g_hash_table_lookup(p->uid_source, uid) == NULL)
-		g_hash_table_insert(p->uid_source, e_mempool_strdup(p->uid_pool, uid), (void *)1);
-}
-
-/**
- * camel_folder_change_info_add_source_list:
- * @info: 
- * @list: 
- * 
- * Add a list of source uid's for generating a changeset.
- **/
-void
-camel_folder_change_info_add_source_list(CamelFolderChangeInfo *info, const GPtrArray *list)
-{
-	struct _CamelFolderChangeInfoPrivate *p;
-	int i;
-	
-	g_assert(info != NULL);
-	g_assert(list != NULL);
-	
-	p = info->priv;
-
-	if (p->uid_source == NULL)
-		p->uid_source = g_hash_table_new(g_str_hash, g_str_equal);
-
-	for (i=0;ilen;i++) {
-		char *uid = list->pdata[i];
-
-		if (g_hash_table_lookup(p->uid_source, uid) == NULL)
-			g_hash_table_insert(p->uid_source, e_mempool_strdup(p->uid_pool, uid), (void *)1);
-	}
-}
-
-/**
- * camel_folder_change_info_add_update:
- * @info: 
- * @uid: 
- * 
- * Add a uid from the updated list, used to generate a changeset diff.
- **/
-void
-camel_folder_change_info_add_update(CamelFolderChangeInfo *info, const char *uid)
-{
-	struct _CamelFolderChangeInfoPrivate *p;
-	char *key;
-	int value;
-	
-	g_assert(info != NULL);
-	
-	p = info->priv;
-	
-	if (p->uid_source == NULL) {
-		camel_folder_change_info_add_uid(info, uid);
-		return;
-	}
-
-	if (g_hash_table_lookup_extended(p->uid_source, uid, (void **)&key, (void **)&value)) {
-		g_hash_table_remove(p->uid_source, key);
-	} else {
-		camel_folder_change_info_add_uid(info, uid);
-	}
-}
-
-/**
- * camel_folder_change_info_add_update_list:
- * @info: 
- * @list: 
- * 
- * Add a list of uid's from the updated list.
- **/
-void
-camel_folder_change_info_add_update_list(CamelFolderChangeInfo *info, const GPtrArray *list)
-{
-	int i;
-	
-	g_assert(info != NULL);
-	g_assert(list != NULL);
-	
-	for (i=0;ilen;i++)
-		camel_folder_change_info_add_update(info, list->pdata[i]);
-}
-
-static void
-change_info_remove(char *key, void *value, CamelFolderChangeInfo *info)
-{
-	struct _CamelFolderChangeInfoPrivate *p = info->priv;
-	GPtrArray *olduids;
-	char *olduid;
-
-	if (g_hash_table_lookup_extended(p->uid_stored, key, (void **)&olduid, (void **)&olduids)) {
-		/* if it was added/changed them removed, then remove it */
-		if (olduids != info->uid_removed) {
-			g_ptr_array_remove_fast(olduids, olduid);
-			g_ptr_array_add(info->uid_removed, olduid);
-			g_hash_table_insert(p->uid_stored, olduid, info->uid_removed);
-		}
-		return;
-	}
-
-	/* we dont need to copy this, as they've already been copied into our pool */
-	g_ptr_array_add(info->uid_removed, key);
-	g_hash_table_insert(p->uid_stored, key, info->uid_removed);
-}
-
-/**
- * camel_folder_change_info_build_diff:
- * @info: 
- * 
- * Compare the source uid set to the updated uid set and generate the differences
- * into the added and removed lists.
- **/
-void
-camel_folder_change_info_build_diff(CamelFolderChangeInfo *info)
-{
-	struct _CamelFolderChangeInfoPrivate *p;
-	
-	g_assert(info != NULL);
-	
-	p = info->priv;
-	
-	if (p->uid_source) {
-		g_hash_table_foreach(p->uid_source, (GHFunc)change_info_remove, info);
-		g_hash_table_destroy(p->uid_source);
-		p->uid_source = NULL;
-	}
-}
-
-static void
-change_info_cat(CamelFolderChangeInfo *info, GPtrArray *source, void (*add)(CamelFolderChangeInfo *info, const char *uid))
-{
-	int i;
-
-	for (i=0;ilen;i++)
-		add(info, source->pdata[i]);
-}
-
-/**
- * camel_folder_change_info_cat:
- * @info: 
- * @source: 
- * 
- * Concatenate one change info onto antoher.  Can be used to copy
- * them too.
- **/
-void
-camel_folder_change_info_cat(CamelFolderChangeInfo *info, CamelFolderChangeInfo *source)
-{
-	g_assert(info != NULL);
-	g_assert(source != NULL);
-	
-	change_info_cat(info, source->uid_added, camel_folder_change_info_add_uid);
-	change_info_cat(info, source->uid_removed, camel_folder_change_info_remove_uid);
-	change_info_cat(info, source->uid_changed, camel_folder_change_info_change_uid);
-	change_info_cat(info, source->uid_recent, camel_folder_change_info_recent_uid);
-}
-
-/**
- * camel_folder_change_info_add_uid:
- * @info: 
- * @uid: 
- * 
- * Add a new uid to the changeinfo.
- **/
-void
-camel_folder_change_info_add_uid(CamelFolderChangeInfo *info, const char *uid)
-{
-	struct _CamelFolderChangeInfoPrivate *p;
-	GPtrArray *olduids;
-	char *olduid;
-	
-	g_assert(info != NULL);
-	
-	p = info->priv;
-	
-	if (g_hash_table_lookup_extended(p->uid_stored, uid, (void **)&olduid, (void **)&olduids)) {
-		/* if it was removed then added, promote it to a changed */
-		/* if it was changed then added, leave as changed */
-		if (olduids == info->uid_removed) {
-			g_ptr_array_remove_fast(olduids, olduid);
-			g_ptr_array_add(info->uid_changed, olduid);
-			g_hash_table_insert(p->uid_stored, olduid, info->uid_changed);
-		}
-		return;
-	}
-
-	olduid = e_mempool_strdup(p->uid_pool, uid);
-	g_ptr_array_add(info->uid_added, olduid);
-	g_hash_table_insert(p->uid_stored, olduid, info->uid_added);
-}
-
-/**
- * camel_folder_change_info_remove_uid:
- * @info: 
- * @uid: 
- * 
- * Add a uid to the removed uid list.
- **/
-void
-camel_folder_change_info_remove_uid(CamelFolderChangeInfo *info, const char *uid)
-{
-	struct _CamelFolderChangeInfoPrivate *p;
-	GPtrArray *olduids;
-	char *olduid;
-	
-	g_assert(info != NULL);
-	
-	p = info->priv;
-	
-	if (g_hash_table_lookup_extended(p->uid_stored, uid, (void **)&olduid, (void **)&olduids)) {
-		/* if it was added/changed them removed, then remove it */
-		if (olduids != info->uid_removed) {
-			g_ptr_array_remove_fast(olduids, olduid);
-			g_ptr_array_add(info->uid_removed, olduid);
-			g_hash_table_insert(p->uid_stored, olduid, info->uid_removed);
-		}
-		return;
-	}
-
-	olduid = e_mempool_strdup(p->uid_pool, uid);
-	g_ptr_array_add(info->uid_removed, olduid);
-	g_hash_table_insert(p->uid_stored, olduid, info->uid_removed);
-}
-
-/**
- * camel_folder_change_info_change_uid:
- * @info: 
- * @uid: 
- * 
- * Add a uid to the changed uid list.
- **/
-void
-camel_folder_change_info_change_uid(CamelFolderChangeInfo *info, const char *uid)
-{
-	struct _CamelFolderChangeInfoPrivate *p;
-	GPtrArray *olduids;
-	char *olduid;
-	
-	g_assert(info != NULL);
-	
-	p = info->priv;
-	
-	if (g_hash_table_lookup_extended(p->uid_stored, uid, (void **)&olduid, (void **)&olduids)) {
-		/* if we have it already, leave it as that */
-		return;
-	}
-
-	olduid = e_mempool_strdup(p->uid_pool, uid);
-	g_ptr_array_add(info->uid_changed, olduid);
-	g_hash_table_insert(p->uid_stored, olduid, info->uid_changed);
-}
-
-void
-camel_folder_change_info_recent_uid(CamelFolderChangeInfo *info, const char *uid)
-{
-	struct _CamelFolderChangeInfoPrivate *p;
-	GPtrArray *olduids;
-	char *olduid;
-	
-	g_assert(info != NULL);
-	
-	p = info->priv;
-
-	/* always add to recent, but dont let anyone else know */	
-	if (!g_hash_table_lookup_extended(p->uid_stored, uid, (void **)&olduid, (void **)&olduids)) {
-		olduid = e_mempool_strdup(p->uid_pool, uid);
-	}
-	g_ptr_array_add(info->uid_recent, olduid);
-}
-
-/**
- * camel_folder_change_info_changed:
- * @info: 
- * 
- * Return true if the changeset contains any changes.
- *
- * Return Value:
- **/
-gboolean
-camel_folder_change_info_changed(CamelFolderChangeInfo *info)
-{
-	g_assert(info != NULL);
-	
-	return (info->uid_added->len || info->uid_removed->len || info->uid_changed->len || info->uid_recent->len);
-}
-
-/**
- * camel_folder_change_info_clear:
- * @info: 
- * 
- * Empty out the change info; called after changes have been processed.
- **/
-void
-camel_folder_change_info_clear(CamelFolderChangeInfo *info)
-{
-	struct _CamelFolderChangeInfoPrivate *p;
-	
-	g_assert(info != NULL);
-	
-	p = info->priv;
-	
-	g_ptr_array_set_size(info->uid_added, 0);
-	g_ptr_array_set_size(info->uid_removed, 0);
-	g_ptr_array_set_size(info->uid_changed, 0);
-	g_ptr_array_set_size(info->uid_recent, 0);
-	if (p->uid_source) {
-		g_hash_table_destroy(p->uid_source);
-		p->uid_source = NULL;
-	}
-	g_hash_table_destroy(p->uid_stored);
-	p->uid_stored = g_hash_table_new(g_str_hash, g_str_equal);
-	e_mempool_flush(p->uid_pool, TRUE);
-}
-
-/**
- * camel_folder_change_info_free:
- * @info: 
- * 
- * Free memory associated with the folder change info lists.
- **/
-void
-camel_folder_change_info_free(CamelFolderChangeInfo *info)
-{
-	struct _CamelFolderChangeInfoPrivate *p;
-
-	g_assert(info != NULL);
-	
-	p = info->priv;
-	
-	if (p->uid_source)
-		g_hash_table_destroy(p->uid_source);
-
-	g_hash_table_destroy(p->uid_stored);
-	e_mempool_destroy(p->uid_pool);
-	g_free(p);
-
-	g_ptr_array_free(info->uid_added, TRUE);
-	g_ptr_array_free(info->uid_removed, TRUE);
-	g_ptr_array_free(info->uid_changed, TRUE);
-	g_ptr_array_free(info->uid_recent, TRUE);
-	g_free(info);
-}
diff --git a/camel/camel-folder.h b/camel/camel-folder.h
deleted file mode 100644
index 83df665147..0000000000
--- a/camel/camel-folder.h
+++ /dev/null
@@ -1,348 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * camel-folder.h: Abstract class for an email folder
- *
- * Authors: Bertrand Guiheneuf 
- *	    Michael Zucchi 
- *
- * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of version 2 of the GNU General Public 
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-#ifndef CAMEL_FOLDER_H
-#define CAMEL_FOLDER_H 1
-
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include 
-#include 
-#include 
-
-#define CAMEL_FOLDER_TYPE     (camel_folder_get_type ())
-#define CAMEL_FOLDER(obj)     (CAMEL_CHECK_CAST((obj), CAMEL_FOLDER_TYPE, CamelFolder))
-#define CAMEL_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_FOLDER_TYPE, CamelFolderClass))
-#define CAMEL_IS_FOLDER(o)    (CAMEL_CHECK_TYPE((o), CAMEL_FOLDER_TYPE))
-
-typedef struct _CamelFolderChangeInfo CamelFolderChangeInfo;
-
-enum {
-	CAMEL_FOLDER_ARG_FIRST = CAMEL_ARG_FIRST + 0x1000,
-	CAMEL_FOLDER_ARG_NAME = CAMEL_FOLDER_ARG_FIRST,
-	CAMEL_FOLDER_ARG_FULL_NAME,
-	CAMEL_FOLDER_ARG_STORE,
-	CAMEL_FOLDER_ARG_PERMANENTFLAGS,
-	CAMEL_FOLDER_ARG_TOTAL,
-	CAMEL_FOLDER_ARG_UNREAD,
-	CAMEL_FOLDER_ARG_UID_ARRAY,
-	CAMEL_FOLDER_ARG_INFO_ARRAY,
-	CAMEL_FOLDER_ARG_PROPERTIES,
-	CAMEL_FOLDER_ARG_LAST = CAMEL_ARG_FIRST + 0x2000,
-};
-
-enum {
-	CAMEL_FOLDER_NAME = CAMEL_FOLDER_ARG_NAME | CAMEL_ARG_STR,
-	CAMEL_FOLDER_FULL_NAME = CAMEL_FOLDER_ARG_FULL_NAME | CAMEL_ARG_STR,
-	CAMEL_FOLDER_STORE = CAMEL_FOLDER_ARG_STORE | CAMEL_ARG_OBJ,
-	CAMEL_FOLDER_PERMANENTFLAGS = CAMEL_FOLDER_ARG_PERMANENTFLAGS | CAMEL_ARG_INT,
-	CAMEL_FOLDER_TOTAL = CAMEL_FOLDER_ARG_TOTAL | CAMEL_ARG_INT,
-	CAMEL_FOLDER_UNREAD = CAMEL_FOLDER_ARG_UNREAD | CAMEL_ARG_INT,
-	/* should we only get static data?  not stuff that needs to be free'd? */
-	CAMEL_FOLDER_UID_ARRAY = CAMEL_FOLDER_ARG_UID_ARRAY | CAMEL_ARG_PTR,
-	CAMEL_FOLDER_INFO_ARRAY = CAMEL_FOLDER_ARG_INFO_ARRAY | CAMEL_ARG_PTR,
-
-	/* GSList of settable folder properties */
-	CAMEL_FOLDER_PROPERTIES = CAMEL_FOLDER_ARG_PROPERTIES | CAMEL_ARG_PTR,
-};
-
-struct _CamelFolderChangeInfo {
-	GPtrArray *uid_added;
-	GPtrArray *uid_removed;
-	GPtrArray *uid_changed;
-	GPtrArray *uid_recent;
-
-	struct _CamelFolderChangeInfoPrivate *priv;
-};
-
-struct _CamelFolder
-{
-	CamelObject parent_object;
-
-	struct _CamelFolderPrivate *priv;
-
-	/* get these via the :get() method, they might not be set otherwise */
-	char *name;
-	char *full_name;
-	char *description;
-
-	CamelStore *parent_store;
-	CamelFolderSummary *summary;
-
-	guint32 folder_flags;
-	guint32 permanent_flags;
-};
-
-#define CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY (1<<0)
-#define CAMEL_FOLDER_HAS_SEARCH_CAPABILITY  (1<<1)
-#define CAMEL_FOLDER_FILTER_RECENT          (1<<2)
-#define CAMEL_FOLDER_HAS_BEEN_DELETED       (1<<3)
-#define CAMEL_FOLDER_IS_TRASH               (1<<4)
-#define CAMEL_FOLDER_IS_JUNK                (1<<5)
-
-typedef struct {
-	CamelObjectClass parent_class;
-
-	/* Virtual methods */	
-	void   (*refresh_info) (CamelFolder *folder, CamelException *ex);
-
-	void   (*sync) (CamelFolder *folder, gboolean expunge, 
-			CamelException *ex);
-
-	const char *  (*get_name)  (CamelFolder *folder);
-	const char *  (*get_full_name)   (CamelFolder *folder);
-
-	CamelStore *  (*get_parent_store) (CamelFolder *folder);
-
-	void (*expunge)  (CamelFolder *folder, 
-			  CamelException *ex);
-
-	int   (*get_message_count)   (CamelFolder *folder);
-
-	int   (*get_unread_message_count) (CamelFolder *folder);
-
-	void (*append_message)  (CamelFolder *folder, 
-				 CamelMimeMessage *message,
-				 const CamelMessageInfo *info,
-				 char **appended_uid,
-				 CamelException *ex);
-	
-	guint32 (*get_permanent_flags) (CamelFolder *folder);
-	guint32 (*get_message_flags)   (CamelFolder *folder,
-					const char *uid);
-	void    (*set_message_flags)   (CamelFolder *folder,
-					const char *uid,
-					guint32 flags, guint32 set);
-
-	gboolean (*get_message_user_flag) (CamelFolder *folder,
-					   const char *uid,
-					   const char *name);
-	void     (*set_message_user_flag) (CamelFolder *folder,
-					   const char *uid,
-					   const char *name,
-					   gboolean value);
-
-	const char * (*get_message_user_tag) (CamelFolder *folder,
-					      const char *uid,
-					      const char *name);
-	void     (*set_message_user_tag) (CamelFolder *folder,
-					  const char *uid,
-					  const char *name,
-					  const char *value);
-
-	CamelMimeMessage * (*get_message)  (CamelFolder *folder, 
-					    const char *uid, 
-					    CamelException *ex);
-
-	GPtrArray * (*get_uids)       (CamelFolder *folder);
-	void (*free_uids)             (CamelFolder *folder,
-				       GPtrArray *array);
-
-	GPtrArray * (*get_summary)    (CamelFolder *folder);
-	void (*free_summary)          (CamelFolder *folder,
-				       GPtrArray *summary);
-
-	gboolean (*has_search_capability) (CamelFolder *folder);
-
-	GPtrArray * (*search_by_expression) (CamelFolder *, const char *, CamelException *);
-	GPtrArray * (*search_by_uids) (CamelFolder *, const char *, GPtrArray *uids, CamelException *);
-
-	void (*search_free) (CamelFolder *folder, GPtrArray *result);
-
-	CamelMessageInfo * (*get_message_info) (CamelFolder *, const char *uid);
-	void (*ref_message_info) (CamelFolder *, CamelMessageInfo *);
-	void (*free_message_info) (CamelFolder *, CamelMessageInfo *);
-
-	void (*transfer_messages_to) (CamelFolder *source,
-				      GPtrArray *uids,
-				      CamelFolder *destination,
-				      GPtrArray **transferred_uids,
-				      gboolean delete_originals,
-				      CamelException *ex);
-	
-	void (*delete)           (CamelFolder *folder);
-	void (*rename)           (CamelFolder *folder, const char *newname);
-	
-	void     (*freeze)    (CamelFolder *folder);
-	void     (*thaw)      (CamelFolder *folder);
-	gboolean (*is_frozen) (CamelFolder *folder);
-} CamelFolderClass;
-
-/* Standard Camel function */
-CamelType camel_folder_get_type (void);
-
-
-/* public methods */
-void               camel_folder_construct              (CamelFolder *folder,
-							CamelStore *parent_store,
-							const char *full_name,
-							const char *name);
-
-void               camel_folder_refresh_info           (CamelFolder * folder, 
-							CamelException * ex);
-void               camel_folder_sync                   (CamelFolder *folder, 
-							gboolean expunge, 
-							CamelException *ex);
-
-CamelStore *       camel_folder_get_parent_store       (CamelFolder *folder);
-
-
-/* delete operations */
-void		   camel_folder_expunge                (CamelFolder *folder, 
-							CamelException *ex);
-
-
-/* folder name operations */
-const char *      camel_folder_get_name                (CamelFolder *folder);
-const char *      camel_folder_get_full_name           (CamelFolder *folder);
-
-
-/* various properties accessors */
-guint32		   camel_folder_get_permanent_flags    (CamelFolder *folder);
-
-guint32		   camel_folder_get_message_flags      (CamelFolder *folder,
-							const char *uid);
-
-void		   camel_folder_set_message_flags      (CamelFolder *folder,
-							const char *uid,
-							guint32 flags,
-							guint32 set);
-
-gboolean	   camel_folder_get_message_user_flag  (CamelFolder *folder,
-							const char *uid,
-							const char *name);
-
-void		   camel_folder_set_message_user_flag  (CamelFolder *folder,
-							const char *uid,
-							const char *name,
-							gboolean value);
-const char *	   camel_folder_get_message_user_tag  (CamelFolder *folder,
-						       const char *uid,
-						       const char *name);
-
-void		   camel_folder_set_message_user_tag  (CamelFolder *folder,
-						       const char *uid,
-						       const char *name,
-						       const char *value);
-
-
-
-/* message manipulation */
-void               camel_folder_append_message         (CamelFolder *folder, 
-							CamelMimeMessage *message,
-							const CamelMessageInfo *info,
-							char **appended_uid,
-							CamelException *ex);
-
-
-/* summary related operations */
-gboolean           camel_folder_has_summary_capability (CamelFolder *folder);
-
-
-int                camel_folder_get_message_count     (CamelFolder *folder);
-
-int                camel_folder_get_unread_message_count (CamelFolder *folder);
-
-GPtrArray *        camel_folder_get_summary           (CamelFolder *folder);
-void               camel_folder_free_summary          (CamelFolder *folder,
-						       GPtrArray *array);
-
-/* uid based access operations */
-CamelMimeMessage * camel_folder_get_message           (CamelFolder *folder, 
-						       const char *uid, 
-						       CamelException *ex);
-#define camel_folder_delete_message(folder, uid) \
-	camel_folder_set_message_flags (folder, uid, CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_DELETED)
-
-GPtrArray *        camel_folder_get_uids              (CamelFolder *folder);
-void               camel_folder_free_uids             (CamelFolder *folder,
-						       GPtrArray *array);
-
-/* search api */
-gboolean           camel_folder_has_search_capability (CamelFolder *folder);
-GPtrArray *	   camel_folder_search_by_expression  (CamelFolder *folder, const char *expr, CamelException *ex);
-GPtrArray *	   camel_folder_search_by_uids	      (CamelFolder *folder, const char *expr, GPtrArray *uids, CamelException *ex);
-void		   camel_folder_search_free	      (CamelFolder *folder, GPtrArray *);
-
-/* summary info */
-CamelMessageInfo *camel_folder_get_message_info		(CamelFolder *folder, const char *uid);
-void		  camel_folder_free_message_info	(CamelFolder *folder, CamelMessageInfo *info);
-void		  camel_folder_ref_message_info		(CamelFolder *folder, CamelMessageInfo *info);
-
-void               camel_folder_transfer_messages_to   (CamelFolder *source,
-							GPtrArray *uids,
-							CamelFolder *dest,
-							GPtrArray **transferred_uids,
-							gboolean delete_originals,
-							CamelException *ex);
-
-void               camel_folder_delete                 (CamelFolder *folder);
-void               camel_folder_rename                 (CamelFolder *folder, const char *new);
-
-/* stop/restart getting events */
-void               camel_folder_freeze                (CamelFolder *folder);
-void               camel_folder_thaw                  (CamelFolder *folder);
-gboolean           camel_folder_is_frozen             (CamelFolder *folder);
-
-#if 0
-/* lock/unlock at the thread level, NOTE: only used internally */
-void		   camel_folder_lock		      (CamelFolder *folder);
-void		   camel_folder_unlock		      (CamelFolder *folder);
-#endif
-
-/* For use by subclasses (for free_{uids,summary,subfolder_names}) */
-void camel_folder_free_nop     (CamelFolder *folder, GPtrArray *array);
-void camel_folder_free_shallow (CamelFolder *folder, GPtrArray *array);
-void camel_folder_free_deep    (CamelFolder *folder, GPtrArray *array);
-
-/* update functions for change info */
-CamelFolderChangeInfo *	camel_folder_change_info_new		(void);
-void			camel_folder_change_info_clear		(CamelFolderChangeInfo *info);
-void			camel_folder_change_info_free		(CamelFolderChangeInfo *info);
-gboolean		camel_folder_change_info_changed	(CamelFolderChangeInfo *info);
-
-/* for building diff's automatically */
-void			camel_folder_change_info_add_source	(CamelFolderChangeInfo *info, const char *uid);
-void			camel_folder_change_info_add_source_list(CamelFolderChangeInfo *info, const GPtrArray *list);
-void			camel_folder_change_info_add_update	(CamelFolderChangeInfo *info, const char *uid);
-void			camel_folder_change_info_add_update_list(CamelFolderChangeInfo *info, const GPtrArray *list);
-void			camel_folder_change_info_build_diff	(CamelFolderChangeInfo *info);
-
-/* for manipulating diff's directly */
-void			camel_folder_change_info_cat		(CamelFolderChangeInfo *info, CamelFolderChangeInfo *s);
-void			camel_folder_change_info_add_uid	(CamelFolderChangeInfo *info, const char *uid);
-void			camel_folder_change_info_remove_uid	(CamelFolderChangeInfo *info, const char *uid);
-void			camel_folder_change_info_change_uid	(CamelFolderChangeInfo *info, const char *uid);
-void			camel_folder_change_info_recent_uid	(CamelFolderChangeInfo *info, const char *uid);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_FOLDER_H */
-
diff --git a/camel/camel-gpg-context.c b/camel/camel-gpg-context.c
deleted file mode 100644
index f7f52fd7fd..0000000000
--- a/camel/camel-gpg-context.c
+++ /dev/null
@@ -1,1794 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *
- *  Copyright 2002 Ximian, Inc. (www.ximian.com)
- *
- *  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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "gal/util/e-iconv.h"
-
-#include "camel-gpg-context.h"
-#include "camel-mime-filter-charset.h"
-#include "camel-stream-filter.h"
-#include "camel-stream-mem.h"
-#include "camel-stream-fs.h"
-#include "camel-operation.h"
-#include "camel-mime-part.h"
-#include "camel-mime-filter-canon.h"
-
-#include "camel-multipart-signed.h"
-#include "camel-multipart-encrypted.h"
-
-#define d(x)
-
-static CamelCipherContextClass *parent_class = NULL;
-
-/**
- * camel_gpg_context_new:
- * @session: session
- *
- * Creates a new gpg cipher context object.
- *
- * Returns a new gpg cipher context object.
- **/
-CamelCipherContext *
-camel_gpg_context_new (CamelSession *session)
-{
-	CamelCipherContext *cipher;
-	CamelGpgContext *ctx;
-	
-	g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
-	
-	ctx = (CamelGpgContext *) camel_object_new (camel_gpg_context_get_type ());
-	
-	cipher = (CamelCipherContext *) ctx;
-	cipher->session = session;
-	camel_object_ref (session);
-	
-	return cipher;
-}
-
-
-/**
- * camel_gpg_context_set_always_trust:
- * @ctx: gpg context
- * @always_trust always truct flag
- *
- * Sets the @always_trust flag on the gpg context which is used for
- * encryption.
- **/
-void
-camel_gpg_context_set_always_trust (CamelGpgContext *ctx, gboolean always_trust)
-{
-	g_return_if_fail (CAMEL_IS_GPG_CONTEXT (ctx));
-	
-	ctx->always_trust = always_trust;
-}
-
-
-static const char *
-gpg_hash_to_id (CamelCipherContext *context, CamelCipherHash hash)
-{
-	switch (hash) {
-	case CAMEL_CIPHER_HASH_MD2:
-		return "pgp-md2";
-	case CAMEL_CIPHER_HASH_MD5:
-		return "pgp-md5";
-	case CAMEL_CIPHER_HASH_SHA1:
-	case CAMEL_CIPHER_HASH_DEFAULT:
-		return "pgp-sha1";
-	case CAMEL_CIPHER_HASH_RIPEMD160:
-		return "pgp-ripemd160";
-	case CAMEL_CIPHER_HASH_TIGER192:
-		return "pgp-tiger192";
-	case CAMEL_CIPHER_HASH_HAVAL5160:
-		return "pgp-haval-5-160";
-	}
-	
-	return NULL;
-}
-
-static CamelCipherHash
-gpg_id_to_hash (CamelCipherContext *context, const char *id)
-{
-	if (id) {
-		if (!strcmp (id, "pgp-md2"))
-			return CAMEL_CIPHER_HASH_MD2;
-		else if (!strcmp (id, "pgp-md5"))
-			return CAMEL_CIPHER_HASH_MD5;
-		else if (!strcmp (id, "pgp-sha1"))
-			return CAMEL_CIPHER_HASH_SHA1;
-		else if (!strcmp (id, "pgp-ripemd160"))
-			return CAMEL_CIPHER_HASH_RIPEMD160;
-		else if (!strcmp (id, "tiger192"))
-			return CAMEL_CIPHER_HASH_TIGER192;
-		else if (!strcmp (id, "haval-5-160"))
-			return CAMEL_CIPHER_HASH_HAVAL5160;
-	}
-	
-	return CAMEL_CIPHER_HASH_DEFAULT;
-}
-
-
-enum _GpgCtxMode {
-	GPG_CTX_MODE_SIGN,
-	GPG_CTX_MODE_VERIFY,
-	GPG_CTX_MODE_ENCRYPT,
-	GPG_CTX_MODE_DECRYPT,
-	GPG_CTX_MODE_IMPORT,
-	GPG_CTX_MODE_EXPORT,
-};
-
-enum _GpgTrustMetric {
-	GPG_TRUST_UNKNOWN,
-	GPG_TRUST_NEVER,
-	GPG_TRUST_MARGINAL,
-	GPG_TRUST_FULLY,
-	GPG_TRUST_ULTIMATE
-};
-
-struct _GpgCtx {
-	enum _GpgCtxMode mode;
-	CamelSession *session;
-	GHashTable *userid_hint;
-	pid_t pid;
-	
-	char *userid;
-	char *sigfile;
-	GPtrArray *recipients;
-	CamelCipherHash hash;
-	
-	int stdin_fd;
-	int stdout_fd;
-	int stderr_fd;
-	int status_fd;
-	int passwd_fd;  /* only needed for sign/decrypt */
-	
-	/* status-fd buffer */
-	unsigned char *statusbuf;
-	unsigned char *statusptr;
-	unsigned int statusleft;
-	
-	char *passwd;
-	
-	CamelStream *istream;
-	CamelStream *ostream;
-	
-	GByteArray *diagbuf;
-	CamelStream *diagnostics;
-	
-	int exit_status;
-	
-	unsigned int exited:1;
-	unsigned int complete:1;
-	unsigned int seen_eof1:1;
-	unsigned int seen_eof2:1;
-	unsigned int always_trust:1;
-	unsigned int armor:1;
-	unsigned int need_passwd:1;
-	unsigned int send_passwd:1;
-	
-	unsigned int bad_passwds:2;
-	
-	unsigned int validsig:1;
-	unsigned int trust:3;
-	
-	unsigned int diagflushed:1;
-	
-	unsigned int utf8:1;
-	
-	unsigned int padding:16;
-};
-
-static struct _GpgCtx *
-gpg_ctx_new (CamelSession *session)
-{
-	struct _GpgCtx *gpg;
-	const char *charset;
-	CamelStream *stream;
-	
-	gpg = g_new (struct _GpgCtx, 1);
-	gpg->mode = GPG_CTX_MODE_SIGN;
-	gpg->session = session;
-	camel_object_ref (session);
-	gpg->userid_hint = g_hash_table_new (g_str_hash, g_str_equal);
-	gpg->complete = FALSE;
-	gpg->seen_eof1 = TRUE;
-	gpg->seen_eof2 = FALSE;
-	gpg->pid = (pid_t) -1;
-	gpg->exit_status = 0;
-	gpg->exited = FALSE;
-	
-	gpg->userid = NULL;
-	gpg->sigfile = NULL;
-	gpg->recipients = NULL;
-	gpg->hash = CAMEL_CIPHER_HASH_DEFAULT;
-	gpg->always_trust = FALSE;
-	gpg->armor = FALSE;
-	
-	gpg->stdin_fd = -1;
-	gpg->stdout_fd = -1;
-	gpg->stderr_fd = -1;
-	gpg->status_fd = -1;
-	gpg->passwd_fd = -1;
-	
-	gpg->statusbuf = g_malloc (128);
-	gpg->statusptr = gpg->statusbuf;
-	gpg->statusleft = 128;
-	
-	gpg->bad_passwds = 0;
-	gpg->need_passwd = FALSE;
-	gpg->send_passwd = FALSE;
-	gpg->passwd = NULL;
-	
-	gpg->validsig = FALSE;
-	gpg->trust = GPG_TRUST_UNKNOWN;
-	
-	gpg->istream = NULL;
-	gpg->ostream = NULL;
-	
-	stream = camel_stream_mem_new ();
-	gpg->diagbuf = CAMEL_STREAM_MEM (stream)->buffer;
-	gpg->diagflushed = FALSE;
-	
-	if ((charset = e_iconv_locale_charset ()) && strcasecmp (charset, "UTF-8") != 0) {
-		CamelMimeFilterCharset *filter;
-		CamelStreamFilter *fstream;
-		
-		gpg->utf8 = FALSE;
-		
-		if ((filter = camel_mime_filter_charset_new_convert (charset, "UTF-8"))) {
-			fstream = camel_stream_filter_new_with_stream (stream);
-			camel_stream_filter_add (fstream, (CamelMimeFilter *) filter);
-			camel_object_unref (filter);
-			camel_object_unref (stream);
-			
-			stream = (CamelStream *) fstream;
-		}
-	} else {
-		gpg->utf8 = TRUE;
-	}
-	
-	gpg->diagnostics = stream;
-	
-	return gpg;
-}
-
-static void
-gpg_ctx_set_mode (struct _GpgCtx *gpg, enum _GpgCtxMode mode)
-{
-	gpg->mode = mode;
-	gpg->need_passwd = ((gpg->mode == GPG_CTX_MODE_SIGN) || (gpg->mode == GPG_CTX_MODE_DECRYPT));
-}
-
-static void
-gpg_ctx_set_hash (struct _GpgCtx *gpg, CamelCipherHash hash)
-{
-	gpg->hash = hash;
-}
-
-static void
-gpg_ctx_set_always_trust (struct _GpgCtx *gpg, gboolean trust)
-{
-	gpg->always_trust = trust;
-}
-
-static void
-gpg_ctx_set_userid (struct _GpgCtx *gpg, const char *userid)
-{
-	g_free (gpg->userid);
-	gpg->userid = g_strdup (userid);
-}
-
-static void
-gpg_ctx_add_recipient (struct _GpgCtx *gpg, const char *keyid)
-{
-	if (gpg->mode != GPG_CTX_MODE_ENCRYPT && gpg->mode != GPG_CTX_MODE_EXPORT)
-		return;
-	
-	if (!gpg->recipients)
-		gpg->recipients = g_ptr_array_new ();
-	
-	g_ptr_array_add (gpg->recipients, g_strdup (keyid));
-}
-
-static void
-gpg_ctx_set_sigfile (struct _GpgCtx *gpg, const char *sigfile)
-{
-	g_free (gpg->sigfile);
-	gpg->sigfile = g_strdup (sigfile);
-}
-
-static void
-gpg_ctx_set_armor (struct _GpgCtx *gpg, gboolean armor)
-{
-	gpg->armor = armor;
-}
-
-static void
-gpg_ctx_set_istream (struct _GpgCtx *gpg, CamelStream *istream)
-{
-	camel_object_ref (istream);
-	if (gpg->istream)
-		camel_object_unref (gpg->istream);
-	gpg->istream = istream;
-}
-
-static void
-gpg_ctx_set_ostream (struct _GpgCtx *gpg, CamelStream *ostream)
-{
-	camel_object_ref (ostream);
-	if (gpg->ostream)
-		camel_object_unref (gpg->ostream);
-	gpg->ostream = ostream;
-	gpg->seen_eof1 = FALSE;
-}
-
-static const char *
-gpg_ctx_get_diagnostics (struct _GpgCtx *gpg)
-{
-	if (!gpg->diagflushed) {
-		gpg->diagflushed = TRUE;
-		camel_stream_flush (gpg->diagnostics);
-		if (gpg->diagbuf->len == 0)
-			return NULL;
-		
-		g_byte_array_append (gpg->diagbuf, "", 1);
-	}
-	
-	return gpg->diagbuf->data;
-}
-
-static void
-userid_hint_free (gpointer key, gpointer value, gpointer user_data)
-{
-	g_free (key);
-	g_free (value);
-}
-
-static void
-gpg_ctx_free (struct _GpgCtx *gpg)
-{
-	int i;
-
-	if (gpg == NULL)
-		return;
-
-	if (gpg->session)
-		camel_object_unref (gpg->session);
-	
-	g_hash_table_foreach (gpg->userid_hint, userid_hint_free, NULL);
-	g_hash_table_destroy (gpg->userid_hint);
-	
-	g_free (gpg->userid);
-	
-	g_free (gpg->sigfile);
-	
-	if (gpg->recipients) {
-		for (i = 0; i < gpg->recipients->len; i++)
-			g_free (gpg->recipients->pdata[i]);
-	
-		g_ptr_array_free (gpg->recipients, TRUE);
-	}
-	
-	if (gpg->stdin_fd != -1)
-		close (gpg->stdin_fd);
-	if (gpg->stdout_fd != -1)
-		close (gpg->stdout_fd);
-	if (gpg->stderr_fd != -1)
-		close (gpg->stderr_fd);
-	if (gpg->status_fd != -1)
-		close (gpg->status_fd);
-	if (gpg->passwd_fd != -1)
-		close (gpg->passwd_fd);
-	
-	g_free (gpg->statusbuf);
-	
-	if (gpg->passwd)
-		g_free (gpg->passwd);
-	
-	if (gpg->istream)
-		camel_object_unref (gpg->istream);
-	
-	if (gpg->ostream)
-		camel_object_unref (gpg->ostream);
-	
-	camel_object_unref (gpg->diagnostics);
-	
-	g_free (gpg);
-}
-
-static const char *
-gpg_hash_str (CamelCipherHash hash)
-{
-	switch (hash) {
-	case CAMEL_CIPHER_HASH_MD2:
-		return "--digest-algo=MD2";
-	case CAMEL_CIPHER_HASH_MD5:
-		return "--digest-algo=MD5";
-	case CAMEL_CIPHER_HASH_SHA1:
-		return "--digest-algo=SHA1";
-	case CAMEL_CIPHER_HASH_RIPEMD160:
-		return "--digest-algo=RIPEMD160";
-	default:
-		return NULL;
-	}
-}
-
-static GPtrArray *
-gpg_ctx_get_argv (struct _GpgCtx *gpg, int status_fd, char **sfd, int passwd_fd, char **pfd)
-{
-	const char *hash_str;
-	GPtrArray *argv;
-	char *buf;
-	int i;
-	
-	argv = g_ptr_array_new ();
-	g_ptr_array_add (argv, "gpg");
-	
-	g_ptr_array_add (argv, "--verbose");
-	g_ptr_array_add (argv, "--no-secmem-warning");
-	g_ptr_array_add (argv, "--no-greeting");
-	g_ptr_array_add (argv, "--no-tty");
-	if (passwd_fd == -1) {
-		/* only use batch mode if we don't intend on using the
-                   interactive --command-fd option */
-		g_ptr_array_add (argv, "--batch");
-		g_ptr_array_add (argv, "--yes");
-	}
-	
-	*sfd = buf = g_strdup_printf ("--status-fd=%d", status_fd);
-	g_ptr_array_add (argv, buf);
-	
-	if (passwd_fd != -1) {
-		*pfd = buf = g_strdup_printf ("--command-fd=%d", passwd_fd);
-		g_ptr_array_add (argv, buf);
-	}
-	
-	switch (gpg->mode) {
-	case GPG_CTX_MODE_SIGN:
-		g_ptr_array_add (argv, "--sign");
-		g_ptr_array_add (argv, "--detach");
-		if (gpg->armor)
-			g_ptr_array_add (argv, "--armor");
-		hash_str = gpg_hash_str (gpg->hash);
-		if (hash_str)
-			g_ptr_array_add (argv, (char *) hash_str);
-		if (gpg->userid) {
-			g_ptr_array_add (argv, "-u");
-			g_ptr_array_add (argv, (char *) gpg->userid);
-		}
-		g_ptr_array_add (argv, "--output");
-		g_ptr_array_add (argv, "-");
-		break;
-	case GPG_CTX_MODE_VERIFY:
-		if (!camel_session_is_online (gpg->session)) {
-			/* this is a deprecated flag to gpg since 1.0.7 */
-			/*g_ptr_array_add (argv, "--no-auto-key-retrieve");*/
-			g_ptr_array_add (argv, "--keyserver-options");
-			g_ptr_array_add (argv, "no-auto-key-retrieve");
-		}
-		g_ptr_array_add (argv, "--verify");
-		if (gpg->sigfile)
-			g_ptr_array_add (argv, gpg->sigfile);
-		g_ptr_array_add (argv, "-");
-		break;
-	case GPG_CTX_MODE_ENCRYPT:
-		g_ptr_array_add (argv,  "--encrypt");
-		if (gpg->armor)
-			g_ptr_array_add (argv, "--armor");
-		if (gpg->always_trust)
-			g_ptr_array_add (argv, "--always-trust");
-		if (gpg->userid) {
-			g_ptr_array_add (argv, "-u");
-			g_ptr_array_add (argv, (char *) gpg->userid);
-		}
-		if (gpg->recipients) {
-			for (i = 0; i < gpg->recipients->len; i++) {
-				g_ptr_array_add (argv, "-r");
-				g_ptr_array_add (argv, gpg->recipients->pdata[i]);
-			}
-		}
-		g_ptr_array_add (argv, "--output");
-		g_ptr_array_add (argv, "-");
-		break;
-	case GPG_CTX_MODE_DECRYPT:
-		g_ptr_array_add (argv, "--decrypt");
-		g_ptr_array_add (argv, "--output");
-		g_ptr_array_add (argv, "-");
-		break;
-	case GPG_CTX_MODE_IMPORT:
-		g_ptr_array_add (argv, "--import");
-		g_ptr_array_add (argv, "-");
-		break;
-	case GPG_CTX_MODE_EXPORT:
-		if (gpg->armor)
-			g_ptr_array_add (argv, "--armor");
-		g_ptr_array_add (argv, "--export");
-		for (i = 0; i < gpg->recipients->len; i++)
-			g_ptr_array_add (argv, gpg->recipients->pdata[i]);
-		break;
-	}
-	
-	g_ptr_array_add (argv, NULL);
-	
-	return argv;
-}
-
-static int
-gpg_ctx_op_start (struct _GpgCtx *gpg)
-{
-	char *status_fd = NULL, *passwd_fd = NULL;
-	int i, maxfd, errnosave, fds[10];
-	GPtrArray *argv;
-	int flags;
-	
-	for (i = 0; i < 10; i++)
-		fds[i] = -1;
-	
-	maxfd = gpg->need_passwd ? 10 : 8;
-	for (i = 0; i < maxfd; i += 2) {
-		if (pipe (fds + i) == -1)
-			goto exception;
-	}
-	
-	argv = gpg_ctx_get_argv (gpg, fds[7], &status_fd, fds[8], &passwd_fd);
-	
-	if (!(gpg->pid = fork ())) {
-		/* child process */
-		
-		if ((dup2 (fds[0], STDIN_FILENO) < 0 ) ||
-		    (dup2 (fds[3], STDOUT_FILENO) < 0 ) ||
-		    (dup2 (fds[5], STDERR_FILENO) < 0 )) {
-			_exit (255);
-		}
-		
-		/* Dissociate from camel's controlling terminal so
-		 * that gpg won't be able to read from it.
-		 */
-		setsid ();
-		
-		maxfd = sysconf (_SC_OPEN_MAX);
-		/* Loop over all fds. */
-		for (i = 3; i < maxfd; i++) {
-			/* don't close the status-fd or passwd-fd */
-			if (i != fds[7] && i != fds[8])
-				fcntl (i, F_SETFD, FD_CLOEXEC);
-		}
-		
-		/* run gpg */
-		execvp ("gpg", (char **) argv->pdata);
-		_exit (255);
-	} else if (gpg->pid < 0) {
-		g_ptr_array_free (argv, TRUE);
-		g_free (status_fd);
-		g_free (passwd_fd);
-		goto exception;
-	}
-	
-	g_ptr_array_free (argv, TRUE);
-	g_free (status_fd);
-	g_free (passwd_fd);
-	
-	/* Parent */
-	close (fds[0]);
-	gpg->stdin_fd = fds[1];
-	gpg->stdout_fd = fds[2];
-	close (fds[3]);
-	gpg->stderr_fd = fds[4];
-	close (fds[5]);
-	gpg->status_fd = fds[6];
-	close (fds[7]);
-	if (gpg->need_passwd) {
-		close (fds[8]);
-		gpg->passwd_fd = fds[9];
-		flags = fcntl (gpg->passwd_fd, F_GETFL);
-		fcntl (gpg->passwd_fd, F_SETFL, flags | O_NONBLOCK);
-	}
-	
-	flags = fcntl (gpg->stdin_fd, F_GETFL);
-	fcntl (gpg->stdin_fd, F_SETFL, flags | O_NONBLOCK);
-	
-	flags = fcntl (gpg->stdout_fd, F_GETFL);
-	fcntl (gpg->stdout_fd, F_SETFL, flags | O_NONBLOCK);
-	
-	flags = fcntl (gpg->stderr_fd, F_GETFL);
-	fcntl (gpg->stderr_fd, F_SETFL, flags | O_NONBLOCK);
-	
-	flags = fcntl (gpg->status_fd, F_GETFL);
-	fcntl (gpg->status_fd, F_SETFL, flags | O_NONBLOCK);
-	
-	return 0;
-	
- exception:
-	
-	errnosave = errno;
-	
-	for (i = 0; i < 10; i++) {
-		if (fds[i] != -1)
-			close (fds[i]);
-	}
-	
-	errno = errnosave;
-	
-	return -1;
-}
-
-static const char *
-next_token (const char *in, char **token)
-{
-	const char *start, *inptr = in;
-	
-	while (*inptr == ' ')
-		inptr++;
-	
-	if (*inptr == '\0' || *inptr == '\n') {
-		if (token)
-			*token = NULL;
-		return inptr;
-	}
-	
-	start = inptr;
-	while (*inptr && *inptr != ' ' && *inptr != '\n')
-		inptr++;
-	
-	if (token)
-		*token = g_strndup (start, inptr - start);
-	
-	return inptr;
-}
-
-static int
-gpg_ctx_parse_status (struct _GpgCtx *gpg, CamelException *ex)
-{
-	register unsigned char *inptr;
-	const unsigned char *status;
-	size_t nread, nwritten;
-	int len;
-	
- parse:
-	
-	inptr = gpg->statusbuf;
-	while (inptr < gpg->statusptr && *inptr != '\n')
-		inptr++;
-	
-	if (*inptr != '\n') {
-		/* we don't have enough data buffered to parse this status line */
-		return 0;
-	}
-	
-	*inptr++ = '\0';
-	status = gpg->statusbuf;
-	
-	d(printf ("status: %s\n", status));
-	
-	if (strncmp (status, "[GNUPG:] ", 9) != 0) {
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Unexpected GnuPG status message encountered:\n\n%s"),
-				      status);
-		return -1;
-	}
-	
-	status += 9;
-	
-	if (!strncmp (status, "USERID_HINT ", 12)) {
-		char *hint, *user;
-		
-		status += 12;
-		status = next_token (status, &hint);
-		if (!hint) {
-			camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-					     _("Failed to parse gpg userid hint."));
-			return -1;
-		}
-		
-		if (g_hash_table_lookup (gpg->userid_hint, hint)) {
-			/* we already have this userid hint... */
-			g_free (hint);
-			goto recycle;
-		}
-		
-		if (gpg->utf8 || !(user = g_locale_to_utf8 (status, -1, &nread, &nwritten, NULL)))
-			user = g_strdup (status);
-		
-		g_strstrip (user);
-		
-		g_hash_table_insert (gpg->userid_hint, hint, user);
-	} else if (!strncmp (status, "NEED_PASSPHRASE ", 16)) {
-		char *prompt, *userid, *passwd;
-		const char *name;
-		
-		status += 16;
-		
-		status = next_token (status, &userid);
-		if (!userid) {
-			camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-					     _("Failed to parse gpg passphrase request."));
-			return -1;
-		}
-		
-		name = g_hash_table_lookup (gpg->userid_hint, userid);
-		if (!name)
-			name = userid;
-		
-		prompt = g_strdup_printf (_("You need a passphrase to unlock the key for\n"
-					    "user: \"%s\""), name);
-		
-		if ((passwd = camel_session_get_password (gpg->session, prompt, FALSE, TRUE, NULL, userid, ex)) && !gpg->utf8) {
-			char *opasswd = passwd;
-			
-			if ((passwd = g_locale_to_utf8 (passwd, -1, &nread, &nwritten, NULL))) {
-				memset (opasswd, 0, strlen (opasswd));
-				g_free (opasswd);
-			} else {
-				passwd = opasswd;
-			}
-		}
-		g_free (prompt);
-		
-		g_free (gpg->userid);
-		gpg->userid = userid;
-		
-		if (passwd == NULL) {
-			if (!camel_exception_is_set (ex))
-				camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled."));
-			return -1;
-		}
-		
-		gpg->passwd = g_strdup_printf ("%s\n", passwd);
-		memset (passwd, 0, strlen (passwd));
-		g_free (passwd);
-		
-		gpg->send_passwd = TRUE;
-	} else if (!strncmp (status, "GOOD_PASSPHRASE", 15)) {
-		gpg->bad_passwds = 0;
-	} else if (!strncmp (status, "BAD_PASSPHRASE", 14)) {
-		gpg->bad_passwds++;
-		
-		camel_session_forget_password (gpg->session, NULL, gpg->userid, ex);
-		
-		if (gpg->bad_passwds == 3) {
-			camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
-					     _("Failed to unlock secret key: 3 bad passphrases given."));
-			return -1;
-		}
-	} else if (!strncmp (status, "UNEXPECTED ", 11)) {
-		/* this is an error */
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Unexpected response from GnuPG: %s"),
-				      status + 11);
-		return -1;
-	} else if (!strncmp (status, "NODATA", 6)) {
-		/* this is an error */
-		const char *diagnostics;
-		
-		diagnostics = gpg_ctx_get_diagnostics (gpg);
-		if (diagnostics && *diagnostics)
-			camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, diagnostics);
-		else
-			camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-					     _("No data provided"));
-		return -1;
-	} else {
-		/* check to see if we are complete */
-		switch (gpg->mode) {
-		case GPG_CTX_MODE_SIGN:
-			if (!strncmp (status, "SIG_CREATED ", 12)) {
-				/* FIXME: save this state? */
-			}
-			break;
-		case GPG_CTX_MODE_VERIFY:
-			if (!strncmp (status, "TRUST_", 6)) {
-				status += 6;
-				if (!strncmp (status, "NEVER", 5)) {
-					gpg->trust = GPG_TRUST_NEVER;
-				} else if (!strncmp (status, "MARGINAL", 8)) {
-					gpg->trust = GPG_TRUST_MARGINAL;
-				} else if (!strncmp (status, "FULLY", 5)) {
-					gpg->trust = GPG_TRUST_FULLY;
-				} else if (!strncmp (status, "ULTIMATE", 8)) {
-					gpg->trust = GPG_TRUST_ULTIMATE;
-				}
-			} else if (!strncmp (status, "VALIDSIG", 8)) {
-				gpg->validsig = TRUE;
-			} else if (!strncmp (status, "BADSIG", 6)) {
-				gpg->validsig = FALSE;
-			} else if (!strncmp (status, "ERRSIG", 6)) {
-				/* Note: NO_PUBKEY often comes after an ERRSIG, but do we really care? */
-				gpg->validsig = FALSE;
-			}
-			break;
-		case GPG_CTX_MODE_ENCRYPT:
-			if (!strncmp (status, "BEGIN_ENCRYPTION", 16)) {
-				/* nothing to do... but we know to expect data on stdout soon */
-			} else if (!strncmp (status, "END_ENCRYPTION", 14)) {
-				/* nothing to do, but we know the end is near? */
-			} else if (!strncmp (status, "NO_RECP", 7)) {
-				camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-						     _("Failed to encrypt: No valid recipients specified."));
-				return -1;
-			}
-			break;
-		case GPG_CTX_MODE_DECRYPT:
-			if (!strncmp (status, "BEGIN_DECRYPTION", 16)) {
-				/* nothing to do... but we know to expect data on stdout soon */
-			} else if (!strncmp (status, "END_DECRYPTION", 14)) {
-				/* nothing to do, but we know the end is near? */
-			}
-			break;
-		case GPG_CTX_MODE_IMPORT:
-			/* noop */
-			break;
-		case GPG_CTX_MODE_EXPORT:
-			/* noop */
-			break;
-		}
-	}
-	
- recycle:
-	
-	/* recycle our statusbuf by moving inptr to the beginning of statusbuf */
-	len = gpg->statusptr - inptr;
-	memmove (gpg->statusbuf, inptr, len);
-	
-	len = inptr - gpg->statusbuf;
-	gpg->statusleft += len;
-	gpg->statusptr -= len;
-	
-	/* if we have more data, try parsing the next line? */
-	if (gpg->statusptr > gpg->statusbuf)
-		goto parse;
-	
-	return 0;
-}
-
-#define status_backup(gpg, start, len) G_STMT_START {                     \
-	if (gpg->statusleft <= len) {                                     \
-		unsigned int slen, soff;                                  \
-		                                                          \
-		slen = soff = gpg->statusptr - gpg->statusbuf;            \
-		slen = slen ? slen : 1;                                   \
-		                                                          \
-		while (slen < soff + len)                                 \
-			slen <<= 1;                                       \
-		                                                          \
-		gpg->statusbuf = g_realloc (gpg->statusbuf, slen + 1);    \
-		gpg->statusptr = gpg->statusbuf + soff;                   \
-		gpg->statusleft = slen - soff;                            \
-	}                                                                 \
-	                                                                  \
-	memcpy (gpg->statusptr, start, len);                              \
-	gpg->statusptr += len;                                            \
-	gpg->statusleft -= len;                                           \
-} G_STMT_END
-
-static int
-gpg_ctx_op_step (struct _GpgCtx *gpg, CamelException *ex)
-{
-	fd_set rdset, wrset, *wrsetp = NULL;
-	const char *diagnostics;
-	struct timeval timeout;
-	const char *mode;
-	int maxfd = 0;
-	int ready;
-	
- retry:
-	FD_ZERO (&rdset);
-	
-	if (!gpg->seen_eof1) {
-		FD_SET (gpg->stdout_fd, &rdset);
-		maxfd = MAX (maxfd, gpg->stdout_fd);
-	}
-	
-	if (!gpg->seen_eof2) {
-		FD_SET (gpg->stderr_fd, &rdset);
-		maxfd = MAX (maxfd, gpg->stderr_fd);
-	}
-	
-	if (!gpg->complete) {
-		FD_SET (gpg->status_fd, &rdset);
-		maxfd = MAX (maxfd, gpg->status_fd);
-	}
-	
-	if (gpg->stdin_fd != -1 || gpg->passwd_fd != -1) {
-		FD_ZERO (&wrset);
-		if (gpg->stdin_fd != -1) {
-			FD_SET (gpg->stdin_fd, &wrset);
-			maxfd = MAX (maxfd, gpg->stdin_fd);
-		}
-		if (gpg->passwd_fd != -1) {
-			FD_SET (gpg->passwd_fd, &wrset);
-			maxfd = MAX (maxfd, gpg->passwd_fd);
-		}
-		
-		wrsetp = &wrset;
-	}
-	
-	g_assert (maxfd > 0);
-	
-	timeout.tv_sec = 10; /* timeout in seconds */
-	timeout.tv_usec = 0;
-	
-	if ((ready = select (maxfd + 1, &rdset, wrsetp, NULL, &timeout)) == 0)
-		return 0;
-	
-	if (ready < 0) {
-		if (errno == EINTR)
-			goto retry;
-		
-		d(printf ("select() failed: %s\n", strerror (errno)));
-		
-		return -1;
-	}
-	
-	/* Test each and every file descriptor to see if it's 'ready',
-	   and if so - do what we can with it and then drop through to
-	   the next file descriptor and so on until we've done what we
-	   can to all of them. If one fails along the way, return
-	   -1. */
-	
-	if (FD_ISSET (gpg->status_fd, &rdset)) {
-		/* read the status message and decide what to do... */
-		char buffer[4096];
-		ssize_t nread;
-		
-		d(printf ("reading from gpg's status-fd...\n"));
-		
-		do {
-			nread = read (gpg->status_fd, buffer, sizeof (buffer));
-		} while (nread == -1 && (errno == EINTR || errno == EAGAIN));
-		if (nread == -1)
-			goto exception;
-		
-		if (nread > 0) {
-			status_backup (gpg, buffer, nread);
-			
-			if (gpg_ctx_parse_status (gpg, ex) == -1)
-				return -1;
-		} else {
-			gpg->complete = TRUE;
-		}
-	}
-	
-	if (FD_ISSET (gpg->stdout_fd, &rdset) && gpg->ostream) {
-		char buffer[4096];
-		ssize_t nread;
-		
-		d(printf ("reading gpg's stdout...\n"));
-		
-		do {
-			nread = read (gpg->stdout_fd, buffer, sizeof (buffer));
-		} while (nread == -1 && (errno == EINTR || errno == EAGAIN));
-		if (nread == -1)
-			goto exception;
-		
-		if (nread > 0) {
-			if (camel_stream_write (gpg->ostream, buffer, (size_t) nread) == -1)
-				goto exception;
-		} else {
-			gpg->seen_eof1 = TRUE;
-		}
-	}
-	
-	if (FD_ISSET (gpg->stderr_fd, &rdset)) {
-		char buffer[4096];
-		ssize_t nread;
-		
-		d(printf ("reading gpg's stderr...\n"));
-		
-		do {
-			nread = read (gpg->stderr_fd, buffer, sizeof (buffer));
-		} while (nread == -1 && (errno == EINTR || errno == EAGAIN));
-		if (nread == -1)
-			goto exception;
-		
-		if (nread > 0) {
-			camel_stream_write (gpg->diagnostics, buffer, nread);
-		} else {
-			gpg->seen_eof2 = TRUE;
-		}
-	}
-	
-	if (wrsetp && gpg->passwd_fd != -1 && FD_ISSET (gpg->passwd_fd, &wrset) && gpg->need_passwd && gpg->send_passwd) {
-		ssize_t w, nwritten = 0;
-		size_t n;
-		
-		d(printf ("sending gpg our passphrase...\n"));
-		
-		/* send the passphrase to gpg */
-		n = strlen (gpg->passwd);
-		do {
-			do {
-				w = write (gpg->passwd_fd, gpg->passwd + nwritten, n - nwritten);
-			} while (w == -1 && (errno == EINTR || errno == EAGAIN));
-			
-			if (w > 0)
-				nwritten += w;
-		} while (nwritten < n && w != -1);
-		
-		/* zero and free our passwd buffer */
-		memset (gpg->passwd, 0, n);
-		g_free (gpg->passwd);
-		gpg->passwd = NULL;
-		
-		if (w == -1)
-			goto exception;
-		
-		gpg->send_passwd = FALSE;
-	}
-	
-	if (gpg->istream && wrsetp && gpg->stdin_fd != -1 && FD_ISSET (gpg->stdin_fd, &wrset)) {
-		char buffer[4096];
-		ssize_t nread;
-		
-		d(printf ("writing to gpg's stdin...\n"));
-		
-		/* write our stream to gpg's stdin */
-		nread = camel_stream_read (gpg->istream, buffer, sizeof (buffer));
-		if (nread > 0) {
-			ssize_t w, nwritten = 0;
-			
-			do {
-				do {
-					w = write (gpg->stdin_fd, buffer + nwritten, nread - nwritten);
-				} while (w == -1 && (errno == EINTR || errno == EAGAIN));
-				
-				if (w > 0)
-					nwritten += w;
-			} while (nwritten < nread && w != -1);
-			
-			d(printf ("wrote %d (out of %d) bytes to gpg's stdin\n", nwritten, nread));
-			
-			if (w == -1)
-				goto exception;
-		}
-		
-		if (camel_stream_eos (gpg->istream)) {
-			d(printf ("closing gpg's stdin\n"));
-			close (gpg->stdin_fd);
-			gpg->stdin_fd = -1;
-		}
-	}
-	
-	return 0;
-	
- exception:
-	
-	switch (gpg->mode) {
-	case GPG_CTX_MODE_SIGN:
-		mode = "sign";
-		break;
-	case GPG_CTX_MODE_VERIFY:
-		mode = "verify";
-		break;
-	case GPG_CTX_MODE_ENCRYPT:
-		mode = "encrypt";
-		break;
-	case GPG_CTX_MODE_DECRYPT:
-		mode = "decrypt";
-		break;
-	case GPG_CTX_MODE_IMPORT:
-		mode = "import keys";
-		break;
-	case GPG_CTX_MODE_EXPORT:
-		mode = "export keys";
-		break;
-	default:
-		g_assert_not_reached ();
-		mode = NULL;
-		break;
-	}
-	
-	diagnostics = gpg_ctx_get_diagnostics (gpg);
-	if (diagnostics && *diagnostics) {
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Failed to GPG %s: %s\n\n%s"),
-				      mode, g_strerror (errno),
-				      diagnostics);
-	} else {
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Failed to GPG %s: %s\n"),
-				      mode, g_strerror (errno));
-	}
-	
-	return -1;
-}
-
-static gboolean
-gpg_ctx_op_complete (struct _GpgCtx *gpg)
-{
-	return gpg->complete && gpg->seen_eof1 && gpg->seen_eof2;
-}
-
-#if 0
-static gboolean
-gpg_ctx_op_exited (struct _GpgCtx *gpg)
-{
-	pid_t retval;
-	int status;
-	
-	if (gpg->exited)
-		return TRUE;
-	
-	retval = waitpid (gpg->pid, &status, WNOHANG);
-	if (retval == gpg->pid) {
-		gpg->exit_status = status;
-		gpg->exited = TRUE;
-		return TRUE;
-	}
-	
-	return FALSE;
-}
-#endif
-
-static void
-gpg_ctx_op_cancel (struct _GpgCtx *gpg)
-{
-	pid_t retval;
-	int status;
-	
-	if (gpg->exited)
-		return;
-	
-	kill (gpg->pid, SIGTERM);
-	sleep (1);
-	retval = waitpid (gpg->pid, &status, WNOHANG);
-	if (retval == (pid_t) 0) {
-		/* no more mr nice guy... */
-		kill (gpg->pid, SIGKILL);
-		sleep (1);
-		waitpid (gpg->pid, &status, WNOHANG);
-	}
-}
-
-static int
-gpg_ctx_op_wait (struct _GpgCtx *gpg)
-{
-	sigset_t mask, omask;
-	pid_t retval;
-	int status;
-	
-	if (!gpg->exited) {
-		sigemptyset (&mask);
-		sigaddset (&mask, SIGALRM);
-		sigprocmask (SIG_BLOCK, &mask, &omask);
-		alarm (1);
-		retval = waitpid (gpg->pid, &status, 0);
-		alarm (0);
-		sigprocmask (SIG_SETMASK, &omask, NULL);
-		
-		if (retval == (pid_t) -1 && errno == EINTR) {
-			/* The child is hanging: send a friendly reminder. */
-			kill (gpg->pid, SIGTERM);
-			sleep (1);
-			retval = waitpid (gpg->pid, &status, WNOHANG);
-			if (retval == (pid_t) 0) {
-				/* Still hanging; use brute force. */
-				kill (gpg->pid, SIGKILL);
-				sleep (1);
-				retval = waitpid (gpg->pid, &status, WNOHANG);
-			}
-		}
-	} else {
-		status = gpg->exit_status;
-		retval = gpg->pid;
-	}
-	
-	if (retval != (pid_t) -1 && WIFEXITED (status))
-		return WEXITSTATUS (status);
-	else
-		return -1;
-}
-
-
-
-static int
-gpg_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex)
-{
-	struct _GpgCtx *gpg;
-	CamelStream *ostream = camel_stream_mem_new(), *istream;
-	CamelDataWrapper *dw;
-	CamelContentType *ct;
-	int res = -1;
-	CamelMimePart *sigpart;
-	CamelMultipartSigned *mps;
-
-	/* Note: see rfc2015 or rfc3156, section 5 */
-
-	/* FIXME: stream this, we stream output at least */
-	istream = camel_stream_mem_new();
-	if (camel_cipher_canonical_to_stream(ipart, CAMEL_MIME_FILTER_CANON_STRIP|CAMEL_MIME_FILTER_CANON_CRLF|CAMEL_MIME_FILTER_CANON_FROM,
-					     istream) == -1) {
-		camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
-				     _("Could not generate signing data: %s"), g_strerror(errno));
-		goto fail;
-	}
-
-	gpg = gpg_ctx_new (context->session);
-	gpg_ctx_set_mode (gpg, GPG_CTX_MODE_SIGN);
-	gpg_ctx_set_hash (gpg, hash);
-	gpg_ctx_set_armor (gpg, TRUE);
-	gpg_ctx_set_userid (gpg, userid);
-	gpg_ctx_set_istream (gpg, istream);
-	gpg_ctx_set_ostream (gpg, ostream);
-	
-	if (gpg_ctx_op_start (gpg) == -1) {
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Failed to execute gpg: %s"), g_strerror (errno));
-		goto fail;
-	}
-	
-	while (!gpg_ctx_op_complete (gpg)) {
-		if (camel_operation_cancel_check (NULL)) {
-			camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
-					     _("Cancelled."));
-			gpg_ctx_op_cancel (gpg);
-			goto fail;
-		}
-		
-		if (gpg_ctx_op_step (gpg, ex) == -1) {
-			gpg_ctx_op_cancel (gpg);
-			goto fail;
-		}
-	}
-	
-	if (gpg_ctx_op_wait (gpg) != 0) {
-		const char *diagnostics;
-		
-		diagnostics = gpg_ctx_get_diagnostics (gpg);
-		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-				     diagnostics && *diagnostics ? diagnostics :
-				     _("Failed to execute gpg."));
-		goto fail;
-	}
-
-	res = 0;
-
-	dw = camel_data_wrapper_new();
-	camel_stream_reset(ostream);
-	camel_data_wrapper_construct_from_stream(dw, ostream);
-
-	sigpart = camel_mime_part_new();
-	ct = camel_content_type_new("application", "pgp-signature");
-	camel_content_type_set_param(ct, "name", "signature.asc");
-	camel_data_wrapper_set_mime_type_field(dw, ct);
-	camel_content_type_unref(ct);
-
-	camel_medium_set_content_object((CamelMedium *)sigpart, dw);
-	camel_object_unref(dw);
-
-	camel_mime_part_set_description(sigpart, _("This is a digitally signed message part"));
-
-	mps = camel_multipart_signed_new();
-	ct = camel_content_type_new("multipart", "signed");
-	camel_content_type_set_param(ct, "micalg", camel_cipher_hash_to_id(context, hash));
-	camel_content_type_set_param(ct, "protocol", context->sign_protocol);
-	camel_data_wrapper_set_mime_type_field((CamelDataWrapper *)mps, ct);
-	camel_content_type_unref(ct);
-	camel_multipart_set_boundary((CamelMultipart *)mps, NULL);
-
-	mps->signature = sigpart;
-	mps->contentraw = istream;
-	camel_stream_reset(istream);
-	camel_object_ref(istream);
-
-	camel_medium_set_content_object((CamelMedium *)opart, (CamelDataWrapper *)mps);
-fail:
-	camel_object_unref(ostream);
-	gpg_ctx_free (gpg);
-	
-	return res;
-}
-
-
-static char *
-swrite (CamelMimePart *sigpart)
-{
-	CamelStream *ostream;
-	char *template;
-	int fd, ret;
-	
-	template = g_strdup ("/tmp/evolution-pgp.XXXXXX");
-	fd = mkstemp (template);
-	if (fd == -1) {
-		g_free (template);
-		return NULL;
-	}
-
-	/* TODO: This should probably just write the decoded message content out, not the part + headers */
-
-	ostream = camel_stream_fs_new_with_fd (fd);
-	ret = camel_data_wrapper_write_to_stream((CamelDataWrapper *)sigpart, ostream);
-	if (ret != -1) {
-		ret = camel_stream_flush (ostream);
-		if (ret != -1)
-			ret = camel_stream_close (ostream);
-	}
-
-	camel_object_unref(ostream);
-
-	if (ret == -1) {
-		unlink (template);
-		g_free (template);
-		return NULL;
-	}
-	
-	return template;
-}
-
-static CamelCipherValidity *
-gpg_verify (CamelCipherContext *context, CamelMimePart *ipart, CamelException *ex)
-{
-	CamelCipherValidity *validity;
-	const char *diagnostics = NULL, *tmp;
-	struct _GpgCtx *gpg = NULL;
-	char *sigfile = NULL;
-	gboolean valid;
-	CamelContentType *ct;
-	CamelMimePart *sigpart, *datapart;
-	CamelStream *istream = NULL;
-	CamelMultipart *mps;
-
-	ct = camel_mime_part_get_content_type(ipart);
-	tmp = camel_content_type_param(ct, "protocol");
-	mps = (CamelMultipart *)camel_medium_get_content_object((CamelMedium *)ipart);
-	if (!camel_content_type_is(ct, "multipart", "signed")
-	    || !CAMEL_IS_MULTIPART_SIGNED(mps)
-	    || tmp == NULL
-	    || g_ascii_strcasecmp(tmp, context->sign_protocol) != 0) {
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Cannot verify message signature: Incorrect message format"));
-		return NULL;
-	}
-
-	datapart = camel_multipart_get_part(mps, CAMEL_MULTIPART_SIGNED_CONTENT);
-	sigpart = camel_multipart_get_part(mps, CAMEL_MULTIPART_SIGNED_SIGNATURE);
-
-	if (sigpart == NULL || datapart == NULL) {
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Cannot verify message signature: Incorrect message format"));
-		goto exception;
-	}
-
-	sigfile = swrite (sigpart);
-	if (sigfile == NULL) {
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Cannot verify message signature: could not create temp file: %s"),
-				      g_strerror (errno));
-		goto exception;
-	}
-
-	istream = camel_stream_mem_new();
-	camel_cipher_canonical_to_stream(datapart, CAMEL_MIME_FILTER_CANON_CRLF, istream);
-	camel_stream_reset(istream);
-	
-	gpg = gpg_ctx_new (context->session);
-	gpg_ctx_set_mode (gpg, GPG_CTX_MODE_VERIFY);
-	gpg_ctx_set_hash (gpg, camel_cipher_id_to_hash(context, camel_content_type_param(ct, "micalg")));
-	gpg_ctx_set_sigfile (gpg, sigfile);
-	gpg_ctx_set_istream (gpg, istream);
-	
-	if (gpg_ctx_op_start (gpg) == -1) {
-		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-				     _("Failed to execute gpg."));
-		gpg_ctx_free (gpg);
-		goto exception;
-	}
-	
-	while (!gpg_ctx_op_complete (gpg)) {
-		if (camel_operation_cancel_check (NULL)) {
-			camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
-					     _("Cancelled."));
-			gpg_ctx_op_cancel (gpg);
-			goto exception;
-		}
-		
-		if (gpg_ctx_op_step (gpg, ex) == -1) {
-			gpg_ctx_op_cancel (gpg);
-			goto exception;
-		}
-	}
-	
-	valid = gpg_ctx_op_wait (gpg) == 0;
-	validity = camel_cipher_validity_new ();
-	diagnostics = gpg_ctx_get_diagnostics (gpg);
-	camel_cipher_validity_set_valid (validity, valid);
-	camel_cipher_validity_set_description (validity, diagnostics);
-	gpg_ctx_free (gpg);
-	
-	if (sigfile) {
-		unlink (sigfile);
-		g_free (sigfile);
-	}
-	
-	return validity;
-	
- exception:
-	
-	gpg_ctx_free (gpg);
-
-	if (istream)
-		camel_object_unref(istream);
-
-	if (sigfile) {
-		unlink (sigfile);
-		g_free (sigfile);
-	}
-	
-	return NULL;
-}
-
-static int
-gpg_encrypt (CamelCipherContext *context, const char *userid, GPtrArray *recipients, struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex)
-{
-	CamelGpgContext *ctx = (CamelGpgContext *) context;
-	struct _GpgCtx *gpg;
-	int i, res = -1;
-	CamelStream *istream, *ostream, *vstream;
-	CamelMimePart *encpart, *verpart;
-	CamelDataWrapper *dw;
-	CamelContentType *ct;
-	CamelMultipartEncrypted *mpe;
-
-	ostream = camel_stream_mem_new();
-	istream = camel_stream_mem_new();
-	if (camel_cipher_canonical_to_stream(ipart, CAMEL_MIME_FILTER_CANON_CRLF, istream) == -1) {
-		camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
-				     _("Could not generate encrypting data: %s"), g_strerror(errno));
-		goto fail1;
-	}
-	
-	gpg = gpg_ctx_new (context->session);
-	gpg_ctx_set_mode (gpg, GPG_CTX_MODE_ENCRYPT);
-	gpg_ctx_set_armor (gpg, TRUE);
-	gpg_ctx_set_userid (gpg, userid);
-	gpg_ctx_set_istream (gpg, istream);
-	gpg_ctx_set_ostream (gpg, ostream);
-	gpg_ctx_set_always_trust (gpg, ctx->always_trust);
-
-	for (i = 0; i < recipients->len; i++) {
-		gpg_ctx_add_recipient (gpg, recipients->pdata[i]);
-	}
-	
-	if (gpg_ctx_op_start (gpg) == -1) {
-		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to execute gpg."));
-		goto fail;
-	}
-
-	/* FIXME: move tihs to a common routine */
-	while (!gpg_ctx_op_complete(gpg)) {
-		if (camel_operation_cancel_check(NULL)) {
-			camel_exception_set(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled."));
-			gpg_ctx_op_cancel(gpg);
-			goto fail;
-		}
-		
-		if (gpg_ctx_op_step (gpg, ex) == -1) {
-			gpg_ctx_op_cancel (gpg);
-			goto fail;
-		}
-	}
-	
-	if (gpg_ctx_op_wait (gpg) != 0) {
-		const char *diagnostics;
-		
-		diagnostics = gpg_ctx_get_diagnostics (gpg);
-		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-				     diagnostics && *diagnostics ? diagnostics : _("Failed to execute gpg."));
-		goto fail;
-	}
-
-	res = 0;
-
-	dw = camel_data_wrapper_new();
-	camel_data_wrapper_construct_from_stream(dw, ostream);
-
-	encpart = camel_mime_part_new();
-	ct = camel_content_type_new("application", "octet-stream");
-	camel_content_type_set_param(ct, "name", "encrypted.asc");
-	camel_data_wrapper_set_mime_type_field(dw, ct);
-	camel_content_type_unref(ct);
-
-	camel_medium_set_content_object((CamelMedium *)encpart, dw);
-	camel_object_unref(dw);
-
-	camel_mime_part_set_description(encpart, _("This is a digitally encrypted message part"));
-
-	vstream = camel_stream_mem_new();
-	camel_stream_write(vstream, "Version: 1\n", strlen("Version: 1\n"));
-	camel_stream_reset(vstream);
-
-	verpart = camel_mime_part_new();
-	dw = camel_data_wrapper_new();
-	camel_data_wrapper_set_mime_type(dw, context->encrypt_protocol);
-	camel_data_wrapper_construct_from_stream(dw, vstream);
-	camel_object_unref(vstream);
-	camel_medium_set_content_object((CamelMedium *)verpart, dw);
-	camel_object_unref(dw);
-
-	mpe = camel_multipart_encrypted_new();
-	ct = camel_content_type_new("multipart", "encrypted");
-	camel_content_type_set_param(ct, "protocol", context->encrypt_protocol);
-	camel_data_wrapper_set_mime_type_field((CamelDataWrapper *)mpe, ct);
-	camel_content_type_unref(ct);
-	camel_multipart_set_boundary((CamelMultipart *)mpe, NULL);
-
-	mpe->decrypted = ipart;
-	camel_object_ref(ipart);
-
-	camel_multipart_add_part((CamelMultipart *)mpe, verpart);
-	camel_object_unref(verpart);
-	camel_multipart_add_part((CamelMultipart *)mpe, encpart);
-	camel_object_unref(encpart);
-
-	camel_medium_set_content_object((CamelMedium *)opart, (CamelDataWrapper *)mpe);
-fail:
-	gpg_ctx_free(gpg);
-fail1:
-	camel_object_unref(istream);
-	camel_object_unref(ostream);
-		
-	return res;
-}
-
-static CamelCipherValidity *
-gpg_decrypt(CamelCipherContext *context, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex)
-{
-	struct _GpgCtx *gpg;
-	CamelCipherValidity *valid = NULL;
-	CamelStream *ostream, *istream;
-
-	istream = camel_stream_mem_new();
-	camel_data_wrapper_write_to_stream(camel_medium_get_content_object((CamelMedium *)ipart), istream);
-	camel_stream_reset(istream);
-
-	/* TODO: de-canonicalise end of lines? */
-	/*stream = camel_stream_mem_new ();
-	filtered_stream = (CamelStream *) camel_stream_filter_new_with_stream (stream);
-	crlf_filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE,
-						  CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
-	camel_stream_filter_add (CAMEL_STREAM_FILTER (filtered_stream), crlf_filter);
-	camel_object_unref (crlf_filter);*/
-	ostream = camel_stream_mem_new();
-
-	gpg = gpg_ctx_new (context->session);
-	gpg_ctx_set_mode (gpg, GPG_CTX_MODE_DECRYPT);
-	gpg_ctx_set_istream (gpg, istream);
-	gpg_ctx_set_ostream (gpg, ostream);
-	
-	if (gpg_ctx_op_start (gpg) == -1) {
-		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-				     _("Failed to execute gpg."));
-		goto fail;
-	}
-	
-	while (!gpg_ctx_op_complete (gpg)) {
-		if (camel_operation_cancel_check (NULL)) {
-			camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
-					     _("Cancelled."));
-			gpg_ctx_op_cancel (gpg);
-			goto fail;
-		}
-		
-		if (gpg_ctx_op_step (gpg, ex) == -1) {
-			gpg_ctx_op_cancel (gpg);
-			goto fail;
-		}
-	}
-	
-	if (gpg_ctx_op_wait (gpg) != 0) {
-		const char *diagnostics;
-		
-		diagnostics = gpg_ctx_get_diagnostics (gpg);
-		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-				     diagnostics && *diagnostics ? diagnostics :
-				     _("Failed to execute gpg."));
-		goto fail;
-	}
-
-	camel_stream_reset(ostream);
-	if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)opart, ostream) != -1) {
-		valid = camel_cipher_validity_new();
-		valid->encrypt.description = g_strdup(_("Encrypted content"));
-		valid->encrypt.status = CAMEL_CIPHER_VALIDITY_ENCRYPT_ENCRYPTED;
-	} else {
-		camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
-				     _("Unable to parse message content"));
-	}
-fail:
-	camel_object_unref(ostream);
-	camel_object_unref(istream);
-	gpg_ctx_free (gpg);
-
-	return valid;
-}
-
-static int
-gpg_import_keys (CamelCipherContext *context, CamelStream *istream, CamelException *ex)
-{
-	struct _GpgCtx *gpg;
-	
-	gpg = gpg_ctx_new (context->session);
-	gpg_ctx_set_mode (gpg, GPG_CTX_MODE_IMPORT);
-	gpg_ctx_set_istream (gpg, istream);
-	
-	if (gpg_ctx_op_start (gpg) == -1) {
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Failed to execute gpg: %s"),
-				      errno ? g_strerror (errno) : _("Unknown"));
-		gpg_ctx_free (gpg);
-		
-		return -1;
-	}
-	
-	while (!gpg_ctx_op_complete (gpg)) {
-		if (gpg_ctx_op_step (gpg, ex) == -1) {
-			gpg_ctx_op_cancel (gpg);
-			gpg_ctx_free (gpg);
-			
-			return -1;
-		}
-	}
-	
-	if (gpg_ctx_op_wait (gpg) != 0) {
-		const char *diagnostics;
-		
-		diagnostics = gpg_ctx_get_diagnostics (gpg);
-		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-				     diagnostics && *diagnostics ? diagnostics :
-				     _("Failed to execute gpg."));
-		
-		gpg_ctx_free (gpg);
-		
-		return -1;
-	}
-	
-	gpg_ctx_free (gpg);
-	
-	return 0;
-}
-
-static int
-gpg_export_keys (CamelCipherContext *context, GPtrArray *keys, CamelStream *ostream, CamelException *ex)
-{
-	struct _GpgCtx *gpg;
-	int i;
-	
-	gpg = gpg_ctx_new (context->session);
-	gpg_ctx_set_mode (gpg, GPG_CTX_MODE_EXPORT);
-	gpg_ctx_set_armor (gpg, TRUE);
-	gpg_ctx_set_ostream (gpg, ostream);
-	
-	for (i = 0; i < keys->len; i++) {
-		gpg_ctx_add_recipient (gpg, keys->pdata[i]);
-	}
-	
-	if (gpg_ctx_op_start (gpg) == -1) {
-		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-				      _("Failed to execute gpg: %s"),
-				      errno ? g_strerror (errno) : _("Unknown"));
-		gpg_ctx_free (gpg);
-		
-		return -1;
-	}
-	
-	while (!gpg_ctx_op_complete (gpg)) {
-		if (gpg_ctx_op_step (gpg, ex) == -1) {
-			gpg_ctx_op_cancel (gpg);
-			gpg_ctx_free (gpg);
-			
-			return -1;
-		}
-	}
-	
-	if (gpg_ctx_op_wait (gpg) != 0) {
-		const char *diagnostics;
-		
-		diagnostics = gpg_ctx_get_diagnostics (gpg);
-		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
-				     diagnostics && *diagnostics ? diagnostics :
-				     _("Failed to execute gpg."));
-		
-		gpg_ctx_free (gpg);
-		
-		return -1;
-	}
-	
-	gpg_ctx_free (gpg);
-	
-	return 0;
-}
-
-/* ********************************************************************** */
-
-static void
-camel_gpg_context_class_init (CamelGpgContextClass *klass)
-{
-	CamelCipherContextClass *cipher_class = CAMEL_CIPHER_CONTEXT_CLASS (klass);
-	
-	parent_class = CAMEL_CIPHER_CONTEXT_CLASS (camel_type_get_global_classfuncs (camel_cipher_context_get_type ()));
-	
-	cipher_class->hash_to_id = gpg_hash_to_id;
-	cipher_class->id_to_hash = gpg_id_to_hash;
-	cipher_class->sign = gpg_sign;
-	cipher_class->verify = gpg_verify;
-	cipher_class->encrypt = gpg_encrypt;
-	cipher_class->decrypt = gpg_decrypt;
-	cipher_class->import_keys = gpg_import_keys;
-	cipher_class->export_keys = gpg_export_keys;
-}
-
-static void
-camel_gpg_context_init (CamelGpgContext *context)
-{
-	CamelCipherContext *cipher = (CamelCipherContext *) context;
-	
-	context->always_trust = FALSE;
-	
-	cipher->sign_protocol = "application/pgp-signature";
-	cipher->encrypt_protocol = "application/pgp-encrypted";
-	cipher->key_protocol = "application/pgp-keys";
-}
-
-static void
-camel_gpg_context_finalise (CamelObject *object)
-{
-	;
-}
-
-CamelType
-camel_gpg_context_get_type (void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-	
-	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register (camel_cipher_context_get_type (),
-					    "CamelGpgContext",
-					    sizeof (CamelGpgContext),
-					    sizeof (CamelGpgContextClass),
-					    (CamelObjectClassInitFunc) camel_gpg_context_class_init,
-					    NULL,
-					    (CamelObjectInitFunc) camel_gpg_context_init,
-					    (CamelObjectFinalizeFunc) camel_gpg_context_finalise);
-	}
-	
-	return type;
-}
-
-
diff --git a/camel/camel-gpg-context.h b/camel/camel-gpg-context.h
deleted file mode 100644
index 0d98fed75d..0000000000
--- a/camel/camel-gpg-context.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast 
- *
- *  Copyright 2002 Ximian, Inc. (www.ximian.com)
- *
- *  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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-
-#ifndef __CAMEL_GPG_CONTEXT_H__
-#define __CAMEL_GPG_CONTEXT_H__
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include 
-
-#define CAMEL_GPG_CONTEXT_TYPE     (camel_gpg_context_get_type ())
-#define CAMEL_GPG_CONTEXT(obj)     (CAMEL_CHECK_CAST((obj), CAMEL_GPG_CONTEXT_TYPE, CamelGpgContext))
-#define CAMEL_GPG_CONTEXT_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_GPG_CONTEXT_TYPE, CamelGpgContextClass))
-#define CAMEL_IS_GPG_CONTEXT(o)    (CAMEL_CHECK_TYPE((o), CAMEL_GPG_CONTEXT_TYPE))
-
-typedef struct _CamelGpgContext CamelGpgContext;
-typedef struct _CamelGpgContextClass CamelGpgContextClass;
-
-struct _CamelGpgContext {
-	CamelCipherContext parent_object;
-	
-	gboolean always_trust;
-};
-
-struct _CamelGpgContextClass {
-	CamelCipherContextClass parent_class;
-	
-};
-
-
-CamelType camel_gpg_context_get_type (void);
-
-CamelCipherContext *camel_gpg_context_new (CamelSession *session);
-
-void camel_gpg_context_set_always_trust (CamelGpgContext *ctx, gboolean trust);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __CAMEL_GPG_CONTEXT_H__ */
diff --git a/camel/camel-html-parser.c b/camel/camel-html-parser.c
deleted file mode 100644
index 31c0aee15b..0000000000
--- a/camel/camel-html-parser.c
+++ /dev/null
@@ -1,807 +0,0 @@
-/*
- *  Copyright (C) 2001 Ximian Inc.
- *
- *  Authors: Michael Zucchi 
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/** WARNING
- **
- ** DO NOT USE THIS CODE OUTSIDE OF CAMEL
- **
- ** IT IS SUBJECT TO CHANGE OR MAY VANISH AT ANY TIME
- **/
-
-#include "camel-html-parser.h"
-
-#include 
-#include 
-
-#include 
-#include 
-
-/* if defined, must also compile in dump_tag() below somewhere */
-#define d(x)
-
-static void camel_html_parser_class_init (CamelHTMLParserClass *klass);
-static void camel_html_parser_init       (CamelObject *o);
-static void camel_html_parser_finalize   (CamelObject *o);
-
-static CamelObjectClass *camel_html_parser_parent;
-
-/* Parser definitions, see below object code for details */
-
-typedef struct _CamelHTMLParserPrivate CamelHTMLParserPrivate;
-
-struct _CamelHTMLParserPrivate {
-	char *inbuf,
-		*inptr,
-		*inend,
-		*start;
-	enum _camel_html_parser_t state;
-	char *charset;
-	int eof;
-	GString *tag;
-	GString *ent;
-	char ent_utf8[8];
-	int attr;
-	GPtrArray *attrs;
-	GPtrArray *values;
-	int quote;
-};
-
-static void tokenise_setup(void);
-static CamelHTMLParserPrivate *tokenise_init(void);
-static void tokenise_free(CamelHTMLParserPrivate *p);
-static int tokenise_step(CamelHTMLParserPrivate *p, char **datap, int *lenp);
-
-/* ********************************************************************** */
-
-CamelType
-camel_html_parser_get_type (void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-	
-	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register (camel_object_get_type (), "CamelHTMLParser",
-					    sizeof (CamelHTMLParser),
-					    sizeof (CamelHTMLParserClass),
-					    (CamelObjectClassInitFunc) camel_html_parser_class_init,
-					    NULL,
-					    (CamelObjectInitFunc) camel_html_parser_init,
-					    (CamelObjectFinalizeFunc) camel_html_parser_finalize);
-	}
-	
-	return type;
-}
-
-static void
-camel_html_parser_finalize(CamelObject *o)
-{
-	CamelHTMLParser *f = (CamelHTMLParser *)o;
-
-	tokenise_free(f->priv);
-}
-
-static void
-camel_html_parser_init       (CamelObject *o)
-{
-	CamelHTMLParser *f = (CamelHTMLParser *)o;
-
-	f->priv = tokenise_init();
-}
-
-static void
-camel_html_parser_class_init (CamelHTMLParserClass *klass)
-{
-	camel_html_parser_parent = CAMEL_OBJECT_CLASS (camel_type_get_global_classfuncs (camel_object_get_type ()));
-
-	tokenise_setup();
-}
-
-/**
- * camel_html_parser_new:
- *
- * Create a new CamelHTMLParser object.
- * 
- * Return value: A new CamelHTMLParser widget.
- **/
-CamelHTMLParser *
-camel_html_parser_new (void)
-{
-	CamelHTMLParser *new = CAMEL_HTML_PARSER ( camel_object_new (camel_html_parser_get_type ()));
-	return new;
-}
-
-
-void camel_html_parser_set_data(CamelHTMLParser *hp, const char *start, int len, int last)
-{
-	CamelHTMLParserPrivate *p = hp->priv;
-
-	p->inptr = p->inbuf = (char *)start;
-	p->inend = (char *)start+len;
-	p->eof = last;
-}
-
-camel_html_parser_t camel_html_parser_step(CamelHTMLParser *hp, const char **datap, int *lenp)
-{
-	return tokenise_step(hp->priv, (char **)datap, lenp);
-}
-
-const char *camel_html_parser_left(CamelHTMLParser *hp, int *lenp)
-{
-	CamelHTMLParserPrivate *p = hp->priv;
-
-	if (lenp)
-		*lenp = p->inend - p->inptr;
-
-	return p->inptr;
-}
-
-const char *camel_html_parser_tag(CamelHTMLParser *hp)
-{
-	return hp->priv->tag->str;
-}
-
-const char *camel_html_parser_attr(CamelHTMLParser *hp, const char *name)
-{
-	int i;
-	CamelHTMLParserPrivate *p = hp->priv;
-
-	for (i=0;iattrs->len;i++) {
-		if (!strcasecmp(((GString *)p->attrs->pdata[i])->str, name)) {
-			return ((GString *)p->values->pdata[i])->str;
-		}
-	}
-
-	return NULL;
-}
-
-const GPtrArray *camel_html_parser_attr_list(CamelHTMLParser *hp, const GPtrArray **values)
-{
-	if (values)
-		*values = hp->priv->values;
-
-	return hp->priv->attrs;
-}
-
-/* this map taken out of libxml */
-static struct {
-	unsigned int val;
-	const char *name;
-} entity_map[] = {
-/*
- * the 4 absolute ones,
- */
-	{ 34,	"quot",	/* quotation mark = APL quote, U+0022 ISOnum */ },
-	{ 38,	"amp",	/* ampersand, U+0026 ISOnum */ },
-	{ 60,	"lt",	/* less-than sign, U+003C ISOnum */ },
-	{ 62,	"gt",	/* greater-than sign, U+003E ISOnum */ },
-
-/*
- * A bunch still in the 128-255 range
- * Replacing them depend really on the charset used.
- */
-	{ 39,	"apos",	/* single quote */ },
-	{ 160,	"nbsp",	/* no-break space = non-breaking space, U+00A0 ISOnum */ },
-	{ 161,	"iexcl",/* inverted exclamation mark, U+00A1 ISOnum */ },
-	{ 162,	"cent",	/* cent sign, U+00A2 ISOnum */ },
-	{ 163,	"pound",/* pound sign, U+00A3 ISOnum */ },
-	{ 164,	"curren",/* currency sign, U+00A4 ISOnum */ },
-	{ 165,	"yen",	/* yen sign = yuan sign, U+00A5 ISOnum */ },
-	{ 166,	"brvbar",/* broken bar = broken vertical bar, U+00A6 ISOnum */ },
-	{ 167,	"sect",	/* section sign, U+00A7 ISOnum */ },
-	{ 168,	"uml",	/* diaeresis = spacing diaeresis, U+00A8 ISOdia */ },
-	{ 169,	"copy",	/* copyright sign, U+00A9 ISOnum */ },
-	{ 170,	"ordf",	/* feminine ordinal indicator, U+00AA ISOnum */ },
-	{ 171,	"laquo",/* left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum */ },
-	{ 172,	"not",	/* not sign, U+00AC ISOnum */ },
-	{ 173,	"shy",	/* soft hyphen = discretionary hyphen, U+00AD ISOnum */ },
-	{ 174,	"reg",	/* registered sign = registered trade mark sign, U+00AE ISOnum */ },
-	{ 175,	"macr",	/* macron = spacing macron = overline = APL overbar, U+00AF ISOdia */ },
-	{ 176,	"deg",	/* degree sign, U+00B0 ISOnum */ },
-	{ 177,	"plusmn",/* plus-minus sign = plus-or-minus sign, U+00B1 ISOnum */ },
-	{ 178,	"sup2",	/* superscript two = superscript digit two = squared, U+00B2 ISOnum */ },
-	{ 179,	"sup3",	/* superscript three = superscript digit three = cubed, U+00B3 ISOnum */ },
-	{ 180,	"acute",/* acute accent = spacing acute, U+00B4 ISOdia */ },
-	{ 181,	"micro",/* micro sign, U+00B5 ISOnum */ },
-	{ 182,	"para",	/* pilcrow sign = paragraph sign, U+00B6 ISOnum */ },
-	{ 183,	"middot",/* middle dot = Georgian comma Greek middle dot, U+00B7 ISOnum */ },
-	{ 184,	"cedil",/* cedilla = spacing cedilla, U+00B8 ISOdia */ },
-	{ 185,	"sup1",	/* superscript one = superscript digit one, U+00B9 ISOnum */ },
-	{ 186,	"ordm",	/* masculine ordinal indicator, U+00BA ISOnum */ },
-	{ 187,	"raquo",/* right-pointing double angle quotation mark right pointing guillemet, U+00BB ISOnum */ },
-	{ 188,	"frac14",/* vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum */ },
-	{ 189,	"frac12",/* vulgar fraction one half = fraction one half, U+00BD ISOnum */ },
-	{ 190,	"frac34",/* vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum */ },
-	{ 191,	"iquest",/* inverted question mark = turned question mark, U+00BF ISOnum */ },
-	{ 192,	"Agrave",/* latin capital letter A with grave = latin capital letter A grave, U+00C0 ISOlat1 */ },
-	{ 193,	"Aacute",/* latin capital letter A with acute, U+00C1 ISOlat1 */ },
-	{ 194,	"Acirc",/* latin capital letter A with circumflex, U+00C2 ISOlat1 */ },
-	{ 195,	"Atilde",/* latin capital letter A with tilde, U+00C3 ISOlat1 */ },
-	{ 196,	"Auml",	/* latin capital letter A with diaeresis, U+00C4 ISOlat1 */ },
-	{ 197,	"Aring",/* latin capital letter A with ring above = latin capital letter A ring, U+00C5 ISOlat1 */ },
-	{ 198,	"AElig",/* latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1 */ },
-	{ 199,	"Ccedil",/* latin capital letter C with cedilla, U+00C7 ISOlat1 */ },
-	{ 200,	"Egrave",/* latin capital letter E with grave, U+00C8 ISOlat1 */ },
-	{ 201,	"Eacute",/* latin capital letter E with acute, U+00C9 ISOlat1 */ },
-	{ 202,	"Ecirc",/* latin capital letter E with circumflex, U+00CA ISOlat1 */ },
-	{ 203,	"Euml",	/* latin capital letter E with diaeresis, U+00CB ISOlat1 */ },
-	{ 204,	"Igrave",/* latin capital letter I with grave, U+00CC ISOlat1 */ },
-	{ 205,	"Iacute",/* latin capital letter I with acute, U+00CD ISOlat1 */ },
-	{ 206,	"Icirc",/* latin capital letter I with circumflex, U+00CE ISOlat1 */ },
-	{ 207,	"Iuml",	/* latin capital letter I with diaeresis, U+00CF ISOlat1 */ },
-	{ 208,	"ETH",	/* latin capital letter ETH, U+00D0 ISOlat1 */ },
-	{ 209,	"Ntilde",/* latin capital letter N with tilde, U+00D1 ISOlat1 */ },
-	{ 210,	"Ograve",/* latin capital letter O with grave, U+00D2 ISOlat1 */ },
-	{ 211,	"Oacute",/* latin capital letter O with acute, U+00D3 ISOlat1 */ },
-	{ 212,	"Ocirc",/* latin capital letter O with circumflex, U+00D4 ISOlat1 */ },
-	{ 213,	"Otilde",/* latin capital letter O with tilde, U+00D5 ISOlat1 */ },
-	{ 214,	"Ouml",	/* latin capital letter O with diaeresis, U+00D6 ISOlat1 */ },
-	{ 215,	"times",/* multiplication sign, U+00D7 ISOnum */ },
-	{ 216,	"Oslash",/* latin capital letter O with stroke latin capital letter O slash, U+00D8 ISOlat1 */ },
-	{ 217,	"Ugrave",/* latin capital letter U with grave, U+00D9 ISOlat1 */ },
-	{ 218,	"Uacute",/* latin capital letter U with acute, U+00DA ISOlat1 */ },
-	{ 219,	"Ucirc",/* latin capital letter U with circumflex, U+00DB ISOlat1 */ },
-	{ 220,	"Uuml",	/* latin capital letter U with diaeresis, U+00DC ISOlat1 */ },
-	{ 221,	"Yacute",/* latin capital letter Y with acute, U+00DD ISOlat1 */ },
-	{ 222,	"THORN",/* latin capital letter THORN, U+00DE ISOlat1 */ },
-	{ 223,	"szlig",/* latin small letter sharp s = ess-zed, U+00DF ISOlat1 */ },
-	{ 224,	"agrave",/* latin small letter a with grave = latin small letter a grave, U+00E0 ISOlat1 */ },
-	{ 225,	"aacute",/* latin small letter a with acute, U+00E1 ISOlat1 */ },
-	{ 226,	"acirc",/* latin small letter a with circumflex, U+00E2 ISOlat1 */ },
-	{ 227,	"atilde",/* latin small letter a with tilde, U+00E3 ISOlat1 */ },
-	{ 228,	"auml",	/* latin small letter a with diaeresis, U+00E4 ISOlat1 */ },
-	{ 229,	"aring",/* latin small letter a with ring above = latin small letter a ring, U+00E5 ISOlat1 */ },
-	{ 230,	"aelig",/* latin small letter ae = latin small ligature ae, U+00E6 ISOlat1 */ },
-	{ 231,	"ccedil",/* latin small letter c with cedilla, U+00E7 ISOlat1 */ },
-	{ 232,	"egrave",/* latin small letter e with grave, U+00E8 ISOlat1 */ },
-	{ 233,	"eacute",/* latin small letter e with acute, U+00E9 ISOlat1 */ },
-	{ 234,	"ecirc",/* latin small letter e with circumflex, U+00EA ISOlat1 */ },
-	{ 235,	"euml",	/* latin small letter e with diaeresis, U+00EB ISOlat1 */ },
-	{ 236,	"igrave",/* latin small letter i with grave, U+00EC ISOlat1 */ },
-	{ 237,	"iacute",/* latin small letter i with acute, U+00ED ISOlat1 */ },
-	{ 238,	"icirc",/* latin small letter i with circumflex, U+00EE ISOlat1 */ },
-	{ 239,	"iuml",	/* latin small letter i with diaeresis, U+00EF ISOlat1 */ },
-	{ 240,	"eth",	/* latin small letter eth, U+00F0 ISOlat1 */ },
-	{ 241,	"ntilde",/* latin small letter n with tilde, U+00F1 ISOlat1 */ },
-	{ 242,	"ograve",/* latin small letter o with grave, U+00F2 ISOlat1 */ },
-	{ 243,	"oacute",/* latin small letter o with acute, U+00F3 ISOlat1 */ },
-	{ 244,	"ocirc",/* latin small letter o with circumflex, U+00F4 ISOlat1 */ },
-	{ 245,	"otilde",/* latin small letter o with tilde, U+00F5 ISOlat1 */ },
-	{ 246,	"ouml",	/* latin small letter o with diaeresis, U+00F6 ISOlat1 */ },
-	{ 247,	"divide",/* division sign, U+00F7 ISOnum */ },
-	{ 248,	"oslash",/* latin small letter o with stroke, = latin small letter o slash, U+00F8 ISOlat1 */ },
-	{ 249,	"ugrave",/* latin small letter u with grave, U+00F9 ISOlat1 */ },
-	{ 250,	"uacute",/* latin small letter u with acute, U+00FA ISOlat1 */ },
-	{ 251,	"ucirc",/* latin small letter u with circumflex, U+00FB ISOlat1 */ },
-	{ 252,	"uuml",	/* latin small letter u with diaeresis, U+00FC ISOlat1 */ },
-	{ 253,	"yacute",/* latin small letter y with acute, U+00FD ISOlat1 */ },
-	{ 254,	"thorn",/* latin small letter thorn with, U+00FE ISOlat1 */ },
-	{ 255,	"yuml",	/* latin small letter y with diaeresis, U+00FF ISOlat1 */ },
-
-/*
- * Anything below should really be kept as entities references
- */
-	{ 402,	"fnof",	/* latin small f with hook = function = florin, U+0192 ISOtech */ },
-
-	{ 913,	"Alpha",/* greek capital letter alpha, U+0391 */ },
-	{ 914,	"Beta",	/* greek capital letter beta, U+0392 */ },
-	{ 915,	"Gamma",/* greek capital letter gamma, U+0393 ISOgrk3 */ },
-	{ 916,	"Delta",/* greek capital letter delta, U+0394 ISOgrk3 */ },
-	{ 917,	"Epsilon",/* greek capital letter epsilon, U+0395 */ },
-	{ 918,	"Zeta",	/* greek capital letter zeta, U+0396 */ },
-	{ 919,	"Eta",	/* greek capital letter eta, U+0397 */ },
-	{ 920,	"Theta",/* greek capital letter theta, U+0398 ISOgrk3 */ },
-	{ 921,	"Iota",	/* greek capital letter iota, U+0399 */ },
-	{ 922,	"Kappa",/* greek capital letter kappa, U+039A */ },
-	{ 923,	"Lambda"/* greek capital letter lambda, U+039B ISOgrk3 */ },
-	{ 924,	"Mu",	/* greek capital letter mu, U+039C */ },
-	{ 925,	"Nu",	/* greek capital letter nu, U+039D */ },
-	{ 926,	"Xi",	/* greek capital letter xi, U+039E ISOgrk3 */ },
-	{ 927,	"Omicron",/* greek capital letter omicron, U+039F */ },
-	{ 928,	"Pi",	/* greek capital letter pi, U+03A0 ISOgrk3 */ },
-	{ 929,	"Rho",	/* greek capital letter rho, U+03A1 */ },
-	{ 931,	"Sigma",/* greek capital letter sigma, U+03A3 ISOgrk3 */ },
-	{ 932,	"Tau",	/* greek capital letter tau, U+03A4 */ },
-	{ 933,	"Upsilon",/* greek capital letter upsilon, U+03A5 ISOgrk3 */ },
-	{ 934,	"Phi",	/* greek capital letter phi, U+03A6 ISOgrk3 */ },
-	{ 935,	"Chi",	/* greek capital letter chi, U+03A7 */ },
-	{ 936,	"Psi",	/* greek capital letter psi, U+03A8 ISOgrk3 */ },
-	{ 937,	"Omega",/* greek capital letter omega, U+03A9 ISOgrk3 */ },
-
-	{ 945,	"alpha",/* greek small letter alpha, U+03B1 ISOgrk3 */ },
-	{ 946,	"beta",	/* greek small letter beta, U+03B2 ISOgrk3 */ },
-	{ 947,	"gamma",/* greek small letter gamma, U+03B3 ISOgrk3 */ },
-	{ 948,	"delta",/* greek small letter delta, U+03B4 ISOgrk3 */ },
-	{ 949,	"epsilon",/* greek small letter epsilon, U+03B5 ISOgrk3 */ },
-	{ 950,	"zeta",	/* greek small letter zeta, U+03B6 ISOgrk3 */ },
-	{ 951,	"eta",	/* greek small letter eta, U+03B7 ISOgrk3 */ },
-	{ 952,	"theta",/* greek small letter theta, U+03B8 ISOgrk3 */ },
-	{ 953,	"iota",	/* greek small letter iota, U+03B9 ISOgrk3 */ },
-	{ 954,	"kappa",/* greek small letter kappa, U+03BA ISOgrk3 */ },
-	{ 955,	"lambda",/* greek small letter lambda, U+03BB ISOgrk3 */ },
-	{ 956,	"mu",	/* greek small letter mu, U+03BC ISOgrk3 */ },
-	{ 957,	"nu",	/* greek small letter nu, U+03BD ISOgrk3 */ },
-	{ 958,	"xi",	/* greek small letter xi, U+03BE ISOgrk3 */ },
-	{ 959,	"omicron",/* greek small letter omicron, U+03BF NEW */ },
-	{ 960,	"pi",	/* greek small letter pi, U+03C0 ISOgrk3 */ },
-	{ 961,	"rho",	/* greek small letter rho, U+03C1 ISOgrk3 */ },
-	{ 962,	"sigmaf",/* greek small letter final sigma, U+03C2 ISOgrk3 */ },
-	{ 963,	"sigma",/* greek small letter sigma, U+03C3 ISOgrk3 */ },
-	{ 964,	"tau",	/* greek small letter tau, U+03C4 ISOgrk3 */ },
-	{ 965,	"upsilon",/* greek small letter upsilon, U+03C5 ISOgrk3 */ },
-	{ 966,	"phi",	/* greek small letter phi, U+03C6 ISOgrk3 */ },
-	{ 967,	"chi",	/* greek small letter chi, U+03C7 ISOgrk3 */ },
-	{ 968,	"psi",	/* greek small letter psi, U+03C8 ISOgrk3 */ },
-	{ 969,	"omega",/* greek small letter omega, U+03C9 ISOgrk3 */ },
-	{ 977,	"thetasym",/* greek small letter theta symbol, U+03D1 NEW */ },
-	{ 978,	"upsih",/* greek upsilon with hook symbol, U+03D2 NEW */ },
-	{ 982,	"piv",	/* greek pi symbol, U+03D6 ISOgrk3 */ },
-
-	{ 8226,	"bull",	/* bullet = black small circle, U+2022 ISOpub */ },
-	{ 8230,	"hellip",/* horizontal ellipsis = three dot leader, U+2026 ISOpub */ },
-	{ 8242,	"prime",/* prime = minutes = feet, U+2032 ISOtech */ },
-	{ 8243,	"Prime",/* double prime = seconds = inches, U+2033 ISOtech */ },
-	{ 8254,	"oline",/* overline = spacing overscore, U+203E NEW */ },
-	{ 8260,	"frasl",/* fraction slash, U+2044 NEW */ },
-
-	{ 8472,	"weierp",/* script capital P = power set = Weierstrass p, U+2118 ISOamso */ },
-	{ 8465,	"image",/* blackletter capital I = imaginary part, U+2111 ISOamso */ },
-	{ 8476,	"real",	/* blackletter capital R = real part symbol, U+211C ISOamso */ },
-	{ 8482,	"trade",/* trade mark sign, U+2122 ISOnum */ },
-	{ 8501,	"alefsym",/* alef symbol = first transfinite cardinal, U+2135 NEW */ },
-	{ 8592,	"larr",	/* leftwards arrow, U+2190 ISOnum */ },
-	{ 8593,	"uarr",	/* upwards arrow, U+2191 ISOnum */ },
-	{ 8594,	"rarr",	/* rightwards arrow, U+2192 ISOnum */ },
-	{ 8595,	"darr",	/* downwards arrow, U+2193 ISOnum */ },
-	{ 8596,	"harr",	/* left right arrow, U+2194 ISOamsa */ },
-	{ 8629,	"crarr",/* downwards arrow with corner leftwards = carriage return, U+21B5 NEW */ },
-	{ 8656,	"lArr",	/* leftwards double arrow, U+21D0 ISOtech */ },
-	{ 8657,	"uArr",	/* upwards double arrow, U+21D1 ISOamsa */ },
-	{ 8658,	"rArr",	/* rightwards double arrow, U+21D2 ISOtech */ },
-	{ 8659,	"dArr",	/* downwards double arrow, U+21D3 ISOamsa */ },
-	{ 8660,	"hArr",	/* left right double arrow, U+21D4 ISOamsa */ },
-
-
-	{ 8704,	"forall",/* for all, U+2200 ISOtech */ },
-	{ 8706,	"part",	/* partial differential, U+2202 ISOtech */ },
-	{ 8707,	"exist",/* there exists, U+2203 ISOtech */ },
-	{ 8709,	"empty",/* empty set = null set = diameter, U+2205 ISOamso */ },
-	{ 8711,	"nabla",/* nabla = backward difference, U+2207 ISOtech */ },
-	{ 8712,	"isin",	/* element of, U+2208 ISOtech */ },
-	{ 8713,	"notin",/* not an element of, U+2209 ISOtech */ },
-	{ 8715,	"ni",	/* contains as member, U+220B ISOtech */ },
-	{ 8719,	"prod",	/* n-ary product = product sign, U+220F ISOamsb */ },
-	{ 8721,	"sum",	/* n-ary sumation, U+2211 ISOamsb */ },
-	{ 8722,	"minus",/* minus sign, U+2212 ISOtech */ },
-	{ 8727,	"lowast",/* asterisk operator, U+2217 ISOtech */ },
-	{ 8730,	"radic",/* square root = radical sign, U+221A ISOtech */ },
-	{ 8733,	"prop",	/* proportional to, U+221D ISOtech */ },
-	{ 8734,	"infin",/* infinity, U+221E ISOtech */ },
-	{ 8736,	"ang",	/* angle, U+2220 ISOamso */ },
-	{ 8743,	"and",	/* logical and = wedge, U+2227 ISOtech */ },
-	{ 8744,	"or",	/* logical or = vee, U+2228 ISOtech */ },
-	{ 8745,	"cap",	/* intersection = cap, U+2229 ISOtech */ },
-	{ 8746,	"cup",	/* union = cup, U+222A ISOtech */ },
-	{ 8747,	"int",	/* integral, U+222B ISOtech */ },
-	{ 8756,	"there4",/* therefore, U+2234 ISOtech */ },
-	{ 8764,	"sim",	/* tilde operator = varies with = similar to, U+223C ISOtech */ },
-	{ 8773,	"cong",	/* approximately equal to, U+2245 ISOtech */ },
-	{ 8776,	"asymp",/* almost equal to = asymptotic to, U+2248 ISOamsr */ },
-	{ 8800,	"ne",	/* not equal to, U+2260 ISOtech */ },
-	{ 8801,	"equiv",/* identical to, U+2261 ISOtech */ },
-	{ 8804,	"le",	/* less-than or equal to, U+2264 ISOtech */ },
-	{ 8805,	"ge",	/* greater-than or equal to, U+2265 ISOtech */ },
-	{ 8834,	"sub",	/* subset of, U+2282 ISOtech */ },
-	{ 8835,	"sup",	/* superset of, U+2283 ISOtech */ },
-	{ 8836,	"nsub",	/* not a subset of, U+2284 ISOamsn */ },
-	{ 8838,	"sube",	/* subset of or equal to, U+2286 ISOtech */ },
-	{ 8839,	"supe",	/* superset of or equal to, U+2287 ISOtech */ },
-	{ 8853,	"oplus",/* circled plus = direct sum, U+2295 ISOamsb */ },
-	{ 8855,	"otimes",/* circled times = vector product, U+2297 ISOamsb */ },
-	{ 8869,	"perp",	/* up tack = orthogonal to = perpendicular, U+22A5 ISOtech */ },
-	{ 8901,	"sdot",	/* dot operator, U+22C5 ISOamsb */ },
-	{ 8968,	"lceil",/* left ceiling = apl upstile, U+2308 ISOamsc */ },
-	{ 8969,	"rceil",/* right ceiling, U+2309 ISOamsc */ },
-	{ 8970,	"lfloor",/* left floor = apl downstile, U+230A ISOamsc */ },
-	{ 8971,	"rfloor",/* right floor, U+230B ISOamsc */ },
-	{ 9001,	"lang",	/* left-pointing angle bracket = bra, U+2329 ISOtech */ },
-	{ 9002,	"rang",	/* right-pointing angle bracket = ket, U+232A ISOtech */ },
-	{ 9674,	"loz",	/* lozenge, U+25CA ISOpub */ },
-
-	{ 9824,	"spades",/* black spade suit, U+2660 ISOpub */ },
-	{ 9827,	"clubs",/* black club suit = shamrock, U+2663 ISOpub */ },
-	{ 9829,	"hearts",/* black heart suit = valentine, U+2665 ISOpub */ },
-	{ 9830,	"diams",/* black diamond suit, U+2666 ISOpub */ },
-
-	{ 338,	"OElig",/* latin capital ligature OE, U+0152 ISOlat2 */ },
-	{ 339,	"oelig",/* latin small ligature oe, U+0153 ISOlat2 */ },
-	{ 352,	"Scaron",/* latin capital letter S with caron, U+0160 ISOlat2 */ },
-	{ 353,	"scaron",/* latin small letter s with caron, U+0161 ISOlat2 */ },
-	{ 376,	"Yuml",	/* latin capital letter Y with diaeresis, U+0178 ISOlat2 */ },
-	{ 710,	"circ",	/* modifier letter circumflex accent, U+02C6 ISOpub */ },
-	{ 732,	"tilde",/* small tilde, U+02DC ISOdia */ },
-
-	{ 8194,	"ensp",	/* en space, U+2002 ISOpub */ },
-	{ 8195,	"emsp",	/* em space, U+2003 ISOpub */ },
-	{ 8201,	"thinsp",/* thin space, U+2009 ISOpub */ },
-	{ 8204,	"zwnj",	/* zero width non-joiner, U+200C NEW RFC 2070 */ },
-	{ 8205,	"zwj",	/* zero width joiner, U+200D NEW RFC 2070 */ },
-	{ 8206,	"lrm",	/* left-to-right mark, U+200E NEW RFC 2070 */ },
-	{ 8207,	"rlm",	/* right-to-left mark, U+200F NEW RFC 2070 */ },
-	{ 8211,	"ndash",/* en dash, U+2013 ISOpub */ },
-	{ 8212,	"mdash",/* em dash, U+2014 ISOpub */ },
-	{ 8216,	"lsquo",/* left single quotation mark, U+2018 ISOnum */ },
-	{ 8217,	"rsquo",/* right single quotation mark, U+2019 ISOnum */ },
-	{ 8218,	"sbquo",/* single low-9 quotation mark, U+201A NEW */ },
-	{ 8220,	"ldquo",/* left double quotation mark, U+201C ISOnum */ },
-	{ 8221,	"rdquo",/* right double quotation mark, U+201D ISOnum */ },
-	{ 8222,	"bdquo",/* double low-9 quotation mark, U+201E NEW */ },
-	{ 8224,	"dagger",/* dagger, U+2020 ISOpub */ },
-	{ 8225,	"Dagger",/* double dagger, U+2021 ISOpub */ },
-	{ 8240,	"permil",/* per mille sign, U+2030 ISOtech */ },
-	{ 8249,	"lsaquo",/* single left-pointing angle quotation mark, U+2039 ISO proposed */ },
-	{ 8250,	"rsaquo",/* single right-pointing angle quotation mark, U+203A ISO proposed */ },
-	{ 8364,	"euro",	/* euro sign, U+20AC NEW */ }
-};
-
-static GHashTable *entities;
-
-/* this cannot be called in a thread context */
-static void tokenise_setup(void)
-{
-	int i;
-
-	if (entities == NULL) {
-		entities = g_hash_table_new(g_str_hash, g_str_equal);
-		for (i=0;istate = CAMEL_HTML_PARSER_DATA;
-
-	p->attr = 0;
-	p->attrs = g_ptr_array_new();
-	p->values = g_ptr_array_new();
-	p->tag = g_string_new("");
-	p->ent = g_string_new("");
-	p->charset = NULL;
-	
-	if (entities == NULL)
-		tokenise_setup();
-
-	return p;
-}
-
-static void tokenise_free(CamelHTMLParserPrivate *p)
-{
-	int i;
-
-	g_string_free(p->tag, TRUE);
-	g_string_free(p->ent, TRUE);
-	g_free(p->charset);
-
-	for (i=0;iattrs->len;i++)
-		g_string_free(p->attrs->pdata[i], TRUE);
-
-	for (i=0;ivalues->len;i++)
-		g_string_free(p->values->pdata[i], TRUE);
-
-	g_free(p);
-}
-
-static int convert_entity(const char *e, char *ent)
-{
-	unsigned int val;
-
-	if (e[0] == '#')
-		return g_unichar_to_utf8(atoi(e+1), ent);
-
-	val = GPOINTER_TO_UINT(g_hash_table_lookup(entities, e));
-	if (ent)
-		return g_unichar_to_utf8(val, ent);
-	else
-		return 0;
-}
-
-#if 0
-static void dump_tag(CamelHTMLParserPrivate *p)
-{
-	int i;
-
-	printf("got tag: %s\n", p->tag->str);
-	printf("%d attributes:\n", p->attr);
-	for (i=0;iattr;i++) {
-		printf(" %s = '%s'\n", ((GString *)p->attrs->pdata[i])->str, ((GString *)p->values->pdata[i])->str);
-	}
-}
-#endif
-
-static int tokenise_step(CamelHTMLParserPrivate *p, char **datap, int *lenp)
-{
-	char *in = p->inptr;
-	char *inend = p->inend;
-	char c;
-	int state = p->state, ret, len;
-	char *start = p->inptr;
-
-	d(printf("Tokenise step\n"));
-
-	while (in < inend) {
-		c = *in++;
-		switch (state) {
-		case CAMEL_HTML_PARSER_DATA:
-			if (c == '<') {
-				ret = state;
-				state = CAMEL_HTML_PARSER_TAG;
-				p->attr = 0;
-				g_string_truncate(p->tag, 0);
-				d(printf("got data '%.*s'\n", in-start-1, start));
-				*datap = start;
-				*lenp = in-start-1;
-				goto done;
-			} else if (c=='&') {
-				ret = state;
-				state = CAMEL_HTML_PARSER_ENT;
-				g_string_truncate(p->ent, 0);
-				g_string_append_c(p->ent, c);
-				d(printf("got data '%.*s'\n", in-start-1, start));
-				*datap = start;
-				*lenp = in-start-1;
-				goto done;
-			}
-			break;
-		case CAMEL_HTML_PARSER_ENT:
-			if (c==';') {
-				len = convert_entity(p->ent->str+1, p->ent_utf8);
-				if (len == 0) {
-					/* handle broken entity */
-					g_string_append_c(p->ent, c);
-					ret = state = CAMEL_HTML_PARSER_DATA;
-					*datap = p->ent->str;
-					*lenp = p->ent->len;
-					goto done;
-				} else {
-					d(printf("got entity: %s = %s\n", p->ent->str, p->ent_utf8));
-					ret = state;
-					state = CAMEL_HTML_PARSER_DATA;
-					*datap = p->ent_utf8;
-					*lenp = len;
-					goto done;
-				}
-			} else if (isalnum(c) || c=='#') { /* FIXME: right type */
-				g_string_append_c(p->ent, c);
-			} else {
-				/* handle broken entity */
-				g_string_append_c(p->ent, c);
-				ret = state = CAMEL_HTML_PARSER_DATA;
-				*datap = p->ent->str;
-				*lenp = p->ent->len;
-				goto done;
-			}
-			break;
-		case CAMEL_HTML_PARSER_TAG:
-			if (c == '!') {
-				state = CAMEL_HTML_PARSER_COMMENT0;
-				g_string_append_c(p->tag, c);
-			} else if (c == '>') {
-				d(dump_tag(p));
-				ret = CAMEL_HTML_PARSER_ELEMENT;
-				state = CAMEL_HTML_PARSER_DATA;
-				goto done;
-			} else if (c == ' ' || c=='\n' || c=='\t') {
-				state = CAMEL_HTML_PARSER_ATTR0;
-			} else {
-				g_string_append_c(p->tag, c);
-			}
-			break;
-			/* check for ",                FALSE, NULL               },
-	{ "np",          "
", FALSE, NULL }, - { "fontfamily", "", TRUE, param_parse_font }, - { "/fontfamily", "", FALSE, NULL }, - { "color", "", TRUE, param_parse_colour }, - { "/color", "", FALSE, NULL }, - { "lang", "", TRUE, param_parse_lang }, - { "/lang", "", FALSE, NULL }, - - /* don't handle this tag yet... */ - { "paraindent", "", FALSE, NULL }, - - /* as soon as we support all the tags that can have a param - * tag argument, these should be unnecessary, but we'll keep - * them anyway just in case? */ - { "param", "", FALSE, NULL }, -}; - -#define NUM_ENRICHED_TAGS (sizeof (enriched_tags) / sizeof (enriched_tags[0])) - -static GHashTable *enriched_hash = NULL; - - -static void camel_mime_filter_enriched_class_init (CamelMimeFilterEnrichedClass *klass); -static void camel_mime_filter_enriched_init (CamelMimeFilterEnriched *filter); -static void camel_mime_filter_enriched_finalize (CamelObject *obj); - -static void filter_filter (CamelMimeFilter *filter, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace); -static void filter_complete (CamelMimeFilter *filter, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace); -static void filter_reset (CamelMimeFilter *filter); - - -static CamelMimeFilterClass *parent_class = NULL; - - -CamelType -camel_mime_filter_enriched_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_mime_filter_get_type (), - "CamelMimeFilterEnriched", - sizeof (CamelMimeFilterEnriched), - sizeof (CamelMimeFilterEnrichedClass), - (CamelObjectClassInitFunc) camel_mime_filter_enriched_class_init, - NULL, - (CamelObjectInitFunc) camel_mime_filter_enriched_init, - (CamelObjectFinalizeFunc) camel_mime_filter_enriched_finalize); - } - - return type; -} - -static void -camel_mime_filter_enriched_class_init (CamelMimeFilterEnrichedClass *klass) -{ - CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass; - int i; - - parent_class = CAMEL_MIME_FILTER_CLASS (camel_mime_filter_get_type ()); - - filter_class->reset = filter_reset; - filter_class->filter = filter_filter; - filter_class->complete = filter_complete; - - if (!enriched_hash) { - enriched_hash = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); - for (i = 0; i < NUM_ENRICHED_TAGS; i++) - g_hash_table_insert (enriched_hash, enriched_tags[i].enriched, - enriched_tags[i].html); - } -} - -static void -camel_mime_filter_enriched_finalize (CamelObject *obj) -{ - ; -} - -static void -camel_mime_filter_enriched_init (CamelMimeFilterEnriched *filter) -{ - filter->flags = 0; - filter->nofill = 0; -} - - -#if 0 -static gboolean -enriched_tag_needs_param (const char *tag) -{ - int i; - - for (i = 0; i < NUM_ENRICHED_TAGS; i++) - if (!strcasecmp (tag, enriched_tags[i].enriched)) - return enriched_tags[i].needs_param; - - return FALSE; -} -#endif - -static gboolean -html_tag_needs_param (const char *tag) -{ - return strstr (tag, "%s") != NULL; -} - -static const char *valid_colours[] = { - "red", "green", "blue", "yellow", "cyan", "magenta", "black", "white" -}; - -#define NUM_VALID_COLOURS (sizeof (valid_colours) / sizeof (valid_colours[0])) - -static char * -param_parse_colour (const char *inptr, int inlen) -{ - const char *inend, *end; - guint32 rgb = 0; - guint v; - int i; - - for (i = 0; i < NUM_VALID_COLOURS; i++) { - if (!strncasecmp (inptr, valid_colours[i], inlen)) - return g_strdup (valid_colours[i]); - } - - /* check for numeric r/g/b in the format: ####,####,#### */ - if (inptr[4] != ',' || inptr[9] != ',') { - /* okay, mailer must have used a string name that - * rfc1896 did not specify? do some simple scanning - * action, a colour name MUST be [a-zA-Z] */ - end = inptr; - inend = inptr + inlen; - while (end < inend && ((*end >= 'a' && *end <= 'z') || (*end >= 'A' && *end <= 'Z'))) - end++; - - return g_strndup (inptr, end - inptr); - } - - for (i = 0; i < 3; i++) { - v = strtoul (inptr, (char **) &end, 16); - if (end != inptr + 4) - goto invalid_format; - - v >>= 8; - rgb = (rgb << 8) | (v & 0xff); - - inptr += 5; - } - - return g_strdup_printf ("#%.6X", rgb); - - invalid_format: - - /* default colour? */ - return g_strdup ("black"); -} - -static char * -param_parse_font (const char *fontfamily, int inlen) -{ - register const char *inptr = fontfamily; - const char *inend = inptr + inlen; - - /* don't allow any of '"', '<', nor '>' */ - while (inptr < inend && *inptr != '"' && *inptr != '<' && *inptr != '>') - inptr++; - - return g_strndup (fontfamily, inptr - fontfamily); -} - -static char * -param_parse_lang (const char *lang, int inlen) -{ - register const char *inptr = lang; - const char *inend = inptr + inlen; - - /* don't allow any of '"', '<', nor '>' */ - while (inptr < inend && *inptr != '"' && *inptr != '<' && *inptr != '>') - inptr++; - - return g_strndup (lang, inptr - lang); -} - -static char * -param_parse (const char *enriched, const char *inptr, int inlen) -{ - int i; - - for (i = 0; i < NUM_ENRICHED_TAGS; i++) { - if (!strcasecmp (enriched, enriched_tags[i].enriched)) - return enriched_tags[i].parse_param (inptr, inlen); - } - - g_assert_not_reached (); - - return NULL; -} - -#define IS_RICHTEXT CAMEL_MIME_FILTER_ENRICHED_IS_RICHTEXT - -static void -enriched_to_html (CamelMimeFilter *filter, char *in, size_t inlen, size_t prespace, - char **out, size_t *outlen, size_t *outprespace, gboolean flush) -{ - CamelMimeFilterEnriched *enriched = (CamelMimeFilterEnriched *) filter; - const char *tag, *inend, *outend; - register const char *inptr; - register char *outptr; - - camel_mime_filter_set_size (filter, inlen * 2 + 6, FALSE); - - inptr = in; - inend = in + inlen; - outptr = filter->outbuf; - outend = filter->outbuf + filter->outsize; - - retry: - do { - while (inptr < inend && outptr < outend && !strchr (" <>&\n", *inptr)) - *outptr++ = *inptr++; - - if (outptr == outend) - goto backup; - - if ((inptr + 1) >= inend) - break; - - switch (*inptr++) { - case ' ': - while (inptr < inend && (outptr + 7) < outend && *inptr == ' ') { - memcpy (outptr, " ", 6); - outptr += 6; - inptr++; - } - - if (outptr < outend) - *outptr++ = ' '; - - break; - case '\n': - if (!(enriched->flags & IS_RICHTEXT) && enriched->nofill <= 0) { - /* text/enriched */ - while (inptr < inend && (outptr + 4) < outend && *inptr == '\n') { - memcpy (outptr, "
", 4); - outptr += 4; - inptr++; - } - } else { - /* text/richtext */ - *outptr++ = ' '; - } - break; - case '>': - if ((outptr + 4) < outend) { - memcpy (outptr, ">", 4); - outptr += 4; - } else { - inptr--; - goto backup; - } - break; - case '&': - if ((outptr + 5) < outend) { - memcpy (outptr, "&", 5); - outptr += 5; - } else { - inptr--; - goto backup; - } - break; - case '<': - if (!(enriched->flags & IS_RICHTEXT)) { - /* text/enriched */ - if (*inptr == '<') { - if ((outptr + 4) < outend) { - memcpy (outptr, "<", 4); - outptr += 4; - inptr++; - break; - } else { - inptr--; - goto backup; - } - } - } else { - /* text/richtext */ - if ((inend - inptr) >= 3 && (outptr + 4) < outend) { - if (strncmp (inptr, "lt>", 3) == 0) { - memcpy (outptr, "<", 4); - outptr += 4; - inptr += 3; - break; - } else if (strncmp (inptr, "nl>", 3) == 0) { - memcpy (outptr, "
", 4); - outptr += 4; - inptr += 3; - break; - } - } else { - inptr--; - goto backup; - } - } - - tag = inptr; - while (inptr < inend && *inptr != '>') - inptr++; - - if (inptr == inend) { - inptr = tag - 1; - goto need_input; - } - - if (!strncasecmp (tag, "nofill>", 7)) { - if ((outptr + 5) < outend) { - memcpy (outptr, "
", 5);
-					enriched->nofill++;
-					outptr += 5;
-				} else {
-					inptr = tag - 1;
-					goto backup;
-				}
-			} else if (!strncasecmp (tag, "/nofill>", 8)) {
-				if ((outptr + 6) < outend) {
-					memcpy (outptr, "
", 6); - enriched->nofill--; - outptr += 6; - } else { - inptr = tag - 1; - goto backup; - } - } else { - const char *html_tag; - char *enriched_tag; - int len; - - len = inptr - tag; - enriched_tag = g_alloca (len + 1); - memcpy (enriched_tag, tag, len); - enriched_tag[len] = '\0'; - - html_tag = g_hash_table_lookup (enriched_hash, enriched_tag); - - if (html_tag) { - if (html_tag_needs_param (html_tag)) { - const char *start; - char *param; - - while (inptr < inend && *inptr != '<') - inptr++; - -#define PARAM_TAG_MIN_LEN (sizeof ("") + sizeof ("") - 1) - if (inptr == inend || (inend - inptr) <= PARAM_TAG_MIN_LEN) { - inptr = tag - 1; - goto need_input; - } - - if (strncasecmp (inptr, "", 7) != 0) { - /* ignore the enriched command tag... */ - inptr -= 1; - goto loop; - } - - inptr += 7; - start = inptr; - - while (inptr < inend && *inptr != '<') - inptr++; - - if (inptr == inend || (inend - inptr) <= 8) { - inptr = tag - 1; - goto need_input; - } - - if (strncasecmp (inptr, "", 8) != 0) { - /* ignore the enriched command tag... */ - inptr += 7; - goto loop; - } - - len = inptr - start; - param = param_parse (enriched_tag, start, len); - len = strlen (param); - - inptr += 7; - - len += strlen (html_tag); - - if ((outptr + len) < outend) { - outptr += snprintf (outptr, len, html_tag, param); - g_free (param); - } else { - g_free (param); - inptr = tag - 1; - goto backup; - } - } else { - len = strlen (html_tag); - if ((outptr + len) < outend) { - memcpy (outptr, html_tag, len); - outptr += len; - } else { - inptr = tag - 1; - goto backup; - } - } - } - } - - loop: - inptr++; - break; - default: - break; - } - } while (inptr < inend); - - need_input: - - /* the reason we ignore @flush here is because if there isn't - enough input to parse a tag, then there's nothing we can - do. */ - - if (inptr < inend) - camel_mime_filter_backup (filter, inptr, (unsigned) (inend - inptr)); - - *out = filter->outbuf; - *outlen = outptr - filter->outbuf; - *outprespace = filter->outpre; - - return; - - backup: - - if (flush) { - size_t offset, grow; - - grow = (inend - inptr) * 2 + 20; - offset = outptr - filter->outbuf; - camel_mime_filter_set_size (filter, filter->outsize + grow, TRUE); - outend = filter->outbuf + filter->outsize; - outptr = filter->outbuf + offset; - - goto retry; - } else { - camel_mime_filter_backup (filter, inptr, (unsigned) (inend - inptr)); - } - - *out = filter->outbuf; - *outlen = outptr - filter->outbuf; - *outprespace = filter->outpre; -} - -static void -filter_filter (CamelMimeFilter *filter, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace) -{ - enriched_to_html (filter, in, len, prespace, out, outlen, outprespace, FALSE); -} - -static void -filter_complete (CamelMimeFilter *filter, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace) -{ - enriched_to_html (filter, in, len, prespace, out, outlen, outprespace, TRUE); -} - -static void -filter_reset (CamelMimeFilter *filter) -{ - CamelMimeFilterEnriched *enriched = (CamelMimeFilterEnriched *) filter; - - enriched->nofill = 0; -} - - -/** - * camel_mime_filter_enriched_new: - * @flags: - * - * Creates a new CamelMimeFilterEnriched object. - * - * Returns a new CamelMimeFilter object. - **/ -CamelMimeFilter * -camel_mime_filter_enriched_new (guint32 flags) -{ - CamelMimeFilterEnriched *new; - - new = (CamelMimeFilterEnriched *) camel_object_new (CAMEL_TYPE_MIME_FILTER_ENRICHED); - new->flags = flags; - - return CAMEL_MIME_FILTER (new); -} - -char * -camel_enriched_to_html(const char *in, guint32 flags) -{ - CamelMimeFilter *filter; - size_t outlen, outpre; - char *outbuf; - - if (in == NULL) - return NULL; - - filter = camel_mime_filter_enriched_new(flags); - - camel_mime_filter_complete(filter, (char *)in, strlen(in), 0, &outbuf, &outlen, &outpre); - outbuf = g_strndup (outbuf, outlen); - camel_object_unref (filter); - - return outbuf; -} diff --git a/camel/camel-mime-filter-enriched.h b/camel/camel-mime-filter-enriched.h deleted file mode 100644 index 8561bd65a4..0000000000 --- a/camel/camel-mime-filter-enriched.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __CAMEL_MIME_FILTER_ENRICHED_H__ -#define __CAMEL_MIME_FILTER_ENRICHED_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#define CAMEL_TYPE_MIME_FILTER_ENRICHED (camel_mime_filter_enriched_get_type ()) -#define CAMEL_MIME_FILTER_ENRICHED(obj) (CAMEL_CHECK_CAST (obj, CAMEL_TYPE_MIME_FILTER_ENRICHED, CamelMimeFilterEnriched)) -#define CAMEL_MIME_FILTER_ENRICHED_CLASS(klass) (CAMEL_CHECK_CLASS_CAST (klass, CAMEL_TYPE_MIME_FILTER_ENRICHED, CamelMimeFilterEnrichedClass)) -#define CAMEL_IS_MIME_FILTER_ENRICHED(obj) (CAMEL_CHECK_TYPE (obj, CAMEL_TYPE_MIME_FILTER_ENRICHED)) - - -#define CAMEL_MIME_FILTER_ENRICHED_IS_RICHTEXT (1 << 0) - - -typedef struct _CamelMimeFilterEnriched CamelMimeFilterEnriched; -typedef struct _CamelMimeFilterEnrichedClass CamelMimeFilterEnrichedClass; - -struct _CamelMimeFilterEnriched { - CamelMimeFilter parent_object; - - guint32 flags; - int nofill; -}; - -struct _CamelMimeFilterEnrichedClass { - CamelMimeFilterClass parent_class; - -}; - -CamelType camel_mime_filter_enriched_get_type (void); - -CamelMimeFilter *camel_mime_filter_enriched_new (guint32 flags); -char *camel_enriched_to_html(const char *in, guint32 flags); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_MIME_FILTER_ENRICHED_H__ */ diff --git a/camel/camel-mime-filter-from.c b/camel/camel-mime-filter-from.c deleted file mode 100644 index 092f4d3904..0000000000 --- a/camel/camel-mime-filter-from.c +++ /dev/null @@ -1,217 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "camel-mime-filter-from.h" - -#define d(x) - -static void camel_mime_filter_from_class_init (CamelMimeFilterFromClass *klass); -static void camel_mime_filter_from_init (CamelMimeFilterFrom *obj); - -static CamelMimeFilterClass *camel_mime_filter_from_parent; - -CamelType -camel_mime_filter_from_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_mime_filter_get_type (), "CamelMimeFilterFrom", - sizeof (CamelMimeFilterFrom), - sizeof (CamelMimeFilterFromClass), - (CamelObjectClassInitFunc) camel_mime_filter_from_class_init, - NULL, - (CamelObjectInitFunc) camel_mime_filter_from_init, - NULL); - } - - return type; -} - -struct fromnode { - struct fromnode *next; - char *pointer; -}; - -static void -complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace) -{ - *out = in; - *outlen = len; - *outprespace = prespace; -} - -/* Yes, it is complicated ... */ -static void -filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace) -{ - CamelMimeFilterFrom *f = (CamelMimeFilterFrom *)mf; - register char *inptr, *inend; - int left; - int midline = f->midline; - int fromcount = 0; - struct fromnode *head = NULL, *tail = (struct fromnode *)&head, *node; - char *outptr; - - inptr = in; - inend = inptr+len; - - d(printf("Filtering '%.*s'\n", len, in)); - - /* first, see if we need to escape any from's */ - while (inptr 0) { - midline = TRUE; - if (left < 5) { - if (inptr[0] == 'F') { - camel_mime_filter_backup(mf, inptr, left); - midline = FALSE; - inend = inptr; - break; - } - } else { - if (!strncmp(inptr, "From ", 5)) { - fromcount++; - /* yes, we do alloc them on the stack ... at most we're going to get - len / 7 of them anyway */ - node = alloca(sizeof(*node)); - node->pointer = inptr; - node->next = NULL; - tail->next = node; - tail = node; - inptr += 5; - } - } - } else { - /* \n is at end of line, check next buffer */ - midline = FALSE; - } - } - } - - f->midline = midline; - - if (fromcount > 0) { - camel_mime_filter_set_size(mf, len + fromcount, FALSE); - node = head; - inptr = in; - outptr = mf->outbuf; - while (node) { - memcpy(outptr, inptr, node->pointer - inptr); - outptr += node->pointer - inptr; - *outptr++ = '>'; - inptr = node->pointer; - node = node->next; - } - memcpy(outptr, inptr, inend - inptr); - outptr += inend - inptr; - *out = mf->outbuf; - *outlen = outptr - mf->outbuf; - *outprespace = mf->outbuf - mf->outreal; - - d(printf("Filtered '%.*s'\n", *outlen, *out)); - } else { - *out = in; - *outlen = inend - in; - *outprespace = prespace; - - d(printf("Filtered '%.*s'\n", *outlen, *out)); - } -} - -static void -camel_mime_filter_from_class_init (CamelMimeFilterFromClass *klass) -{ - CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass; - - camel_mime_filter_from_parent = CAMEL_MIME_FILTER_CLASS (camel_type_get_global_classfuncs (camel_mime_filter_get_type ())); - - filter_class->filter = filter; - filter_class->complete = complete; -} - -static void -camel_mime_filter_from_init (CamelMimeFilterFrom *obj) -{ - ; -} - -/** - * camel_mime_filter_from_new: - * - * Create a new CamelMimeFilterFrom object. - * - * Return value: A new CamelMimeFilterFrom widget. - **/ -CamelMimeFilterFrom * -camel_mime_filter_from_new (void) -{ - CamelMimeFilterFrom *new = CAMEL_MIME_FILTER_FROM ( camel_object_new (camel_mime_filter_from_get_type ())); - return new; -} - -#if 0 - -#include - -int main(int argc, char **argv) -{ - CamelMimeFilterFrom *f; - char *buffer; - int len, prespace; - - g_tk_init(&argc, &argv); - - - f = camel_mime_filter_from_new(); - - buffer = "This is a test\nFrom Someone\nTo someone. From Someone else, From\n From blah\nFromblah\nBye! \nFrom "; - len = strlen(buffer); - prespace = 0; - - printf("input = '%.*s'\n", len, buffer); - camel_mime_filter_filter(f, buffer, len, prespace, &buffer, &len, &prespace); - printf("output = '%.*s'\n", len, buffer); - buffer = ""; - len = 0; - prespace = 0; - camel_mime_filter_complete(f, buffer, len, prespace, &buffer, &len, &prespace); - printf("complete = '%.*s'\n", len, buffer); - - - return 0; -} - -#endif diff --git a/camel/camel-mime-filter-from.h b/camel/camel-mime-filter-from.h deleted file mode 100644 index b8f1bb9a4e..0000000000 --- a/camel/camel-mime-filter-from.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_MIME_FILTER_FROM_H -#define _CAMEL_MIME_FILTER_FROM_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#define CAMEL_MIME_FILTER_FROM(obj) CAMEL_CHECK_CAST (obj, camel_mime_filter_from_get_type (), CamelMimeFilterFrom) -#define CAMEL_MIME_FILTER_FROM_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_mime_filter_from_get_type (), CamelMimeFilterFromClass) -#define CAMEL_IS_MIME_FILTER_FROM(obj) CAMEL_CHECK_TYPE (obj, camel_mime_filter_from_get_type ()) - -typedef struct _CamelMimeFilterFrom CamelMimeFilterFrom; -typedef struct _CamelMimeFilterFromClass CamelMimeFilterFromClass; - -struct _CamelMimeFilterFrom { - CamelMimeFilter parent; - - int midline; /* are we between lines? */ -}; - -struct _CamelMimeFilterFromClass { - CamelMimeFilterClass parent_class; -}; - -CamelType camel_mime_filter_from_get_type (void); -CamelMimeFilterFrom *camel_mime_filter_from_new (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_MIME_FILTER_FROM_H */ diff --git a/camel/camel-mime-filter-html.c b/camel/camel-mime-filter-html.c deleted file mode 100644 index 3a9bdaba75..0000000000 --- a/camel/camel-mime-filter-html.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2001 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include -#include -#include - - -#include -#include -#include -#include -#include - -#include "camel-mime-filter-html.h" -#include "camel-html-parser.h" - -#define d(x) - -static void camel_mime_filter_html_class_init (CamelMimeFilterHTMLClass *klass); -static void camel_mime_filter_html_init (CamelObject *o); -static void camel_mime_filter_html_finalize (CamelObject *o); - -static CamelMimeFilterClass *camel_mime_filter_html_parent; - -struct _CamelMimeFilterHTMLPrivate { - CamelHTMLParser *ctxt; -}; - -/* ********************************************************************** */ - -#if 0 - -/* well we odnt use this stuff yet */ - -#define ARRAY_LEN(x) (sizeof(x)/sizeof((x)[0])) - -static struct { - char *element; - char *remap; -} map_start[] = { - { "p", "\n\n" }, - { "br", "\n" }, - { "h1", "\n" }, { "h2", "\n" }, { "h3", "\n" }, { "h4", "\n" }, { "h5", "\n" }, { "h6", "\n" }, -}; - - -static struct { - char *element; - char *remap; -} map_end[] = { - { "h1", "\n" }, { "h2", "\n" }, { "h3", "\n" }, { "h4", "\n" }, { "h5", "\n" }, { "h6", "\n" }, -}; -#endif - - -/* ********************************************************************** */ - - -CamelType -camel_mime_filter_html_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_mime_filter_get_type (), "CamelMimeFilterHTML", - sizeof (CamelMimeFilterHTML), - sizeof (CamelMimeFilterHTMLClass), - (CamelObjectClassInitFunc) camel_mime_filter_html_class_init, - NULL, - (CamelObjectInitFunc) camel_mime_filter_html_init, - (CamelObjectFinalizeFunc) camel_mime_filter_html_finalize); - } - - return type; -} - -static void -camel_mime_filter_html_finalize(CamelObject *o) -{ - CamelMimeFilterHTML *f = (CamelMimeFilterHTML *)o; - - camel_object_unref((CamelObject *)f->priv->ctxt); - g_free(f->priv); -} - -static void -camel_mime_filter_html_init (CamelObject *o) -{ - CamelMimeFilterHTML *f = (CamelMimeFilterHTML *)o; - - f->priv = g_malloc0(sizeof(*f->priv)); - f->priv->ctxt = camel_html_parser_new(); -} - -static void -run(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlenptr, size_t *outprespace, int last) -{ - camel_html_parser_t state; - char *outp; - CamelMimeFilterHTML *f = (CamelMimeFilterHTML *)mf; - - d(printf("converting html:\n%.*s\n", (int)len, in)); - - /* We should generally shrink the data, but this'll do */ - camel_mime_filter_set_size(mf, len*2+256, FALSE); - outp = mf->outbuf; - - camel_html_parser_set_data(f->priv->ctxt, in, len, last); - do { - const char *data; - int len; - - state = camel_html_parser_step(f->priv->ctxt, &data, &len); - - switch(state) { - case CAMEL_HTML_PARSER_DATA: - case CAMEL_HTML_PARSER_ENT: - memcpy(outp, data, len); - outp += len; - break; - case CAMEL_HTML_PARSER_ELEMENT: - /* FIXME: do some whitespace processing here */ - break; - default: - /* ignore everything else */ - break; - } - } while (state != CAMEL_HTML_PARSER_EOF && state != CAMEL_HTML_PARSER_EOD); - - *out = mf->outbuf; - *outlenptr = outp - mf->outbuf; - *outprespace = mf->outbuf - mf->outreal; - - d(printf("converted html end:\n%.*s\n", (int)*outlenptr, *out)); -} - -static void -complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlenptr, size_t *outprespace) -{ - run(mf, in, len, prespace, out, outlenptr, outprespace, TRUE); -} - -static void -filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlenptr, size_t *outprespace) -{ - run(mf, in, len, prespace, out, outlenptr, outprespace, FALSE); -} - -static void -reset(CamelMimeFilter *mf) -{ - CamelMimeFilterHTML *f = (CamelMimeFilterHTML *)mf; - - camel_object_unref((CamelObject *)f->priv->ctxt); - f->priv->ctxt = camel_html_parser_new(); -} - -static void -camel_mime_filter_html_class_init (CamelMimeFilterHTMLClass *klass) -{ - CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass; - - camel_mime_filter_html_parent = CAMEL_MIME_FILTER_CLASS (camel_type_get_global_classfuncs (camel_mime_filter_get_type ())); - - filter_class->reset = reset; - filter_class->filter = filter; - filter_class->complete = complete; -} - -/** - * camel_mime_filter_html_new: - * - * Create a new CamelMimeFilterHTML object. - * - * Return value: A new CamelMimeFilterHTML widget. - **/ -CamelMimeFilterHTML * -camel_mime_filter_html_new (void) -{ - CamelMimeFilterHTML *new = CAMEL_MIME_FILTER_HTML ( camel_object_new (camel_mime_filter_html_get_type ())); - return new; -} diff --git a/camel/camel-mime-filter-html.h b/camel/camel-mime-filter-html.h deleted file mode 100644 index bb9b6aaa4e..0000000000 --- a/camel/camel-mime-filter-html.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2001 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_MIME_FILTER_HTML_H -#define _CAMEL_MIME_FILTER_HTML_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#define CAMEL_MIME_FILTER_HTML(obj) CAMEL_CHECK_CAST (obj, camel_mime_filter_html_get_type (), CamelMimeFilterHTML) -#define CAMEL_MIME_FILTER_HTML_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_mime_filter_html_get_type (), CamelMimeFilterHTMLClass) -#define CAMEL_IS_MIME_FILTER_HTML(obj) CAMEL_CHECK_TYPE (obj, camel_mime_filter_html_get_type ()) - -typedef struct _CamelMimeFilterHTMLClass CamelMimeFilterHTMLClass; -typedef struct _CamelMimeFilterHTML CamelMimeFilterHTML; - -struct _CamelMimeFilterHTML { - CamelMimeFilter parent; - - struct _CamelMimeFilterHTMLPrivate *priv; -}; - -struct _CamelMimeFilterHTMLClass { - CamelMimeFilterClass parent_class; -}; - -CamelType camel_mime_filter_html_get_type (void); -CamelMimeFilterHTML *camel_mime_filter_html_new (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_MIME_FILTER_HTML_H */ diff --git a/camel/camel-mime-filter-index.c b/camel/camel-mime-filter-index.c deleted file mode 100644 index 6648abf860..0000000000 --- a/camel/camel-mime-filter-index.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "camel-mime-filter-index.h" - -#include "camel-text-index.h" - -static void camel_mime_filter_index_class_init (CamelMimeFilterIndexClass *klass); -static void camel_mime_filter_index_finalize (CamelObject *o); - -static CamelMimeFilterClass *camel_mime_filter_index_parent; - -CamelType -camel_mime_filter_index_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_mime_filter_get_type (), "CamelMimeFilterIndex", - sizeof (CamelMimeFilterIndex), - sizeof (CamelMimeFilterIndexClass), - (CamelObjectClassInitFunc) camel_mime_filter_index_class_init, - NULL, - NULL, - (CamelObjectFinalizeFunc) camel_mime_filter_index_finalize); - } - - return type; -} - -static void -camel_mime_filter_index_finalize(CamelObject *o) -{ - CamelMimeFilterIndex *f = (CamelMimeFilterIndex *)o; - - if (f->name) - camel_object_unref((CamelObject *)f->name); - camel_object_unref((CamelObject *)f->index); -} - -static void -complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlenptr, size_t *outprespace) -{ - CamelMimeFilterIndex *f = (CamelMimeFilterIndex *)mf; - - if (f->index == NULL || f->name==NULL) { - goto donothing; - } - - camel_index_name_add_buffer(f->name, in, len); - camel_index_name_add_buffer(f->name, NULL, 0); - -donothing: - *out = in; - *outlenptr = len; - *outprespace = prespace; -} - -static void -filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlenptr, size_t *outprespace) -{ - CamelMimeFilterIndex *f = (CamelMimeFilterIndex *)mf; - - if (f->index == NULL || f->name==NULL) { - goto donothing; - } - - camel_index_name_add_buffer(f->name, in, len); - -donothing: - *out = in; - *outlenptr = len; - *outprespace = prespace; -} - -static void -camel_mime_filter_index_class_init (CamelMimeFilterIndexClass *klass) -{ - CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass; - - camel_mime_filter_index_parent = CAMEL_MIME_FILTER_CLASS (camel_type_get_global_classfuncs (camel_mime_filter_get_type ())); - - /*filter_class->reset = reset;*/ - filter_class->filter = filter; - filter_class->complete = complete; -} - -/** - * camel_mime_filter_index_new: - * - * Create a new CamelMimeFilterIndex object. - * - * Return value: A new CamelMimeFilterIndex widget. - **/ -CamelMimeFilterIndex * -camel_mime_filter_index_new (void) -{ - CamelMimeFilterIndex *new = CAMEL_MIME_FILTER_INDEX ( camel_object_new (camel_mime_filter_index_get_type ())); - return new; -} - -CamelMimeFilterIndex *camel_mime_filter_index_new_index (struct _CamelIndex *index) -{ - CamelMimeFilterIndex *new = camel_mime_filter_index_new(); - - if (new) { - new->index = index; - if (index) - camel_object_ref((CamelObject *)index); - } - return new; -} - -/* Set the match name for any indexed words */ -void camel_mime_filter_index_set_name (CamelMimeFilterIndex *mf, struct _CamelIndexName *name) -{ - if (mf->name) - camel_object_unref((CamelObject *)mf->name); - mf->name = name; - if (name) - camel_object_ref((CamelObject *)name); -} - -void camel_mime_filter_index_set_index (CamelMimeFilterIndex *mf, CamelIndex *index) -{ - if (mf->index) { - char *out; - size_t outlen, outspace; - - camel_mime_filter_complete((CamelMimeFilter *)mf, "", 0, 0, &out, &outlen, &outspace); - camel_object_unref ((CamelObject *)index); - } - - mf->index = index; - if (index) - camel_object_ref((CamelObject *)index); -} - - - diff --git a/camel/camel-mime-filter-index.h b/camel/camel-mime-filter-index.h deleted file mode 100644 index 3bb1bd532c..0000000000 --- a/camel/camel-mime-filter-index.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_MIME_FILTER_INDEX_H -#define _CAMEL_MIME_FILTER_INDEX_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#define CAMEL_MIME_FILTER_INDEX(obj) CAMEL_CHECK_CAST (obj, camel_mime_filter_index_get_type (), CamelMimeFilterIndex) -#define CAMEL_MIME_FILTER_INDEX_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_mime_filter_index_get_type (), CamelMimeFilterIndexClass) -#define CAMEL_IS_MIME_FILTER_INDEX(obj) CAMEL_CHECK_TYPE (obj, camel_mime_filter_index_get_type ()) - -typedef struct _CamelMimeFilterIndexClass CamelMimeFilterIndexClass; - -struct _CamelMimeFilterIndex { - CamelMimeFilter parent; - - struct _CamelMimeFilterIndexPrivate *priv; - - struct _CamelIndex *index; - struct _CamelIndexName *name; -}; - -struct _CamelMimeFilterIndexClass { - CamelMimeFilterClass parent_class; -}; - -CamelType camel_mime_filter_index_get_type (void); -CamelMimeFilterIndex *camel_mime_filter_index_new (void); - -CamelMimeFilterIndex *camel_mime_filter_index_new_index(struct _CamelIndex *); - -/* Set the match name for any indexed words */ -void camel_mime_filter_index_set_name (CamelMimeFilterIndex *, struct _CamelIndexName *name); -void camel_mime_filter_index_set_index (CamelMimeFilterIndex *mf, struct _CamelIndex *index); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_MIME_FILTER_INDEX_H */ diff --git a/camel/camel-mime-filter-linewrap.c b/camel/camel-mime-filter-linewrap.c deleted file mode 100644 index c9a741dacf..0000000000 --- a/camel/camel-mime-filter-linewrap.c +++ /dev/null @@ -1,147 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Ximian, Inc. - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "camel-mime-filter-linewrap.h" - - -static void filter (CamelMimeFilter *f, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace); -static void complete (CamelMimeFilter *f, char *in, size_t len, - size_t prespace, char **out, size_t *outlen, - size_t *outprespace); -static void reset (CamelMimeFilter *f); - - -static void -camel_mime_filter_linewrap_class_init (CamelMimeFilterLinewrapClass *klass) -{ - CamelMimeFilterClass *mime_filter_class = - (CamelMimeFilterClass *) klass; - - mime_filter_class->filter = filter; - mime_filter_class->complete = complete; - mime_filter_class->reset = reset; -} - -CamelType -camel_mime_filter_linewrap_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_mime_filter_get_type(), "CamelMimeFilterLinewrap", - sizeof (CamelMimeFilterLinewrap), - sizeof (CamelMimeFilterLinewrapClass), - (CamelObjectClassInitFunc) camel_mime_filter_linewrap_class_init, - NULL, - NULL, - NULL); - } - - return type; -} - -static void -filter (CamelMimeFilter *f, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace) -{ - CamelMimeFilterLinewrap *linewrap = (CamelMimeFilterLinewrap *)f; - char *inend, *last, *p, *q; - int nchars = linewrap->nchars; - - /* we'll be adding chars here so we need a bigger buffer */ - camel_mime_filter_set_size (f, 3 * len, FALSE); - - p = in; - q = f->outbuf; - inend = in + len; - - while (p < inend) { - if (*p == '\n') { - last = q; - *q++ = *p++; - nchars = 0; - } else if (isspace (*p)) { - last = q; - - if (nchars >= linewrap->wrap_len) { - *q++ = '\n'; - p++; - nchars = 0; - } else { - *q++ = *p++; - } - } else { - *q++ = *p++; - nchars++; - } - - /* line is getting way too long, we must force a wrap here */ - if (nchars >= (linewrap->max_len - 1) && *p != '\n') { - *q++ = '\n'; - *q++ = linewrap->indent; - nchars = 0; - } - } - - linewrap->nchars = nchars; - - *out = f->outbuf; - *outlen = q - f->outbuf; - *outprespace = f->outpre; -} - -static void -complete (CamelMimeFilter *f, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace) -{ - if (len) - filter (f, in, len, prespace, out, outlen, outprespace); -} - -static void -reset (CamelMimeFilter *f) -{ - CamelMimeFilterLinewrap *linewrap = (CamelMimeFilterLinewrap *)f; - - linewrap->nchars = 0; -} - -CamelMimeFilter * -camel_mime_filter_linewrap_new (guint preferred_len, guint max_len, char indent_char) -{ - CamelMimeFilterLinewrap *linewrap = - CAMEL_MIME_FILTER_LINEWRAP (camel_object_new (CAMEL_MIME_FILTER_LINEWRAP_TYPE)); - - linewrap->indent = indent_char; - linewrap->wrap_len = preferred_len; - linewrap->max_len = max_len; - linewrap->nchars = 0; - - return (CamelMimeFilter *) linewrap; -} diff --git a/camel/camel-mime-filter-linewrap.h b/camel/camel-mime-filter-linewrap.h deleted file mode 100644 index 1d6f444da4..0000000000 --- a/camel/camel-mime-filter-linewrap.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_MIME_FILTER_LINEWRAP_H -#define _CAMEL_MIME_FILTER_LINEWRAP_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#define CAMEL_MIME_FILTER_LINEWRAP_TYPE (camel_mime_filter_linewrap_get_type ()) -#define CAMEL_MIME_FILTER_LINEWRAP(obj) CAMEL_CHECK_CAST (obj, CAMEL_MIME_FILTER_LINEWRAP_TYPE, CamelMimeFilterLinewrap) -#define CAMEL_MIME_FILTER_LINEWRAP_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, CAMEL_MIME_FILTER_LINEWRAP_TYPE, CamelMimeFilterLinewrapClass) -#define CAMEL_IS_MIME_FILTER_LINEWRAP(obj) CAMEL_CHECK_TYPE (obj, CAMEL_MIME_FILTER_LINEWRAP_TYPE) - -typedef struct _CamelMimeFilterLinewrapClass CamelMimeFilterLinewrapClass; - -struct _CamelMimeFilterLinewrap { - CamelMimeFilter parent; - - guint wrap_len; - guint max_len; - char indent; - int nchars; -}; - -struct _CamelMimeFilterLinewrapClass { - CamelMimeFilterClass parent_class; -}; - -CamelType camel_mime_filter_linewrap_get_type (void); - -CamelMimeFilter *camel_mime_filter_linewrap_new (guint preferred_len, guint max_len, char indent_char); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_MIME_FILTER_LINEWRAP_H */ diff --git a/camel/camel-mime-filter-save.c b/camel/camel-mime-filter-save.c deleted file mode 100644 index 3c6bf4b8a3..0000000000 --- a/camel/camel-mime-filter-save.c +++ /dev/null @@ -1,115 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef HAVE_CONFIG_H -#include -#endif - -#include "camel-mime-filter-save.h" -#include "camel-stream-mem.h" - -static void filter (CamelMimeFilter *f, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace); -static void complete (CamelMimeFilter *f, char *in, size_t len, - size_t prespace, char **out, size_t *outlen, - size_t *outprespace); -static void reset (CamelMimeFilter *f); - - -static void -camel_mime_filter_save_class_init (CamelMimeFilterSaveClass *klass) -{ - CamelMimeFilterClass *mime_filter_class = - (CamelMimeFilterClass *) klass; - - mime_filter_class->filter = filter; - mime_filter_class->complete = complete; - mime_filter_class->reset = reset; -} - -CamelType -camel_mime_filter_save_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_mime_filter_get_type(), "CamelMimeFilterSave", - sizeof (CamelMimeFilterSave), - sizeof (CamelMimeFilterSaveClass), - (CamelObjectClassInitFunc) camel_mime_filter_save_class_init, - NULL, - NULL, - NULL); - } - - return type; -} - -static void -filter (CamelMimeFilter *f, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace) -{ - CamelMimeFilterSave *save = (CamelMimeFilterSave *) f; - - if (save->stream) - camel_stream_write (save->stream, in, len); - - *out = in; - *outlen = len; - *outprespace = f->outpre; -} - -static void -complete (CamelMimeFilter *f, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace) -{ - if (len) - filter (f, in, len, prespace, out, outlen, outprespace); -} - -static void -reset (CamelMimeFilter *f) -{ - /* no-op */ -} - -CamelMimeFilter * -camel_mime_filter_save_new (void) -{ - CamelMimeFilterSave *save = CAMEL_MIME_FILTER_SAVE (camel_object_new (CAMEL_MIME_FILTER_SAVE_TYPE)); - - save->stream = camel_stream_mem_new (); - - return (CamelMimeFilter *) save; -} - -CamelMimeFilter * -camel_mime_filter_save_new_with_stream (CamelStream *stream) -{ - CamelMimeFilterSave *save = CAMEL_MIME_FILTER_SAVE (camel_object_new (CAMEL_MIME_FILTER_SAVE_TYPE)); - - save->stream = stream; - camel_object_ref (stream); - - return (CamelMimeFilter *) save; -} diff --git a/camel/camel-mime-filter-save.h b/camel/camel-mime-filter-save.h deleted file mode 100644 index 20ebbea6f4..0000000000 --- a/camel/camel-mime-filter-save.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __CAMEL_MIME_FILTER_SAVE_H__ -#define __CAMEL_MIME_FILTER_SAVE_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include - -#define CAMEL_MIME_FILTER_SAVE_TYPE (camel_mime_filter_save_get_type ()) -#define CAMEL_MIME_FILTER_SAVE(obj) CAMEL_CHECK_CAST (obj, camel_mime_filter_save_get_type (), CamelMimeFilterSave) -#define CAMEL_MIME_FILTER_SAVE_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_mime_filter_save_get_type (), CamelMimeFilterSaveClass) -#define CAMEL_IS_MIME_FILTER_SAVE(obj) CAMEL_CHECK_TYPE (obj, camel_mime_filter_save_get_type ()) - -typedef struct _CamelMimeFilterSaveClass CamelMimeFilterSaveClass; - -struct _CamelMimeFilterSave { - CamelMimeFilter parent; - - CamelStream *stream; -}; - -struct _CamelMimeFilterSaveClass { - CamelMimeFilterClass parent_class; -}; - -CamelType camel_mime_filter_save_get_type (void); - -CamelMimeFilter *camel_mime_filter_save_new (void); -CamelMimeFilter *camel_mime_filter_save_new_with_stream (CamelStream *stream); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_MIME_FILTER_SAVE_H__ */ diff --git a/camel/camel-mime-filter-tohtml.c b/camel/camel-mime-filter-tohtml.c deleted file mode 100644 index 678d8005f4..0000000000 --- a/camel/camel-mime-filter-tohtml.c +++ /dev/null @@ -1,447 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "camel-url-scanner.h" -#include "camel-mime-filter-tohtml.h" -#include "camel-utf8.h" - -/** - * TODO: convert common text/plain 'markup' to html. eg.: - * - * _word_ -> _word_ - * *word* -> *word* - * /word/ -> /word/ - **/ - -#define d(x) - -#define CONVERT_WEB_URLS CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS -#define CONVERT_ADDRSPEC CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES - -static struct { - unsigned int mask; - urlpattern_t pattern; -} patterns[] = { - { CONVERT_WEB_URLS, { "file://", "", camel_url_file_start, camel_url_file_end } }, - { CONVERT_WEB_URLS, { "ftp://", "", camel_url_web_start, camel_url_web_end } }, - { CONVERT_WEB_URLS, { "http://", "", camel_url_web_start, camel_url_web_end } }, - { CONVERT_WEB_URLS, { "https://", "", camel_url_web_start, camel_url_web_end } }, - { CONVERT_WEB_URLS, { "news://", "", camel_url_web_start, camel_url_web_end } }, - { CONVERT_WEB_URLS, { "nntp://", "", camel_url_web_start, camel_url_web_end } }, - { CONVERT_WEB_URLS, { "telnet://", "", camel_url_web_start, camel_url_web_end } }, - { CONVERT_WEB_URLS, { "www.", "http://", camel_url_web_start, camel_url_web_end } }, - { CONVERT_WEB_URLS, { "ftp.", "ftp://", camel_url_web_start, camel_url_web_end } }, - { CONVERT_ADDRSPEC, { "@", "mailto:", camel_url_addrspec_start, camel_url_addrspec_end } }, -}; - -#define NUM_URL_PATTERNS (sizeof (patterns) / sizeof (patterns[0])) - -static void camel_mime_filter_tohtml_class_init (CamelMimeFilterToHTMLClass *klass); -static void camel_mime_filter_tohtml_init (CamelMimeFilterToHTML *filter); -static void camel_mime_filter_tohtml_finalize (CamelObject *obj); - -static CamelMimeFilterClass *camel_mime_filter_tohtml_parent; - - -CamelType -camel_mime_filter_tohtml_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_mime_filter_get_type (), - "CamelMimeFilterToHTML", - sizeof (CamelMimeFilterToHTML), - sizeof (CamelMimeFilterToHTMLClass), - (CamelObjectClassInitFunc) camel_mime_filter_tohtml_class_init, - NULL, - (CamelObjectInitFunc) camel_mime_filter_tohtml_init, - (CamelObjectFinalizeFunc) camel_mime_filter_tohtml_finalize); - } - - return type; -} - -static void -camel_mime_filter_tohtml_finalize (CamelObject *obj) -{ - CamelMimeFilterToHTML *filter = (CamelMimeFilterToHTML *) obj; - - camel_url_scanner_free (filter->scanner); -} - -static void -camel_mime_filter_tohtml_init (CamelMimeFilterToHTML *filter) -{ - filter->scanner = camel_url_scanner_new (); - - filter->flags = 0; - filter->colour = 0; - filter->column = 0; - filter->pre_open = FALSE; -} - - -static char * -check_size (CamelMimeFilter *filter, char *outptr, char **outend, size_t len) -{ - size_t offset; - - if (*outend - outptr >= len) - return outptr; - - offset = outptr - filter->outbuf; - - camel_mime_filter_set_size (filter, filter->outsize + len, TRUE); - - *outend = filter->outbuf + filter->outsize; - - return filter->outbuf + offset; -} - -static int -citation_depth (const char *in) -{ - register const char *inptr = in; - int depth = 1; - - if (*inptr++ != '>') - return 0; - - /* check that it isn't an escaped From line */ - if (!strncmp (inptr, "From", 4)) - return 0; - - while (*inptr != '\n') { - if (*inptr == ' ') - inptr++; - - if (*inptr++ != '>') - break; - - depth++; - } - - return depth; -} - -static char * -writeln (CamelMimeFilter *filter, const char *in, const char *inend, char *outptr, char **outend) -{ - CamelMimeFilterToHTML *html = (CamelMimeFilterToHTML *) filter; - const char *inptr = in; - - while (inptr < inend) { - guint32 u; - - outptr = check_size (filter, outptr, outend, 16); - - u = camel_utf8_getc_limit ((const unsigned char **) &inptr, inend); - switch (u) { - case 0xffff: - g_warning("Truncated utf8 buffer"); - return outptr; - case '<': - outptr = g_stpcpy (outptr, "<"); - html->column++; - break; - case '>': - outptr = g_stpcpy (outptr, ">"); - html->column++; - break; - case '&': - outptr = g_stpcpy (outptr, "&"); - html->column++; - break; - case '"': - outptr = g_stpcpy (outptr, """); - html->column++; - break; - case '\t': - if (html->flags & (CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES)) { - do { - outptr = check_size (filter, outptr, outend, 7); - outptr = g_stpcpy (outptr, " "); - html->column++; - } while (html->column % 8); - break; - } - /* otherwise, FALL THROUGH */ - case ' ': - if (html->flags & CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES - && ((inptr == (in + 1) || *inptr == ' ' || *inptr == '\t'))) { - outptr = g_stpcpy (outptr, " "); - html->column++; - break; - } - /* otherwise, FALL THROUGH */ - default: - if (u >= 20 && u <0x80) - *outptr++ = u; - else { - if (html->flags & CAMEL_MIME_FILTER_TOHTML_ESCAPE_8BIT) - *outptr++ = '?'; - else - outptr += sprintf(outptr, "&#%u;", u); - } - html->column++; - break; - } - } - - return outptr; -} - -static void -html_convert (CamelMimeFilter *filter, char *in, size_t inlen, size_t prespace, - char **out, size_t *outlen, size_t *outprespace, gboolean flush) -{ - CamelMimeFilterToHTML *html = (CamelMimeFilterToHTML *) filter; - register char *inptr, *outptr; - char *start, *outend; - const char *inend; - int depth; - - if (inlen == 0) { - *out = in; - *outlen = 0; - *outprespace = 0; - - return; - } - - camel_mime_filter_set_size (filter, inlen * 2 + 6, FALSE); - - inptr = in; - inend = in + inlen; - outptr = filter->outbuf; - outend = filter->outbuf + filter->outsize; - - if (html->flags & CAMEL_MIME_FILTER_TOHTML_PRE && !html->pre_open) { - outptr = g_stpcpy (outptr, "
");
-		html->pre_open = TRUE;
-	}
-
-	start = inptr;
-	do {
-		while (inptr < inend && *inptr != '\n')
-			inptr++;
-
-		if (inptr >= inend && !flush)
-			break;
-
-		html->column = 0;
-		depth = 0;
-		
-		if (html->flags & CAMEL_MIME_FILTER_TOHTML_MARK_CITATION) {
-			if ((depth = citation_depth (start)) > 0) {
-				/* FIXME: we could easily support multiple colour depths here */
-				
-				outptr = check_size (filter, outptr, &outend, 25);
-				outptr += sprintf(outptr, "", (html->colour & 0xffffff));
-			} else if (*start == '>') {
-				/* >From line */
-				start++;
-			}
-		} else if (html->flags & CAMEL_MIME_FILTER_TOHTML_CITE) {
-			outptr = check_size (filter, outptr, &outend, 6);
-			outptr = g_stpcpy (outptr, "> ");
-			html->column += 2;
-		}
-		
-#define CONVERT_URLS (CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES)
-		if (html->flags & CONVERT_URLS) {
-			size_t matchlen, buflen, len;
-			urlmatch_t match;
-			
-			len = inptr - start;
-			
-			do {
-				if (camel_url_scanner_scan (html->scanner, start, len, &match)) {
-					/* write out anything before the first regex match */
-					outptr = writeln (filter, start, start + match.um_so,
-							  outptr, &outend);
-					
-					start += match.um_so;
-					len -= match.um_so;
-					
-					matchlen = match.um_eo - match.um_so;
-					
-					buflen = 20 + strlen (match.prefix) + matchlen + matchlen;
-					outptr = check_size (filter, outptr, &outend, buflen);
-					
-					/* write out the href tag */
-					outptr = g_stpcpy (outptr, "");
-					
-					/* now write the matched string */
-					memcpy (outptr, start, matchlen);
-					html->column += matchlen;
-					outptr += matchlen;
-					start += matchlen;
-					len -= matchlen;
-					
-					/* close the href tag */
-					outptr = g_stpcpy (outptr, "");
-				} else {
-					/* nothing matched so write out the remainder of this line buffer */
-					outptr = writeln (filter, start, start + len, outptr, &outend);
-					break;
-				}
-			} while (len > 0);
-		} else {
-			outptr = writeln (filter, start, inptr, outptr, &outend);
-		}
-		
-		if ((html->flags & CAMEL_MIME_FILTER_TOHTML_MARK_CITATION) && depth > 0) {
-			outptr = check_size (filter, outptr, &outend, 8);
-			outptr = g_stpcpy (outptr, "");
-		}
-		
-		if (inptr < inend) {
-			if (html->flags & CAMEL_MIME_FILTER_TOHTML_CONVERT_NL) {
-				outptr = check_size (filter, outptr, &outend, 5);
-				outptr = g_stpcpy (outptr, "
"); - } - - *outptr++ = '\n'; - } - - start = ++inptr; - } while (inptr < inend); - - if (flush) { - /* flush the rest of our input buffer */ - if (start < inend) - outptr = writeln (filter, start, inend, outptr, &outend); - - if (html->pre_open) { - /* close the pre-tag */ - outptr = check_size (filter, outptr, &outend, 10); - outptr = g_stpcpy (outptr, "
"); - } - } else if (start < inend) { - /* backup */ - camel_mime_filter_backup (filter, start, (unsigned) (inend - start)); - } - - *out = filter->outbuf; - *outlen = outptr - filter->outbuf; - *outprespace = filter->outpre; -} - -static void -filter_filter (CamelMimeFilter *filter, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace) -{ - html_convert (filter, in, len, prespace, out, outlen, outprespace, FALSE); -} - -static void -filter_complete (CamelMimeFilter *filter, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace) -{ - html_convert (filter, in, len, prespace, out, outlen, outprespace, TRUE); -} - -static void -filter_reset (CamelMimeFilter *filter) -{ - CamelMimeFilterToHTML *html = (CamelMimeFilterToHTML *) filter; - - html->column = 0; - html->pre_open = FALSE; -} - -static void -camel_mime_filter_tohtml_class_init (CamelMimeFilterToHTMLClass *klass) -{ - CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass; - - camel_mime_filter_tohtml_parent = CAMEL_MIME_FILTER_CLASS (camel_type_get_global_classfuncs (camel_mime_filter_get_type ())); - - filter_class->reset = filter_reset; - filter_class->filter = filter_filter; - filter_class->complete = filter_complete; -} - - -/** - * camel_mime_filter_tohtml_new: - * @flags: - * @colour: - * - * Creates a new CamelMimeFilterToHTML object. - * - * Returns a new CamelMimeFilter object. - **/ -CamelMimeFilter * -camel_mime_filter_tohtml_new (guint32 flags, guint32 colour) -{ - CamelMimeFilterToHTML *new; - int i; - - new = CAMEL_MIME_FILTER_TOHTML (camel_object_new (camel_mime_filter_tohtml_get_type ())); - - new->flags = flags; - new->colour = colour; - - for (i = 0; i < NUM_URL_PATTERNS; i++) { - if (patterns[i].mask & flags) - camel_url_scanner_add (new->scanner, &patterns[i].pattern); - } - - return CAMEL_MIME_FILTER (new); -} - - -char * -camel_text_to_html (const char *in, guint32 flags, guint32 colour) -{ - CamelMimeFilter *filter; - size_t outlen, outpre; - char *outbuf; - - g_return_val_if_fail (in != NULL, NULL); - - filter = camel_mime_filter_tohtml_new (flags, colour); - - camel_mime_filter_complete (filter, (char *) in, strlen (in), 0, - &outbuf, &outlen, &outpre); - - outbuf = g_strndup (outbuf, outlen); - - camel_object_unref (filter); - - return outbuf; -} diff --git a/camel/camel-mime-filter-tohtml.h b/camel/camel-mime-filter-tohtml.h deleted file mode 100644 index de8690a1e0..0000000000 --- a/camel/camel-mime-filter-tohtml.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __CAMEL_MIME_FILTER_TOHTML_H__ -#define __CAMEL_MIME_FILTER_TOHTML_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#define CAMEL_MIME_FILTER_TOHTML(obj) CAMEL_CHECK_CAST (obj, camel_mime_filter_tohtml_get_type (), CamelMimeFilterToHTML) -#define CAMEL_MIME_FILTER_TOHTML_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_mime_filter_tohtml_get_type (), CamelMimeFilterToHTMLClass) -#define CAMEL_IS_MIME_FILTER_TOHTML(obj) CAMEL_CHECK_TYPE (obj, camel_mime_filter_tohtml_get_type ()) - -#define CAMEL_MIME_FILTER_TOHTML_PRE (1 << 0) -#define CAMEL_MIME_FILTER_TOHTML_CONVERT_NL (1 << 1) -#define CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES (1 << 2) -#define CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS (1 << 3) -#define CAMEL_MIME_FILTER_TOHTML_MARK_CITATION (1 << 4) -#define CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES (1 << 5) -#define CAMEL_MIME_FILTER_TOHTML_ESCAPE_8BIT (1 << 6) -#define CAMEL_MIME_FILTER_TOHTML_CITE (1 << 7) -#define CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT (1 << 8) -#define CAMEL_MIME_FILTER_TOHTML_FORMAT_FLOWED (1 << 9) - -typedef struct _CamelMimeFilterToHTMLClass CamelMimeFilterToHTMLClass; -typedef struct _CamelMimeFilterToHTML CamelMimeFilterToHTML; - -struct _CamelMimeFilterToHTML { - CamelMimeFilter parent; - - struct _CamelUrlScanner *scanner; - - guint32 flags; - guint32 colour; - - guint32 column : 31; - guint32 pre_open : 1; -}; - -struct _CamelMimeFilterToHTMLClass { - CamelMimeFilterClass parent_class; -}; - - -CamelType camel_mime_filter_tohtml_get_type (void); - -CamelMimeFilter *camel_mime_filter_tohtml_new (guint32 flags, guint32 colour); - - -/* utility functions to replace e_text_to_html shit */ - -char *camel_text_to_html (const char *in, guint32 flags, guint32 colour); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_MIME_FILTER_TOHTML_H__ */ diff --git a/camel/camel-mime-filter-windows.c b/camel/camel-mime-filter-windows.c deleted file mode 100644 index 0b6e00dea0..0000000000 --- a/camel/camel-mime-filter-windows.c +++ /dev/null @@ -1,180 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "camel-mime-filter-windows.h" - -#include "camel-charset-map.h" - -#define d(x) - -static void camel_mime_filter_windows_class_init (CamelMimeFilterWindowsClass *klass); -static void camel_mime_filter_windows_init (CamelObject *o); -static void camel_mime_filter_windows_finalize (CamelObject *o); - - -static CamelMimeFilterClass *parent_class = NULL; - - -CamelType -camel_mime_filter_windows_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_mime_filter_get_type (), - "CamelMimeFilterWindows", - sizeof (CamelMimeFilterWindows), - sizeof (CamelMimeFilterWindowsClass), - (CamelObjectClassInitFunc) camel_mime_filter_windows_class_init, - NULL, - (CamelObjectInitFunc) camel_mime_filter_windows_init, - (CamelObjectFinalizeFunc) camel_mime_filter_windows_finalize); - } - - return type; -} - -static void -camel_mime_filter_windows_finalize (CamelObject *o) -{ - CamelMimeFilterWindows *windows = (CamelMimeFilterWindows *) o; - - g_free (windows->claimed_charset); -} - -static void -camel_mime_filter_windows_init (CamelObject *o) -{ - CamelMimeFilterWindows *windows = (CamelMimeFilterWindows *) o; - - windows->is_windows = FALSE; - windows->claimed_charset = NULL; -} - -static void -filter_filter (CamelMimeFilter *filter, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace) -{ - CamelMimeFilterWindows *windows = (CamelMimeFilterWindows *) filter; - register unsigned char *inptr; - unsigned char *inend; - - if (!windows->is_windows) { - inptr = (unsigned char *) in; - inend = inptr + len; - - while (inptr < inend) { - register unsigned char c = *inptr++; - - if (c >= 128 && c <= 159) { - g_warning ("Encountered Windows charset parading as %s", - windows->claimed_charset); - windows->is_windows = TRUE; - break; - } - } - } - - *out = in; - *outlen = len; - *outprespace = prespace; -} - -static void -filter_complete (CamelMimeFilter *filter, char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace) -{ - filter_filter (filter, in, len, prespace, out, outlen, outprespace); -} - -static void -filter_reset (CamelMimeFilter *filter) -{ - CamelMimeFilterWindows *windows = (CamelMimeFilterWindows *) filter; - - windows->is_windows = FALSE; -} - -static void -camel_mime_filter_windows_class_init (CamelMimeFilterWindowsClass *klass) -{ - CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass; - - parent_class = CAMEL_MIME_FILTER_CLASS (camel_type_get_global_classfuncs (camel_mime_filter_get_type ())); - - filter_class->reset = filter_reset; - filter_class->filter = filter_filter; - filter_class->complete = filter_complete; -} - - -/** - * camel_mime_filter_windows_new: - * @claimed_charset: - * - * Creates a new CamelMimeFilterWindows object. - * - * Returns a new CamelMimeFilter object. - **/ -CamelMimeFilter * -camel_mime_filter_windows_new (const char *claimed_charset) -{ - CamelMimeFilterWindows *new; - - g_return_val_if_fail (claimed_charset != NULL, NULL); - - new = CAMEL_MIME_FILTER_WINDOWS (camel_object_new (camel_mime_filter_windows_get_type ())); - - new->claimed_charset = g_strdup (claimed_charset); - - return CAMEL_MIME_FILTER (new); -} - - -gboolean -camel_mime_filter_windows_is_windows_charset (CamelMimeFilterWindows *filter) -{ - g_return_val_if_fail (CAMEL_IS_MIME_FILTER_WINDOWS (filter), FALSE); - - return filter->is_windows; -} - - -const char * -camel_mime_filter_windows_real_charset (CamelMimeFilterWindows *filter) -{ - g_return_val_if_fail (CAMEL_IS_MIME_FILTER_WINDOWS (filter), NULL); - - if (filter->is_windows) - return camel_charset_iso_to_windows (filter->claimed_charset); - else - return filter->claimed_charset; -} diff --git a/camel/camel-mime-filter-windows.h b/camel/camel-mime-filter-windows.h deleted file mode 100644 index d2dac4fe92..0000000000 --- a/camel/camel-mime-filter-windows.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __CAMEL_MIME_FILTER_WINDOWS_H__ -#define __CAMEL_MIME_FILTER_WINDOWS_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#define CAMEL_MIME_FILTER_WINDOWS(obj) CAMEL_CHECK_CAST (obj, camel_mime_filter_windows_get_type (), CamelMimeFilterWindows) -#define CAMEL_MIME_FILTER_WINDOWS_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_mime_filter_windows_get_type (), CamelMimeFilterWindowsClass) -#define CAMEL_IS_MIME_FILTER_WINDOWS(obj) CAMEL_CHECK_TYPE (obj, camel_mime_filter_windows_get_type ()) - -typedef struct _CamelMimeFilterWindowsClass CamelMimeFilterWindowsClass; -typedef struct _CamelMimeFilterWindows CamelMimeFilterWindows; - -struct _CamelMimeFilterWindows { - CamelMimeFilter parent; - - gboolean is_windows; - char *claimed_charset; -}; - -struct _CamelMimeFilterWindowsClass { - CamelMimeFilterClass parent_class; - -}; - - -CamelType camel_mime_filter_windows_get_type (void); - -CamelMimeFilter *camel_mime_filter_windows_new (const char *claimed_charset); - -gboolean camel_mime_filter_windows_is_windows_charset (CamelMimeFilterWindows *filter); -const char *camel_mime_filter_windows_real_charset (CamelMimeFilterWindows *filter); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_MIME_FILTER_WINDOWS_H__ */ diff --git a/camel/camel-mime-filter.c b/camel/camel-mime-filter.c deleted file mode 100644 index 6e94b3cde4..0000000000 --- a/camel/camel-mime-filter.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include -#include "camel-mime-filter.h" - -/*#define MALLOC_CHECK */ /* for some malloc checking, requires mcheck enabled */ - -/* only suitable for glibc */ -#ifdef MALLOC_CHECK -#include -#endif - -struct _CamelMimeFilterPrivate { - char *inbuf; - size_t inlen; -}; - -#define PRE_HEAD (64) -#define BACK_HEAD (64) -#define _PRIVATE(o) (((CamelMimeFilter *)(o))->priv) -#define FCLASS(o) ((CamelMimeFilterClass *)(CAMEL_OBJECT_GET_CLASS(o))) - -static CamelObjectClass *camel_mime_filter_parent; - -static void complete (CamelMimeFilter *mf, char *in, size_t len, - size_t prespace, char **out, size_t *outlen, - size_t *outprespace); - -static void -camel_mime_filter_class_init (CamelMimeFilterClass *klass) -{ - camel_mime_filter_parent = camel_type_get_global_classfuncs (camel_object_get_type ()); - - klass->complete = complete; -} - -static void -camel_mime_filter_init (CamelMimeFilter *obj) -{ - obj->outreal = NULL; - obj->outbuf = NULL; - obj->outsize = 0; - - obj->backbuf = NULL; - obj->backsize = 0; - obj->backlen = 0; - - _PRIVATE(obj) = g_malloc0(sizeof(*obj->priv)); -} - -static void -camel_mime_filter_finalize(CamelObject *o) -{ - CamelMimeFilter *f = (CamelMimeFilter *)o; - struct _CamelMimeFilterPrivate *p = _PRIVATE(f); - - g_free(f->outreal); - g_free(f->backbuf); - g_free(p->inbuf); - g_free(p); -} - -CamelType -camel_mime_filter_get_type (void) -{ - static CamelType camel_mime_filter_type = CAMEL_INVALID_TYPE; - - if (camel_mime_filter_type == CAMEL_INVALID_TYPE) { - camel_mime_filter_type = camel_type_register (CAMEL_OBJECT_TYPE, "CamelMimeFilter", - sizeof (CamelMimeFilter), - sizeof (CamelMimeFilterClass), - (CamelObjectClassInitFunc) camel_mime_filter_class_init, - NULL, - (CamelObjectInitFunc) camel_mime_filter_init, - (CamelObjectFinalizeFunc) camel_mime_filter_finalize); - } - - return camel_mime_filter_type; -} - -static void -complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace) -{ - /* default - do nothing */ -} - -/** - * camel_mime_filter_new: - * - * Create a new CamelMimeFilter object. - * - * Return value: A new CamelMimeFilter widget. - **/ -CamelMimeFilter * -camel_mime_filter_new (void) -{ - CamelMimeFilter *new = CAMEL_MIME_FILTER ( camel_object_new (camel_mime_filter_get_type ())); - return new; -} - -#ifdef MALLOC_CHECK -static void -checkmem(void *p) -{ - if (p) { - int status = mprobe(p); - - switch (status) { - case MCHECK_HEAD: - printf("Memory underrun at %p\n", p); - abort(); - case MCHECK_TAIL: - printf("Memory overrun at %p\n", p); - abort(); - case MCHECK_FREE: - printf("Double free %p\n", p); - abort(); - } - } -} -#endif - -static void filter_run(CamelMimeFilter *f, - char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace, - void (*filterfunc)(CamelMimeFilter *f, - char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace)) -{ - struct _CamelMimeFilterPrivate *p; - -#ifdef MALLOC_CHECK - checkmem(f->outreal); - checkmem(f->backbuf); -#endif - /* - here we take a performance hit, if the input buffer doesn't - have the pre-space required. We make a buffer that does ... - */ - if (prespace < f->backlen) { - int newlen = len+prespace+f->backlen; - p = _PRIVATE(f); - if (p->inlen < newlen) { - /* NOTE: g_realloc copies data, we dont need that (slower) */ - g_free(p->inbuf); - p->inbuf = g_malloc(newlen+PRE_HEAD); - p->inlen = newlen+PRE_HEAD; - } - /* copy to end of structure */ - memcpy(p->inbuf+p->inlen - len, in, len); - in = p->inbuf+p->inlen - len; - prespace = p->inlen - len; - } - -#ifdef MALLOC_CHECK - checkmem(f->outreal); - checkmem(f->backbuf); -#endif - - /* preload any backed up data */ - if (f->backlen > 0) { - memcpy(in-f->backlen, f->backbuf, f->backlen); - in -= f->backlen; - len += f->backlen; - prespace -= f->backlen; - f->backlen = 0; - } - - filterfunc(f, in, len, prespace, out, outlen, outprespace); - -#ifdef MALLOC_CHECK - checkmem(f->outreal); - checkmem(f->backbuf); -#endif - -} - -void camel_mime_filter_filter(CamelMimeFilter *f, - char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace) -{ - if (FCLASS(f)->filter) - filter_run(f, in, len, prespace, out, outlen, outprespace, FCLASS(f)->filter); - else - g_error("Filter function unplmenented in class"); -} - -void camel_mime_filter_complete(CamelMimeFilter *f, - char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace) -{ - if (FCLASS(f)->complete) - filter_run(f, in, len, prespace, out, outlen, outprespace, FCLASS(f)->complete); -} - -void camel_mime_filter_reset(CamelMimeFilter *f) -{ - if (FCLASS(f)->reset) { - FCLASS(f)->reset(f); - } - - /* could free some buffers, if they are really big? */ - f->backlen = 0; -} - -/* sets number of bytes backed up on the input, new calls replace previous ones */ -void camel_mime_filter_backup(CamelMimeFilter *f, const char *data, size_t length) -{ - if (f->backsize < length) { - /* g_realloc copies data, unnecessary overhead */ - g_free(f->backbuf); - f->backbuf = g_malloc(length+BACK_HEAD); - f->backsize = length+BACK_HEAD; - } - f->backlen = length; - memcpy(f->backbuf, data, length); -} - -/* ensure this much size available for filter output (if required) */ -void camel_mime_filter_set_size(CamelMimeFilter *f, size_t size, int keep) -{ - if (f->outsize < size) { - int offset = f->outptr - f->outreal; - if (keep) { - f->outreal = g_realloc(f->outreal, size + PRE_HEAD*4); - } else { - g_free(f->outreal); - f->outreal = g_malloc(size + PRE_HEAD*4); - } - f->outptr = f->outreal + offset; - f->outbuf = f->outreal + PRE_HEAD*4; - f->outsize = size; - /* this could be offset from the end of the structure, but - this should be good enough */ - f->outpre = PRE_HEAD*4; - } -} - diff --git a/camel/camel-mime-filter.h b/camel/camel-mime-filter.h deleted file mode 100644 index 3cd65fe8d1..0000000000 --- a/camel/camel-mime-filter.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* Abstract class for non-copying filters */ - -#ifndef _CAMEL_MIME_FILTER_H -#define _CAMEL_MIME_FILTER_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include - -#define CAMEL_MIME_FILTER_TYPE (camel_mime_filter_get_type ()) -#define CAMEL_MIME_FILTER(obj) CAMEL_CHECK_CAST (obj, camel_mime_filter_get_type (), CamelMimeFilter) -#define CAMEL_MIME_FILTER_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_mime_filter_get_type (), CamelMimeFilterClass) -#define CAMEL_IS_MIME_FILTER(obj) CAMEL_CHECK_TYPE (obj, camel_mime_filter_get_type ()) - -typedef struct _CamelMimeFilterClass CamelMimeFilterClass; - -struct _CamelMimeFilter { - CamelObject parent; - - struct _CamelMimeFilterPrivate *priv; - - char *outreal; /* real malloc'd buffer */ - char *outbuf; /* first 'writable' position allowed (outreal + outpre) */ - char *outptr; - size_t outsize; - size_t outpre; /* prespace of this buffer */ - - char *backbuf; - size_t backsize; - size_t backlen; /* significant data there */ -}; - -struct _CamelMimeFilterClass { - CamelObjectClass parent_class; - - /* virtual functions */ - void (*filter)(CamelMimeFilter *f, - char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace); - void (*complete)(CamelMimeFilter *f, - char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace); - void (*reset)(CamelMimeFilter *f); -}; - -CamelType camel_mime_filter_get_type (void); -CamelMimeFilter *camel_mime_filter_new (void); - -void camel_mime_filter_filter(CamelMimeFilter *f, - char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace); - -void camel_mime_filter_complete(CamelMimeFilter *f, - char *in, size_t len, size_t prespace, - char **out, size_t *outlen, size_t *outprespace); - -void camel_mime_filter_reset(CamelMimeFilter *f); - -/* sets/returns number of bytes backed up on the input */ -void camel_mime_filter_backup(CamelMimeFilter *f, const char *data, size_t length); - -/* ensure this much size available for filter output */ -void camel_mime_filter_set_size(CamelMimeFilter *f, size_t size, int keep); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_MIME_FILTER_H */ diff --git a/camel/camel-mime-message.c b/camel/camel-mime-message.c deleted file mode 100644 index 7f4ac93f4b..0000000000 --- a/camel/camel-mime-message.c +++ /dev/null @@ -1,963 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* camel-mime-message.c : class for a mime_message */ - -/* - * Authors: Bertrand Guiheneuf - * Michael Zucchi - * Jeffrey Stedfast - * - * Copyright 1999-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include - -#include - -#include "camel-mime-message.h" -#include "camel-multipart.h" -#include "camel-stream-mem.h" -#include "camel-string-utils.h" -#include "camel-url.h" - -#include "camel-stream-filter.h" -#include "camel-stream-null.h" -#include "camel-mime-filter-charset.h" -#include "camel-mime-filter-bestenc.h" - -#define d(x) - -/* these 2 below should be kept in sync */ -typedef enum { - HEADER_UNKNOWN, - HEADER_FROM, - HEADER_REPLY_TO, - HEADER_SUBJECT, - HEADER_TO, - HEADER_RESENT_TO, - HEADER_CC, - HEADER_RESENT_CC, - HEADER_BCC, - HEADER_RESENT_BCC, - HEADER_DATE, - HEADER_MESSAGE_ID -} CamelHeaderType; - -static char *header_names[] = { - /* dont include HEADER_UNKNOWN string */ - "From", "Reply-To", "Subject", "To", "Resent-To", "Cc", "Resent-Cc", - "Bcc", "Resent-Bcc", "Date", "Message-Id", NULL -}; - -static GHashTable *header_name_table; - -static CamelMimePartClass *parent_class = NULL; - -static char *recipient_names[] = { - "To", "Cc", "Bcc", "Resent-To", "Resent-Cc", "Resent-Bcc", NULL -}; - -static ssize_t write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream); -static void add_header (CamelMedium *medium, const char *name, const void *value); -static void set_header (CamelMedium *medium, const char *name, const void *value); -static void remove_header (CamelMedium *medium, const char *name); -static int construct_from_parser (CamelMimePart *, CamelMimeParser *); -static void unref_recipient (gpointer key, gpointer value, gpointer user_data); - -/* Returns the class for a CamelMimeMessage */ -#define CMM_CLASS(so) CAMEL_MIME_MESSAGE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CDW_CLASS(so) CAMEL_DATA_WRAPPER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMD_CLASS(so) CAMEL_MEDIUM_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static void -camel_mime_message_class_init (CamelMimeMessageClass *camel_mime_message_class) -{ - CamelDataWrapperClass *camel_data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (camel_mime_message_class); - CamelMimePartClass *camel_mime_part_class = CAMEL_MIME_PART_CLASS (camel_mime_message_class); - CamelMediumClass *camel_medium_class = CAMEL_MEDIUM_CLASS (camel_mime_message_class); - int i; - - parent_class = CAMEL_MIME_PART_CLASS (camel_type_get_global_classfuncs (camel_mime_part_get_type ())); - - header_name_table = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); - for (i = 0;header_names[i]; i++) - g_hash_table_insert (header_name_table, header_names[i], GINT_TO_POINTER(i+1)); - - /* virtual method overload */ - camel_data_wrapper_class->write_to_stream = write_to_stream; - camel_data_wrapper_class->decode_to_stream = write_to_stream; - - camel_medium_class->add_header = add_header; - camel_medium_class->set_header = set_header; - camel_medium_class->remove_header = remove_header; - - camel_mime_part_class->construct_from_parser = construct_from_parser; -} - - -static void -camel_mime_message_init (gpointer object, gpointer klass) -{ - CamelMimeMessage *mime_message = (CamelMimeMessage *)object; - int i; - - mime_message->recipients = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); - for (i=0;recipient_names[i];i++) { - g_hash_table_insert(mime_message->recipients, recipient_names[i], camel_internet_address_new()); - } - - mime_message->subject = NULL; - mime_message->reply_to = NULL; - mime_message->from = NULL; - mime_message->date = CAMEL_MESSAGE_DATE_CURRENT; - mime_message->date_offset = 0; - mime_message->date_received = CAMEL_MESSAGE_DATE_CURRENT; - mime_message->date_received_offset = 0; - mime_message->message_id = NULL; -} - -static void -camel_mime_message_finalize (CamelObject *object) -{ - CamelMimeMessage *message = CAMEL_MIME_MESSAGE (object); - - g_free (message->subject); - - g_free (message->message_id); - - if (message->reply_to) - camel_object_unref ((CamelObject *)message->reply_to); - - if (message->from) - camel_object_unref ((CamelObject *)message->from); - - g_hash_table_foreach (message->recipients, unref_recipient, NULL); - g_hash_table_destroy (message->recipients); -} - - -CamelType -camel_mime_message_get_type (void) -{ - static CamelType camel_mime_message_type = CAMEL_INVALID_TYPE; - - if (camel_mime_message_type == CAMEL_INVALID_TYPE) { - camel_mime_message_type = camel_type_register (camel_mime_part_get_type(), "CamelMimeMessage", - sizeof (CamelMimeMessage), - sizeof (CamelMimeMessageClass), - (CamelObjectClassInitFunc) camel_mime_message_class_init, - NULL, - (CamelObjectInitFunc) camel_mime_message_init, - (CamelObjectFinalizeFunc) camel_mime_message_finalize); - } - - return camel_mime_message_type; -} - -static void -unref_recipient (gpointer key, gpointer value, gpointer user_data) -{ - camel_object_unref (value); -} - -CamelMimeMessage * -camel_mime_message_new (void) -{ - CamelMimeMessage *mime_message; - mime_message = CAMEL_MIME_MESSAGE (camel_object_new (CAMEL_MIME_MESSAGE_TYPE)); - - return mime_message; -} - -/* **** Date: */ - -void -camel_mime_message_set_date (CamelMimeMessage *message, time_t date, int offset) -{ - char *datestr; - - g_assert(message); - - if (date == CAMEL_MESSAGE_DATE_CURRENT) { - struct tm local; - int tz; - - date = time(0); - e_localtime_with_offset(date, &local, &tz); - offset = (((tz/60/60) * 100) + (tz/60 % 60)); - } - message->date = date; - message->date_offset = offset; - - datestr = camel_header_format_date (date, offset); - CAMEL_MEDIUM_CLASS (parent_class)->set_header ((CamelMedium *)message, "Date", datestr); - g_free (datestr); -} - -time_t -camel_mime_message_get_date (CamelMimeMessage *msg, int *offset) -{ - if (offset) - *offset = msg->date_offset; - - return msg->date; -} - -time_t -camel_mime_message_get_date_received (CamelMimeMessage *msg, int *offset) -{ - if (msg->date_received == CAMEL_MESSAGE_DATE_CURRENT) { - const char *received; - - received = camel_medium_get_header ((CamelMedium *)msg, "received"); - if (received) - received = strrchr (received, ';'); - if (received) - msg->date_received = camel_header_decode_date (received + 1, &msg->date_received_offset); - } - - if (offset) - *offset = msg->date_received_offset; - - return msg->date_received; -} - -/* **** Message-Id: */ - -void -camel_mime_message_set_message_id (CamelMimeMessage *mime_message, const char *message_id) -{ - char *id; - - g_assert (mime_message); - - g_free (mime_message->message_id); - - if (message_id) { - id = g_strstrip (g_strdup (message_id)); - } else { - id = camel_header_msgid_generate (); - } - - mime_message->message_id = id; - id = g_strdup_printf ("<%s>", mime_message->message_id); - CAMEL_MEDIUM_CLASS (parent_class)->set_header (CAMEL_MEDIUM (mime_message), "Message-Id", id); - g_free (id); -} - -const char * -camel_mime_message_get_message_id (CamelMimeMessage *mime_message) -{ - g_assert (mime_message); - - return mime_message->message_id; -} - -/* **** Reply-To: */ - -void -camel_mime_message_set_reply_to (CamelMimeMessage *msg, const CamelInternetAddress *reply_to) -{ - char *addr; - - g_assert(msg); - - if (msg->reply_to) { - camel_object_unref ((CamelObject *)msg->reply_to); - msg->reply_to = NULL; - } - - if (reply_to == NULL) { - CAMEL_MEDIUM_CLASS (parent_class)->remove_header (CAMEL_MEDIUM (msg), "Reply-To"); - return; - } - - msg->reply_to = (CamelInternetAddress *)camel_address_new_clone ((CamelAddress *)reply_to); - addr = camel_address_encode ((CamelAddress *)msg->reply_to); - CAMEL_MEDIUM_CLASS (parent_class)->set_header (CAMEL_MEDIUM (msg), "Reply-To", addr); - g_free (addr); -} - -const CamelInternetAddress * -camel_mime_message_get_reply_to (CamelMimeMessage *mime_message) -{ - g_assert (mime_message); - - /* TODO: ref for threading? */ - - return mime_message->reply_to; -} - -/* **** Subject: */ - -void -camel_mime_message_set_subject (CamelMimeMessage *mime_message, const char *subject) -{ - char *text; - - g_assert(mime_message); - - g_free (mime_message->subject); - mime_message->subject = g_strstrip (g_strdup (subject)); - text = camel_header_encode_string((unsigned char *)mime_message->subject); - CAMEL_MEDIUM_CLASS(parent_class)->set_header(CAMEL_MEDIUM (mime_message), "Subject", text); - g_free (text); -} - -const char * -camel_mime_message_get_subject (CamelMimeMessage *mime_message) -{ - g_assert(mime_message); - - return mime_message->subject; -} - -/* *** From: */ - -/* Thought: Since get_from/set_from are so rarely called, it is probably not useful - to cache the from (and reply_to) addresses as InternetAddresses internally, we - could just get it from the headers and reprocess every time. */ -void -camel_mime_message_set_from (CamelMimeMessage *msg, const CamelInternetAddress *from) -{ - char *addr; - - g_assert(msg); - - if (msg->from) { - camel_object_unref((CamelObject *)msg->from); - msg->from = NULL; - } - - if (from == NULL || camel_address_length((CamelAddress *)from) == 0) { - CAMEL_MEDIUM_CLASS(parent_class)->remove_header(CAMEL_MEDIUM(msg), "From"); - return; - } - - msg->from = (CamelInternetAddress *)camel_address_new_clone((CamelAddress *)from); - addr = camel_address_encode((CamelAddress *)msg->from); - CAMEL_MEDIUM_CLASS (parent_class)->set_header(CAMEL_MEDIUM(msg), "From", addr); - g_free(addr); -} - -const CamelInternetAddress * -camel_mime_message_get_from (CamelMimeMessage *mime_message) -{ - g_assert (mime_message); - - /* TODO: we should really ref this for multi-threading to work */ - - return mime_message->from; -} - -/* **** To: Cc: Bcc: */ - -void -camel_mime_message_set_recipients(CamelMimeMessage *mime_message, const char *type, const CamelInternetAddress *r) -{ - char *text; - CamelInternetAddress *addr; - - g_assert(mime_message); - - addr = g_hash_table_lookup (mime_message->recipients, type); - if (addr == NULL) { - g_warning ("trying to set a non-valid receipient type: %s", type); - return; - } - - if (r == NULL || camel_address_length ((CamelAddress *)r) == 0) { - camel_address_remove ((CamelAddress *)addr, -1); - CAMEL_MEDIUM_CLASS (parent_class)->remove_header (CAMEL_MEDIUM (mime_message), type); - return; - } - - /* note this does copy, and not append (cat) */ - camel_address_copy ((CamelAddress *)addr, (const CamelAddress *)r); - - /* and sync our headers */ - text = camel_address_encode (CAMEL_ADDRESS (addr)); - CAMEL_MEDIUM_CLASS (parent_class)->set_header (CAMEL_MEDIUM (mime_message), type, text); - g_free(text); -} - -void -camel_mime_message_set_source (CamelMimeMessage *mime_message, const char *src) -{ - CamelURL *url; - char *uri; - - g_assert (mime_message); - - url = camel_url_new (src, NULL); - if (url) { - uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_medium_add_header (CAMEL_MEDIUM (mime_message), "X-Evolution-Source", uri); - g_free (uri); - camel_url_free (url); - } -} - -const char * -camel_mime_message_get_source (CamelMimeMessage *mime_message) -{ - const char *src; - - g_assert(mime_message); - - src = camel_medium_get_header (CAMEL_MEDIUM (mime_message), "X-Evolution-Source"); - if (src) { - while (*src && isspace ((unsigned) *src)) - ++src; - } - return src; -} - -const CamelInternetAddress * -camel_mime_message_get_recipients (CamelMimeMessage *mime_message, const char *type) -{ - g_assert(mime_message); - - return g_hash_table_lookup (mime_message->recipients, type); -} - -/* mime_message */ -static int -construct_from_parser (CamelMimePart *dw, CamelMimeParser *mp) -{ - char *buf; - size_t len; - int state; - int ret; - int err; - - d(printf("constructing mime-message\n")); - - d(printf("mime_message::construct_from_parser()\n")); - - /* let the mime-part construct the guts ... */ - ret = ((CamelMimePartClass *)parent_class)->construct_from_parser(dw, mp); - - if (ret == -1) - return -1; - - /* ... then clean up the follow-on state */ - state = camel_mime_parser_step (mp, &buf, &len); - switch (state) { - case CAMEL_MIME_PARSER_STATE_EOF: case CAMEL_MIME_PARSER_STATE_FROM_END: /* these doesn't belong to us */ - camel_mime_parser_unstep (mp); - case CAMEL_MIME_PARSER_STATE_MESSAGE_END: - break; - default: - g_error ("Bad parser state: Expecing MESSAGE_END or EOF or EOM, got: %d", camel_mime_parser_state (mp)); - camel_mime_parser_unstep (mp); - return -1; - } - - d(printf("mime_message::construct_from_parser() leaving\n")); - err = camel_mime_parser_errno(mp); - if (err != 0) { - errno = err; - ret = -1; - } - - return ret; -} - -static ssize_t -write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) -{ - CamelMimeMessage *mm = CAMEL_MIME_MESSAGE (data_wrapper); - - /* force mandatory headers ... */ - if (mm->from == NULL) { - /* FIXME: should we just abort? Should we make one up? */ - g_warning ("No from set for message"); - camel_medium_set_header ((CamelMedium *)mm, "From", ""); - } - if (!camel_medium_get_header ((CamelMedium *)mm, "Date")) - camel_mime_message_set_date (mm, CAMEL_MESSAGE_DATE_CURRENT, 0); - - if (mm->subject == NULL) - camel_mime_message_set_subject (mm, "No Subject"); - - if (mm->message_id == NULL) - camel_mime_message_set_message_id (mm, NULL); - - /* FIXME: "To" header needs to be set explicitly as well ... */ - - if (!camel_medium_get_header ((CamelMedium *)mm, "Mime-Version")) - camel_medium_set_header ((CamelMedium *)mm, "Mime-Version", "1.0"); - - return CAMEL_DATA_WRAPPER_CLASS (parent_class)->write_to_stream (data_wrapper, stream); -} - -/* FIXME: check format of fields. */ -static gboolean -process_header (CamelMedium *medium, const char *name, const char *value) -{ - CamelHeaderType header_type; - CamelMimeMessage *message = CAMEL_MIME_MESSAGE (medium); - CamelInternetAddress *addr; - const char *charset; - - header_type = (CamelHeaderType) g_hash_table_lookup (header_name_table, name); - switch (header_type) { - case HEADER_FROM: - if (message->from) - camel_object_unref (message->from); - message->from = camel_internet_address_new (); - camel_address_decode (CAMEL_ADDRESS (message->from), value); - break; - case HEADER_REPLY_TO: - if (message->reply_to) - camel_object_unref (message->reply_to); - message->reply_to = camel_internet_address_new (); - camel_address_decode (CAMEL_ADDRESS (message->reply_to), value); - break; - case HEADER_SUBJECT: - g_free (message->subject); - if (((CamelDataWrapper *) message)->mime_type) { - charset = camel_content_type_param (((CamelDataWrapper *) message)->mime_type, "charset"); - charset = e_iconv_charset_name (charset); - } else - charset = NULL; - message->subject = g_strstrip (camel_header_decode_string (value, charset)); - break; - case HEADER_TO: - case HEADER_CC: - case HEADER_BCC: - case HEADER_RESENT_TO: - case HEADER_RESENT_CC: - case HEADER_RESENT_BCC: - addr = g_hash_table_lookup (message->recipients, name); - if (value) - camel_address_decode (CAMEL_ADDRESS (addr), value); - else - camel_address_remove (CAMEL_ADDRESS (addr), -1); - break; - case HEADER_DATE: - if (value) { - message->date = camel_header_decode_date (value, &message->date_offset); - } else { - message->date = CAMEL_MESSAGE_DATE_CURRENT; - message->date_offset = 0; - } - break; - case HEADER_MESSAGE_ID: - g_free (message->message_id); - if (value) - message->message_id = camel_header_msgid_decode (value); - else - message->message_id = NULL; - break; - default: - return FALSE; - } - - return TRUE; -} - -static void -set_header (CamelMedium *medium, const char *name, const void *value) -{ - process_header (medium, name, value); - parent_class->parent_class.set_header (medium, name, value); -} - -static void -add_header (CamelMedium *medium, const char *name, const void *value) -{ - /* if we process it, then it must be forced unique as well ... */ - if (process_header (medium, name, value)) - parent_class->parent_class.set_header (medium, name, value); - else - parent_class->parent_class.add_header (medium, name, value); -} - -static void -remove_header (CamelMedium *medium, const char *name) -{ - process_header (medium, name, NULL); - parent_class->parent_class.remove_header (medium, name); -} - -typedef gboolean (*CamelPartFunc)(CamelMimeMessage *, CamelMimePart *, void *data); - -static gboolean -message_foreach_part_rec (CamelMimeMessage *msg, CamelMimePart *part, CamelPartFunc callback, void *data) -{ - CamelDataWrapper *containee; - int parts, i; - int go = TRUE; - - if (callback (msg, part, data) == FALSE) - return FALSE; - - containee = camel_medium_get_content_object (CAMEL_MEDIUM (part)); - - if (containee == NULL) - return go; - - /* using the object types is more accurate than using the mime/types */ - if (CAMEL_IS_MULTIPART (containee)) { - parts = camel_multipart_get_number (CAMEL_MULTIPART (containee)); - for (i = 0; go && i < parts; i++) { - CamelMimePart *part = camel_multipart_get_part (CAMEL_MULTIPART (containee), i); - - go = message_foreach_part_rec (msg, part, callback, data); - } - } else if (CAMEL_IS_MIME_MESSAGE (containee)) { - go = message_foreach_part_rec (msg, (CamelMimePart *)containee, callback, data); - } - - return go; -} - -/* dont make this public yet, it might need some more thinking ... */ -/* MPZ */ -static void -camel_mime_message_foreach_part (CamelMimeMessage *msg, CamelPartFunc callback, void *data) -{ - message_foreach_part_rec (msg, (CamelMimePart *)msg, callback, data); -} - -static gboolean -check_8bit (CamelMimeMessage *msg, CamelMimePart *part, void *data) -{ - CamelTransferEncoding encoding; - int *has8bit = data; - - /* check this part, and stop as soon as we are done */ - encoding = camel_mime_part_get_encoding (part); - - *has8bit = encoding == CAMEL_TRANSFER_ENCODING_8BIT || encoding == CAMEL_TRANSFER_ENCODING_BINARY; - - return !(*has8bit); -} - -gboolean -camel_mime_message_has_8bit_parts (CamelMimeMessage *msg) -{ - int has8bit = FALSE; - - camel_mime_message_foreach_part (msg, check_8bit, &has8bit); - - return has8bit; -} - -/* finds the best charset and transfer encoding for a given part */ -static CamelTransferEncoding -find_best_encoding (CamelMimePart *part, CamelBestencRequired required, CamelBestencEncoding enctype, char **charsetp) -{ - CamelMimeFilterCharset *charenc = NULL; - CamelTransferEncoding encoding; - CamelMimeFilterBestenc *bestenc; - unsigned int flags, callerflags; - CamelDataWrapper *content; - CamelStreamFilter *filter; - const char *charsetin = NULL; - char *charset = NULL; - CamelStream *null; - int idb, idc = -1; - gboolean istext; - - /* we use all these weird stream things so we can do it with streams, and - not have to read the whole lot into memory - although i have a feeling - it would make things a fair bit simpler to do so ... */ - - d(printf("starting to check part\n")); - - content = camel_medium_get_content_object ((CamelMedium *)part); - if (content == NULL) { - /* charset might not be right here, but it'll get the right stuff - if it is ever set */ - *charsetp = NULL; - return CAMEL_TRANSFER_ENCODING_DEFAULT; - } - - istext = camel_content_type_is (((CamelDataWrapper *) part)->mime_type, "text", "*"); - if (istext) { - flags = CAMEL_BESTENC_GET_CHARSET | CAMEL_BESTENC_GET_ENCODING; - enctype |= CAMEL_BESTENC_TEXT; - } else { - flags = CAMEL_BESTENC_GET_ENCODING; - } - - /* when building the message, any encoded parts are translated already */ - flags |= CAMEL_BESTENC_LF_IS_CRLF; - /* and get any flags the caller passed in */ - callerflags = (required & CAMEL_BESTENC_NO_FROM); - flags |= callerflags; - - /* first a null stream, so any filtering is thrown away; we only want the sideeffects */ - null = (CamelStream *)camel_stream_null_new (); - filter = camel_stream_filter_new_with_stream (null); - - /* if we're looking for the best charset, then we need to convert to UTF-8 */ - if (istext && (required & CAMEL_BESTENC_GET_CHARSET) != 0 - && (charsetin = camel_content_type_param (content->mime_type, "charset"))) { - charenc = camel_mime_filter_charset_new_convert (charsetin, "UTF-8"); - if (charenc != NULL) - idc = camel_stream_filter_add (filter, (CamelMimeFilter *)charenc); - charsetin = NULL; - } - - bestenc = camel_mime_filter_bestenc_new (flags); - idb = camel_stream_filter_add (filter, (CamelMimeFilter *)bestenc); - d(printf("writing to checking stream\n")); - camel_data_wrapper_decode_to_stream (content, (CamelStream *)filter); - camel_stream_filter_remove (filter, idb); - if (idc != -1) { - camel_stream_filter_remove (filter, idc); - camel_object_unref (charenc); - charenc = NULL; - } - - if (istext && (required & CAMEL_BESTENC_GET_CHARSET) != 0) { - charsetin = camel_mime_filter_bestenc_get_best_charset (bestenc); - d(printf("best charset = %s\n", charsetin ? charsetin : "(null)")); - charset = g_strdup (charsetin); - - charsetin = camel_content_type_param (content->mime_type, "charset"); - } else { - charset = NULL; - } - - /* if we have US-ASCII, or we're not doing text, we dont need to bother with the rest */ - if (istext && charsetin && charset && (required & CAMEL_BESTENC_GET_CHARSET) != 0) { - d(printf("have charset, trying conversion/etc\n")); - - /* now that 'bestenc' has told us what the best encoding is, we can use that to create - a charset conversion filter as well, and then re-add the bestenc to filter the - result to find the best encoding to use as well */ - - charenc = camel_mime_filter_charset_new_convert (charsetin, charset); - if (charenc != NULL) { - /* otherwise, try another pass, converting to the real charset */ - - camel_mime_filter_reset ((CamelMimeFilter *)bestenc); - camel_mime_filter_bestenc_set_flags (bestenc, CAMEL_BESTENC_GET_ENCODING | - CAMEL_BESTENC_LF_IS_CRLF | callerflags); - - camel_stream_filter_add (filter, (CamelMimeFilter *)charenc); - camel_stream_filter_add (filter, (CamelMimeFilter *)bestenc); - - /* and write it to the new stream */ - camel_data_wrapper_write_to_stream (content, (CamelStream *)filter); - - camel_object_unref (charenc); - } - } - - encoding = camel_mime_filter_bestenc_get_best_encoding (bestenc, enctype); - - camel_object_unref (filter); - camel_object_unref (bestenc); - camel_object_unref (null); - - d(printf("done, best encoding = %d\n", encoding)); - - if (charsetp) - *charsetp = charset; - else - g_free (charset); - - return encoding; -} - -struct _enc_data { - CamelBestencRequired required; - CamelBestencEncoding enctype; -}; - -static gboolean -best_encoding (CamelMimeMessage *msg, CamelMimePart *part, void *datap) -{ - struct _enc_data *data = datap; - CamelTransferEncoding encoding; - CamelDataWrapper *wrapper; - char *charset; - - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part)); - if (!wrapper) - return FALSE; - - /* we only care about actual content objects */ - if (!CAMEL_IS_MULTIPART (wrapper) && !CAMEL_IS_MIME_MESSAGE (wrapper)) { - encoding = find_best_encoding (part, data->required, data->enctype, &charset); - /* we always set the encoding, if we got this far. GET_CHARSET implies - also GET_ENCODING */ - camel_mime_part_set_encoding (part, encoding); - - if ((data->required & CAMEL_BESTENC_GET_CHARSET) != 0) { - if (camel_content_type_is (((CamelDataWrapper *) part)->mime_type, "text", "*")) { - char *newct; - - /* FIXME: ick, the part content_type interface needs fixing bigtime */ - camel_content_type_set_param (((CamelDataWrapper *) part)->mime_type, "charset", - charset ? charset : "us-ascii"); - newct = camel_content_type_format (((CamelDataWrapper *) part)->mime_type); - if (newct) { - d(printf("Setting content-type to %s\n", newct)); - - camel_mime_part_set_content_type (part, newct); - g_free (newct); - } - } - } - - g_free (charset); - } - - return TRUE; -} - -void -camel_mime_message_set_best_encoding (CamelMimeMessage *msg, CamelBestencRequired required, CamelBestencEncoding enctype) -{ - struct _enc_data data; - - if ((required & (CAMEL_BESTENC_GET_ENCODING|CAMEL_BESTENC_GET_CHARSET)) == 0) - return; - - data.required = required; - data.enctype = enctype; - - camel_mime_message_foreach_part (msg, best_encoding, &data); -} - -void -camel_mime_message_encode_8bit_parts (CamelMimeMessage *mime_message) -{ - camel_mime_message_set_best_encoding (mime_message, CAMEL_BESTENC_GET_ENCODING, CAMEL_BESTENC_7BIT); -} - - -struct _check_content_id { - CamelMimePart *part; - const char *content_id; -}; - -static gboolean -check_content_id (CamelMimeMessage *message, CamelMimePart *part, void *data) -{ - struct _check_content_id *check = (struct _check_content_id *) data; - const char *content_id; - gboolean found; - - content_id = camel_mime_part_get_content_id (part); - - found = content_id && !strcmp (content_id, check->content_id) ? TRUE : FALSE; - if (found) { - check->part = part; - camel_object_ref (part); - } - - return !found; -} - -CamelMimePart * -camel_mime_message_get_part_by_content_id (CamelMimeMessage *message, const char *id) -{ - struct _check_content_id check; - - g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL); - - if (id == NULL) - return NULL; - - check.content_id = id; - check.part = NULL; - - camel_mime_message_foreach_part (message, check_content_id, &check); - - return check.part; -} - -static char *tz_months[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static char *tz_days[] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - -char * -camel_mime_message_build_mbox_from (CamelMimeMessage *message) -{ - struct _camel_header_raw *header = ((CamelMimePart *)message)->headers; - GString *out = g_string_new("From "); - char *ret; - const char *tmp; - time_t thetime; - int offset; - struct tm tm; - - tmp = camel_header_raw_find (&header, "Sender", NULL); - if (tmp == NULL) - tmp = camel_header_raw_find (&header, "From", NULL); - if (tmp != NULL) { - struct _camel_header_address *addr = camel_header_address_decode (tmp, NULL); - - tmp = NULL; - if (addr) { - if (addr->type == HEADER_ADDRESS_NAME) { - g_string_append (out, addr->v.addr); - tmp = ""; - } - camel_header_address_unref (addr); - } - } - - if (tmp == NULL) - g_string_append (out, "unknown@nodomain.now.au"); - - /* try use the received header to get the date */ - tmp = camel_header_raw_find (&header, "Received", NULL); - if (tmp) { - tmp = strrchr(tmp, ';'); - if (tmp) - tmp++; - } - - /* if there isn't one, try the Date field */ - if (tmp == NULL) - tmp = camel_header_raw_find (&header, "Date", NULL); - - thetime = camel_header_decode_date (tmp, &offset); - thetime += ((offset / 100) * (60 * 60)) + (offset % 100) * 60; - gmtime_r (&thetime, &tm); - g_string_append_printf (out, " %s %s %2d %02d:%02d:%02d %4d\n", - tz_days[tm.tm_wday], tz_months[tm.tm_mon], - tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, - tm.tm_year + 1900); - - ret = out->str; - g_string_free (out, FALSE); - - return ret; -} diff --git a/camel/camel-mime-message.h b/camel/camel-mime-message.h deleted file mode 100644 index c1149d5ef5..0000000000 --- a/camel/camel-mime-message.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* camelMimeMessage.h : class for a mime message - * - * Authors: Bertrand Guiheneuf - * Michael Zucchi - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_MIME_MESSAGE_H -#define CAMEL_MIME_MESSAGE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include -#include -#include - -#define CAMEL_RECIPIENT_TYPE_TO "To" -#define CAMEL_RECIPIENT_TYPE_CC "Cc" -#define CAMEL_RECIPIENT_TYPE_BCC "Bcc" - -#define CAMEL_RECIPIENT_TYPE_RESENT_TO "Resent-To" -#define CAMEL_RECIPIENT_TYPE_RESENT_CC "Resent-Cc" -#define CAMEL_RECIPIENT_TYPE_RESENT_BCC "Resent-Bcc" - -#define CAMEL_MIME_MESSAGE_TYPE (camel_mime_message_get_type ()) -#define CAMEL_MIME_MESSAGE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MIME_MESSAGE_TYPE, CamelMimeMessage)) -#define CAMEL_MIME_MESSAGE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MIME_MESSAGE_TYPE, CamelMimeMessageClass)) -#define CAMEL_IS_MIME_MESSAGE(o) (CAMEL_CHECK_TYPE((o), CAMEL_MIME_MESSAGE_TYPE)) - - -/* specify local time */ -#define CAMEL_MESSAGE_DATE_CURRENT (~0) - -struct _CamelMimeMessage -{ - CamelMimePart parent_object; - - /* header fields */ - time_t date; - int date_offset; /* GMT offset */ - - /* cached internal copy */ - time_t date_received; - int date_received_offset; /* GMT offset */ - - char *subject; - - char *message_id; - - CamelInternetAddress *reply_to; - CamelInternetAddress *from; - - GHashTable *recipients; /* hash table of CamelInternetAddress's */ -}; - -typedef struct { - CamelMimePartClass parent_class; - - /* Virtual methods */ - -} CamelMimeMessageClass; - - - -/* Standard Camel function */ -CamelType camel_mime_message_get_type (void); - - -/* public methods */ -CamelMimeMessage *camel_mime_message_new (void); -void camel_mime_message_set_date (CamelMimeMessage *mime_message, - time_t date, - int offset); -time_t camel_mime_message_get_date (CamelMimeMessage *mime_message, - int *offset); -time_t camel_mime_message_get_date_received (CamelMimeMessage *mime_message, - int *offset); -void camel_mime_message_set_message_id (CamelMimeMessage *mime_message, - const char *message_id); -const char *camel_mime_message_get_message_id (CamelMimeMessage *mime_message); -void camel_mime_message_set_reply_to (CamelMimeMessage *mime_message, - const CamelInternetAddress *reply_to); -const CamelInternetAddress *camel_mime_message_get_reply_to (CamelMimeMessage *mime_message); - -void camel_mime_message_set_subject (CamelMimeMessage *mime_message, - const char *subject); -const char *camel_mime_message_get_subject (CamelMimeMessage *mime_message); -void camel_mime_message_set_from (CamelMimeMessage *mime_message, - const CamelInternetAddress *from); -const CamelInternetAddress *camel_mime_message_get_from (CamelMimeMessage *mime_message); - -const CamelInternetAddress *camel_mime_message_get_recipients (CamelMimeMessage *mime_message, - const char *type); -void camel_mime_message_set_recipients (CamelMimeMessage *mime_message, - const char *type, - const CamelInternetAddress *r); - -void camel_mime_message_set_source (CamelMimeMessage *mime_message, - const char *identity); -const char *camel_mime_message_get_source (CamelMimeMessage *mime_message); - - -/* utility functions */ -gboolean camel_mime_message_has_8bit_parts (CamelMimeMessage *mime_message); -void camel_mime_message_set_best_encoding (CamelMimeMessage *msg, - CamelBestencRequired required, - CamelBestencEncoding enctype); -void camel_mime_message_encode_8bit_parts (CamelMimeMessage *mime_message); - -CamelMimePart *camel_mime_message_get_part_by_content_id (CamelMimeMessage *message, const char *content_id); - -char *camel_mime_message_build_mbox_from (CamelMimeMessage *mime_message); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_MIME_MESSAGE_H */ diff --git a/camel/camel-mime-parser.c b/camel/camel-mime-parser.c deleted file mode 100644 index d3954c069c..0000000000 --- a/camel/camel-mime-parser.c +++ /dev/null @@ -1,1982 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000-2003 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* What should hopefully be a fast mail parser */ - -/* Do not change this code without asking me (Michael Zucchi) first - - There is almost always a reason something was done a certain way. - */ - -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -#include -#include "camel-mime-parser.h" -#include "camel-mime-utils.h" -#include "camel-mime-filter.h" -#include "camel-stream.h" -#include "camel-seekable-stream.h" - -#define r(x) -#define h(x) -#define c(x) -#define d(x) - -/*#define PRESERVE_HEADERS*/ - -/*#define PURIFY*/ - -#define MEMPOOL - -#define STRUCT_ALIGN 4 - -#ifdef PURIFY -int inend_id = -1, - inbuffer_id = -1; -#endif - -#define SCAN_BUF 4096 /* size of read buffer */ -#define SCAN_HEAD 128 /* headroom guaranteed to be before each read buffer */ - -/* a little hacky, but i couldn't be bothered renaming everything */ -#define _header_scan_state _CamelMimeParserPrivate -#define _PRIVATE(o) (((CamelMimeParser *)(o))->priv) - -#ifdef MEMPOOL -typedef struct _MemPoolNode { - struct _MemPoolNode *next; - - int free; - char data[1]; -} MemPoolNode; - -typedef struct _MemPoolThresholdNode { - struct _MemPoolThresholdNode *next; - char data[1]; -} MemPoolThresholdNode; - -typedef struct _MemPool { - int blocksize; - int threshold; - struct _MemPoolNode *blocks; - struct _MemPoolThresholdNode *threshold_blocks; -} MemPool; - -MemPool *mempool_new(int blocksize, int threshold); -void *mempool_alloc(MemPool *pool, int size); -void mempool_flush(MemPool *pool, int freeall); -void mempool_free(MemPool *pool); - -MemPool *mempool_new(int blocksize, int threshold) -{ - MemPool *pool; - - pool = g_malloc(sizeof(*pool)); - if (threshold >= blocksize) - threshold = blocksize * 2 / 3; - pool->blocksize = blocksize; - pool->threshold = threshold; - pool->blocks = NULL; - pool->threshold_blocks = NULL; - return pool; -} - -void *mempool_alloc(MemPool *pool, int size) -{ - size = (size + STRUCT_ALIGN) & (~(STRUCT_ALIGN-1)); - if (size>=pool->threshold) { - MemPoolThresholdNode *n; - - n = g_malloc(sizeof(*n) - sizeof(char) + size); - n->next = pool->threshold_blocks; - pool->threshold_blocks = n; - return &n->data[0]; - } else { - MemPoolNode *n; - - n = pool->blocks; - while (n) { - if (n->free >= size) { - n->free -= size; - return &n->data[n->free]; - } - n = n->next; - } - - n = g_malloc(sizeof(*n) - sizeof(char) + pool->blocksize); - n->next = pool->blocks; - pool->blocks = n; - n->free = pool->blocksize - size; - return &n->data[n->free]; - } -} - -void mempool_flush(MemPool *pool, int freeall) -{ - MemPoolThresholdNode *tn, *tw; - MemPoolNode *pw, *pn; - - tw = pool->threshold_blocks; - while (tw) { - tn = tw->next; - g_free(tw); - tw = tn; - } - pool->threshold_blocks = NULL; - - if (freeall) { - pw = pool->blocks; - while (pw) { - pn = pw->next; - g_free(pw); - pw = pn; - } - pool->blocks = NULL; - } else { - pw = pool->blocks; - while (pw) { - pw->free = pool->blocksize; - pw = pw->next; - } - } -} - -void mempool_free(MemPool *pool) -{ - if (pool) { - mempool_flush(pool, 1); - g_free(pool); - } -} - -#endif - -struct _header_scan_state { - - /* global state */ - - enum _camel_mime_parser_state state; - - /* for building headers during scanning */ - char *outbuf; - char *outptr; - char *outend; - - int fd; /* input for a fd input */ - CamelStream *stream; /* or for a stream */ - - int ioerrno; /* io error state */ - - /* for scanning input buffers */ - char *realbuf; /* the real buffer, SCAN_HEAD*2 + SCAN_BUF bytes */ - char *inbuf; /* points to a subset of the allocated memory, the underflow */ - char *inptr; /* (upto SCAN_HEAD) is for use by filters so they dont copy all data */ - char *inend; - - int atleast; - - off_t seek; /* current offset to start of buffer */ - int unstep; /* how many states to 'unstep' (repeat the current state) */ - - unsigned int midline:1; /* are we mid-line interrupted? */ - unsigned int scan_from:1; /* do we care about From lines? */ - unsigned int scan_pre_from:1; /* do we return pre-from data? */ - unsigned int eof:1; /* reached eof? */ - - off_t start_of_from; /* where from started */ - off_t start_of_headers; /* where headers started from the last scan */ - - off_t header_start; /* start of last header, or -1 */ - - /* filters to apply to all content before output */ - int filterid; /* id of next filter */ - struct _header_scan_filter *filters; - - /* per message/part info */ - struct _header_scan_stack *parts; - -}; - -struct _header_scan_stack { - struct _header_scan_stack *parent; - - enum _camel_mime_parser_state savestate; /* state at invocation of this part */ - -#ifdef MEMPOOL - MemPool *pool; /* memory pool to keep track of headers/etc at this level */ -#endif - struct _camel_header_raw *headers; /* headers for this part */ - - CamelContentType *content_type; - - /* I dont use GString's casue you can't efficiently append a buffer to them */ - GByteArray *pretext; /* for multipart types, save the pre-boundary data here */ - GByteArray *posttext; /* for multipart types, save the post-boundary data here */ - int prestage; /* used to determine if it is a pre-boundary or post-boundary data segment */ - - GByteArray *from_line; /* the from line */ - - char *boundary; /* for multipart/ * boundaries, including leading -- and trailing -- for the final part */ - int boundarylen; /* actual length of boundary, including leading -- if there is one */ - int boundarylenfinal; /* length of boundary, including trailing -- if there is one */ - int atleast; /* the biggest boundary from here to the parent */ -}; - -struct _header_scan_filter { - struct _header_scan_filter *next; - int id; - CamelMimeFilter *filter; -}; - -static void folder_scan_step(struct _header_scan_state *s, char **databuffer, size_t *datalength); -static void folder_scan_drop_step(struct _header_scan_state *s); -static int folder_scan_init_with_fd(struct _header_scan_state *s, int fd); -static int folder_scan_init_with_stream(struct _header_scan_state *s, CamelStream *stream); -static struct _header_scan_state *folder_scan_init(void); -static void folder_scan_close(struct _header_scan_state *s); -static struct _header_scan_stack *folder_scan_content(struct _header_scan_state *s, int *lastone, char **data, size_t *length); -static struct _header_scan_stack *folder_scan_header(struct _header_scan_state *s, int *lastone); -static int folder_scan_skip_line(struct _header_scan_state *s, GByteArray *save); -static off_t folder_seek(struct _header_scan_state *s, off_t offset, int whence); -static off_t folder_tell(struct _header_scan_state *s); -static int folder_read(struct _header_scan_state *s); -#ifdef MEMPOOL -static void header_append_mempool(struct _header_scan_state *s, struct _header_scan_stack *h, char *header, int offset); -#endif - -static void camel_mime_parser_class_init (CamelMimeParserClass *klass); -static void camel_mime_parser_init (CamelMimeParser *obj); - -#if d(!)0 -static char *states[] = { - "CAMEL_MIME_PARSER_STATE_INITIAL", - "CAMEL_MIME_PARSER_STATE_PRE_FROM", /* pre-from data */ - "CAMEL_MIME_PARSER_STATE_FROM", /* got 'From' line */ - "CAMEL_MIME_PARSER_STATE_HEADER", /* toplevel header */ - "CAMEL_MIME_PARSER_STATE_BODY", /* scanning body of message */ - "CAMEL_MIME_PARSER_STATE_MULTIPART", /* got multipart header */ - "CAMEL_MIME_PARSER_STATE_MESSAGE", /* rfc822/news message */ - - "CAMEL_MIME_PARSER_STATE_PART", /* part of a multipart */ - - "CAMEL_MIME_PARSER_STATE_EOF", /* end of file */ - "CAMEL_MIME_PARSER_STATE_PRE_FROM_END", - "CAMEL_MIME_PARSER_STATE_FROM_END", - "CAMEL_MIME_PARSER_STATE_HEAER_END", - "CAMEL_MIME_PARSER_STATE_BODY_END", - "CAMEL_MIME_PARSER_STATE_MULTIPART_END", - "CAMEL_MIME_PARSER_STATE_MESSAGE_END", -}; -#endif - -static CamelObjectClass *camel_mime_parser_parent; - -static void -camel_mime_parser_class_init (CamelMimeParserClass *klass) -{ - camel_mime_parser_parent = camel_type_get_global_classfuncs (camel_object_get_type ()); -} - -static void -camel_mime_parser_init (CamelMimeParser *obj) -{ - struct _header_scan_state *s; - - s = folder_scan_init(); - _PRIVATE(obj) = s; -} - -static void -camel_mime_parser_finalise(CamelObject *o) -{ - struct _header_scan_state *s = _PRIVATE(o); -#ifdef PURIFY - purify_watch_remove_all(); -#endif - folder_scan_close(s); -} - -CamelType -camel_mime_parser_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_object_get_type (), "CamelMimeParser", - sizeof (CamelMimeParser), - sizeof (CamelMimeParserClass), - (CamelObjectClassInitFunc) camel_mime_parser_class_init, - NULL, - (CamelObjectInitFunc) camel_mime_parser_init, - (CamelObjectFinalizeFunc) camel_mime_parser_finalise); - } - - return type; -} - -/** - * camel_mime_parser_new: - * - * Create a new CamelMimeParser object. - * - * Return value: A new CamelMimeParser widget. - **/ -CamelMimeParser * -camel_mime_parser_new (void) -{ - CamelMimeParser *new = CAMEL_MIME_PARSER ( camel_object_new (camel_mime_parser_get_type ())); - return new; -} - - -/** - * camel_mime_parser_filter_add: - * @m: - * @mf: - * - * Add a filter that will be applied to any body content before it is passed - * to the caller. Filters may be pipelined to perform multi-pass operations - * on the content, and are applied in the order they were added. - * - * Note that filters are only applied to the body content of messages, and once - * a filter has been set, all content returned by a filter_step() with a state - * of CAMEL_MIME_PARSER_STATE_BODY will have passed through the filter. - * - * Return value: An id that may be passed to filter_remove() to remove - * the filter, or -1 if the operation failed. - **/ -int -camel_mime_parser_filter_add(CamelMimeParser *m, CamelMimeFilter *mf) -{ - struct _header_scan_state *s = _PRIVATE(m); - struct _header_scan_filter *f, *new; - - new = g_malloc(sizeof(*new)); - new->filter = mf; - new->id = s->filterid++; - if (s->filterid == -1) - s->filterid++; - new->next = 0; - camel_object_ref((CamelObject *)mf); - - /* yes, this is correct, since 'next' is the first element of the struct */ - f = (struct _header_scan_filter *)&s->filters; - while (f->next) - f = f->next; - f->next = new; - return new->id; -} - -/** - * camel_mime_parser_filter_remove: - * @m: - * @id: - * - * Remove a processing filter from the pipeline. There is no - * restriction on the order the filters can be removed. - **/ -void -camel_mime_parser_filter_remove(CamelMimeParser *m, int id) -{ - struct _header_scan_state *s = _PRIVATE(m); - struct _header_scan_filter *f, *old; - - f = (struct _header_scan_filter *)&s->filters; - while (f && f->next) { - old = f->next; - if (old->id == id) { - camel_object_unref((CamelObject *)old->filter); - f->next = old->next; - g_free(old); - /* there should only be a single matching id, but - scan the whole lot anyway */ - } - f = f->next; - } -} - -/** - * camel_mime_parser_header: - * @m: - * @name: Name of header. - * @offset: Pointer that can receive the offset of the header in - * the stream from the start of parsing. - * - * Lookup a header by name. - * - * Return value: The header value, or NULL if the header is not - * defined. - **/ -const char * -camel_mime_parser_header(CamelMimeParser *m, const char *name, int *offset) -{ - struct _header_scan_state *s = _PRIVATE(m); - - if (s->parts && - s->parts->headers) { - return camel_header_raw_find(&s->parts->headers, name, offset); - } - return NULL; -} - -/** - * camel_mime_parser_headers_raw: - * @m: - * - * Get the list of the raw headers which are defined for the - * current state of the parser. These headers are valid - * until the next call to parser_step(), or parser_drop_step(). - * - * Return value: The raw headers, or NULL if there are no headers - * defined for the current part or state. These are READ ONLY. - **/ -struct _camel_header_raw * -camel_mime_parser_headers_raw(CamelMimeParser *m) -{ - struct _header_scan_state *s = _PRIVATE(m); - - if (s->parts) - return s->parts->headers; - return NULL; -} - -static const char * -byte_array_to_string(GByteArray *array) -{ - if (array == NULL) - return NULL; - - if (array->len == 0 || array->data[array->len-1] != '\0') - g_byte_array_append(array, "", 1); - - return array->data; -} - -/** - * camel_mime_parser_preface: - * @m: - * - * Retrieve the preface text for the current multipart. - * Can only be used when the state is CAMEL_MIME_PARSER_STATE_MULTIPART_END. - * - * Return value: The preface text, or NULL if there wasn't any. - **/ -const char * -camel_mime_parser_preface(CamelMimeParser *m) -{ - struct _header_scan_state *s = _PRIVATE(m); - - if (s->parts) - return byte_array_to_string(s->parts->pretext); - - return NULL; -} - -/** - * camel_mime_parser_postface: - * @m: - * - * Retrieve the postface text for the current multipart. - * Only returns valid data when the current state if - * CAMEL_MIME_PARSER_STATE_MULTIPART_END. - * - * Return value: The postface text, or NULL if there wasn't any. - **/ -const char * -camel_mime_parser_postface(CamelMimeParser *m) -{ - struct _header_scan_state *s = _PRIVATE(m); - - if (s->parts) - return byte_array_to_string(s->parts->posttext); - - return NULL; -} - -/** - * camel_mime_parser_from_line: - * @m: - * - * Get the last scanned "From " line, from a recently scanned from. - * This should only be called in the CAMEL_MIME_PARSER_STATE_FROM state. The - * from line will include the closing \n found (if there was one). - * - * The return value will remain valid while in the CAMEL_MIME_PARSER_STATE_FROM - * state, or any deeper state. - * - * Return value: The From line, or NULL if called out of context. - **/ -const char * -camel_mime_parser_from_line(CamelMimeParser *m) -{ - struct _header_scan_state *s = _PRIVATE(m); - - if (s->parts) - return byte_array_to_string(s->parts->from_line); - - return NULL; -} - -/** - * camel_mime_parser_init_with_fd: - * @m: - * @fd: A valid file descriptor. - * - * Initialise the scanner with an fd. The scanner's offsets - * will be relative to the current file position of the file - * descriptor. As a result, seekable descritors should - * be seeked using the parser seek functions. - * - * Return value: Returns -1 on error. - **/ -int -camel_mime_parser_init_with_fd(CamelMimeParser *m, int fd) -{ - struct _header_scan_state *s = _PRIVATE(m); - - return folder_scan_init_with_fd(s, fd); -} - -/** - * camel_mime_parser_init_with_stream: - * @m: - * @stream: - * - * Initialise the scanner with a source stream. The scanner's - * offsets will be relative to the current file position of - * the stream. As a result, seekable streams should only - * be seeked using the parser seek function. - * - * Return value: -1 on error. - **/ -int -camel_mime_parser_init_with_stream(CamelMimeParser *m, CamelStream *stream) -{ - struct _header_scan_state *s = _PRIVATE(m); - - return folder_scan_init_with_stream(s, stream); -} - -/** - * camel_mime_parser_scan_from: - * @parser: MIME parser object - * @scan_from: #TRUE if the scanner should scan From lines. - * - * Tell the scanner if it should scan "^From " lines or not. - * - * If the scanner is scanning from lines, two additional - * states CAMEL_MIME_PARSER_STATE_FROM and CAMEL_MIME_PARSER_STATE_FROM_END will be returned - * to the caller during parsing. - * - * This may also be preceeded by an optional - * CAMEL_MIME_PARSER_STATE_PRE_FROM state which contains the scanned data - * found before the From line is encountered. See also - * scan_pre_from(). - **/ -void -camel_mime_parser_scan_from (CamelMimeParser *parser, gboolean scan_from) -{ - struct _header_scan_state *s = _PRIVATE (parser); - - s->scan_from = scan_from; -} - -/** - * camel_mime_parser_scan_pre_from: - * @parser: MIME parser object - * @scan_pre_from: #TRUE if we want to get pre-from data. - * - * Tell the scanner whether we want to know abou the pre-from - * data during a scan. If we do, then we may get an additional - * state CAMEL_MIME_PARSER_STATE_PRE_FROM which returns the specified data. - **/ -void -camel_mime_parser_scan_pre_from (CamelMimeParser *parser, gboolean scan_pre_from) -{ - struct _header_scan_state *s = _PRIVATE (parser); - - s->scan_pre_from = scan_pre_from; -} - -/** - * camel_mime_parser_content_type: - * @parser: MIME parser object - * - * Get the content type defined in the current part. - * - * Return value: A content_type structure, or NULL if there - * is no content-type defined for this part of state of the - * parser. - **/ -CamelContentType * -camel_mime_parser_content_type (CamelMimeParser *parser) -{ - struct _header_scan_state *s = _PRIVATE (parser); - - /* FIXME: should this search up until it's found the 'right' - content-type? can it? */ - if (s->parts) - return s->parts->content_type; - - return NULL; -} - -/** - * camel_mime_parser_unstep: - * @parser: MIME parser object - * - * Cause the last step operation to repeat itself. If this is - * called repeated times, then the same step will be repeated - * that many times. - * - * Note that it is not possible to scan back using this function, - * only to have a way of peeking the next state. - **/ -void -camel_mime_parser_unstep (CamelMimeParser *parser) -{ - struct _header_scan_state *s = _PRIVATE (parser); - - s->unstep++; -} - -/** - * camel_mime_parser_drop_step: - * @parser: MIME parser object - * - * Drop the last step call. This should only be used - * in conjunction with seeking of the stream as the - * stream may be in an undefined state relative to the - * state of the parser. - * - * Use this call with care. - **/ -void -camel_mime_parser_drop_step (CamelMimeParser *parser) -{ - struct _header_scan_state *s = _PRIVATE (parser); - - s->unstep = 0; - folder_scan_drop_step(s); -} - -/** - * camel_mime_parser_step: - * @parser: MIME parser object - * @databuffer: Pointer to accept a pointer to the data - * associated with this step (if any). May be #NULL, - * in which case datalength is also ingored. - * @datalength: Pointer to accept a pointer to the data - * length associated with this step (if any). - * - * Parse the next part of the MIME message. If _unstep() - * has been called, then continue to return the same state - * for that many calls. - * - * If the step is CAMEL_MIME_PARSER_STATE_BODY then the databuffer and datalength - * pointers will be setup to point to the internal data buffer - * of the scanner and may be processed as required. Any - * filters will have already been applied to this data. - * - * Refer to the state diagram elsewhere for a full listing of - * the states an application is gauranteed to get from the - * scanner. - * - * Return value: The current new state of the parser - * is returned. - **/ -enum _camel_mime_parser_state -camel_mime_parser_step (CamelMimeParser *parser, char **databuffer, size_t *datalength) -{ - struct _header_scan_state *s = _PRIVATE (parser); - - d(printf("OLD STATE: '%s' :\n", states[s->state])); - - if (s->unstep <= 0) { - char *dummy; - size_t dummylength; - - if (databuffer == NULL) { - databuffer = &dummy; - datalength = &dummylength; - } - - folder_scan_step(s, databuffer, datalength); - } else - s->unstep--; - - d(printf("NEW STATE: '%s' :\n", states[s->state])); - - return s->state; -} - -/** - * camel_mime_parser_read: - * @parser: MIME parser object - * @databuffer: - * @len: - * - * Read at most @len bytes from the internal mime parser buffer. - * - * Returns the address of the internal buffer in @databuffer, - * and the length of useful data. - * - * @len may be specified as INT_MAX, in which case you will - * get the full remainder of the buffer at each call. - * - * Note that no parsing of the data read through this function - * occurs, so no state changes occur, but the seek position - * is updated appropriately. - * - * Return value: The number of bytes available, or -1 on error. - **/ -int -camel_mime_parser_read (CamelMimeParser *parser, const char **databuffer, int len) -{ - struct _header_scan_state *s = _PRIVATE (parser); - int there; - - if (len == 0) - return 0; - - d(printf("parser::read() reading %d bytes\n", len)); - - there = MIN(s->inend - s->inptr, len); - d(printf("parser::read() there = %d bytes\n", there)); - if (there > 0) { - *databuffer = s->inptr; - s->inptr += there; - return there; - } - - if (folder_read(s) == -1) - return -1; - - there = MIN(s->inend - s->inptr, len); - d(printf("parser::read() had to re-read, now there = %d bytes\n", there)); - - *databuffer = s->inptr; - s->inptr += there; - - return there; -} - -/** - * camel_mime_parser_tell: - * @parser: MIME parser object - * - * Return the current scanning offset. The meaning of this - * value will depend on the current state of the parser. - * - * An incomplete listing of the states: - * - * CAMEL_MIME_PARSER_STATE_INITIAL, The start of the current message. - * CAMEL_MIME_PARSER_STATE_HEADER, CAMEL_MIME_PARSER_STATE_MESSAGE, CAMEL_MIME_PARSER_STATE_MULTIPART, the character - * position immediately after the end of the header. - * CAMEL_MIME_PARSER_STATE_BODY, Position within the message of the start - * of the current data block. - * CAMEL_MIME_PARSER_STATE_*_END, The position of the character starting - * the next section of the scan (the last position + 1 of - * the respective current state). - * - * Return value: See above. - **/ -off_t -camel_mime_parser_tell (CamelMimeParser *parser) -{ - struct _header_scan_state *s = _PRIVATE (parser); - - return folder_tell(s); -} - -/** - * camel_mime_parser_tell_start_headers: - * @parser: MIME parser object - * - * Find out the position within the file of where the - * headers started, this is cached by the parser - * at the time. - * - * Return value: The header start position, or -1 if - * no headers were scanned in the current state. - **/ -off_t -camel_mime_parser_tell_start_headers (CamelMimeParser *parser) -{ - struct _header_scan_state *s = _PRIVATE (parser); - - return s->start_of_headers; -} - -/** - * camel_mime_parser_tell_start_from: - * @parser: MIME parser object - * - * If the parser is scanning From lines, then this returns - * the position of the start of the From line. - * - * Return value: The start of the from line, or -1 if there - * was no From line, or From lines are not being scanned. - **/ -off_t -camel_mime_parser_tell_start_from (CamelMimeParser *parser) -{ - struct _header_scan_state *s = _PRIVATE (parser); - - return s->start_of_from; -} - -/** - * camel_mime_parser_seek: - * @parser: MIME parser object - * @offset: Number of bytes to offset the seek by. - * @whence: SEEK_SET, SEEK_CUR, SEEK_END - * - * Reset the source position to a known value. - * - * Note that if the source stream/descriptor was not - * positioned at 0 to begin with, and an absolute seek - * is specified (whence != SEEK_CUR), then the seek - * position may not match the desired seek position. - * - * Return value: The new seek offset, or -1 on - * an error (for example, trying to seek on a non-seekable - * stream or file descriptor). - **/ -off_t -camel_mime_parser_seek(CamelMimeParser *parser, off_t offset, int whence) -{ - struct _header_scan_state *s = _PRIVATE (parser); - - return folder_seek(s, offset, whence); -} - -/** - * camel_mime_parser_state: - * @parser: MIME parser object - * - * Get the current parser state. - * - * Return value: The current parser state. - **/ -enum _camel_mime_parser_state -camel_mime_parser_state (CamelMimeParser *parser) -{ - struct _header_scan_state *s = _PRIVATE (parser); - - return s->state; -} - -/** - * camel_mime_parser_stream: - * @parser: MIME parser object - * - * Get the stream, if any, the parser has been initialised - * with. May be used to setup sub-streams, but should not - * be read from directly (without saving and restoring - * the seek position in between). - * - * Return value: The stream from _init_with_stream(), or NULL - * if the parser is reading from a file descriptor or is - * uninitialised. - **/ -CamelStream * -camel_mime_parser_stream (CamelMimeParser *parser) -{ - struct _header_scan_state *s = _PRIVATE (parser); - - return s->stream; -} - -/** - * camel_mime_parser_fd: - * @parser: MIME parser object - * - * Return the file descriptor, if any, the parser has been - * initialised with. - * - * Should not be read from unless the parser it to terminate, - * or the seek offset can be reset before the next parse - * step. - * - * Return value: The file descriptor or -1 if the parser - * is reading from a stream or has not been initialised. - **/ -int -camel_mime_parser_fd (CamelMimeParser *parser) -{ - struct _header_scan_state *s = _PRIVATE (parser); - - return s->fd; -} - -/* Return errno of the parser, incase any error occured during processing */ -int -camel_mime_parser_errno (CamelMimeParser *parser) -{ - struct _header_scan_state *s = _PRIVATE (parser); - - return s->ioerrno; -} - -/* ********************************************************************** */ -/* Implementation */ -/* ********************************************************************** */ - -/* read the next bit of data, ensure there is enough room 'atleast' bytes */ -static int -folder_read(struct _header_scan_state *s) -{ - int len; - int inoffset; - - if (s->inptrinend-s->atleast || s->eof) - return s->inend-s->inptr; -#ifdef PURIFY - purify_watch_remove(inend_id); - purify_watch_remove(inbuffer_id); -#endif - /* check for any remaning bytes (under the atleast limit( */ - inoffset = s->inend - s->inptr; - if (inoffset>0) { - memcpy(s->inbuf, s->inptr, inoffset); - } - if (s->stream) { - len = camel_stream_read(s->stream, s->inbuf+inoffset, SCAN_BUF-inoffset); - } else { - len = read(s->fd, s->inbuf+inoffset, SCAN_BUF-inoffset); - } - r(printf("read %d bytes, offset = %d\n", len, inoffset)); - if (len>=0) { - /* add on the last read block */ - s->seek += s->inptr - s->inbuf; - s->inptr = s->inbuf; - s->inend = s->inbuf+len+inoffset; - s->eof = (len == 0); - r(printf("content = %d '%.*s'\n",s->inend - s->inptr, s->inend - s->inptr, s->inptr)); - } else { - s->ioerrno = errno?errno:EIO; - } - - g_assert(s->inptr<=s->inend); -#ifdef PURIFY - inend_id = purify_watch(&s->inend); - inbuffer_id = purify_watch_n(s->inend+1, SCAN_HEAD-1, "rw"); -#endif - r(printf("content = %d '%.*s'\n", s->inend - s->inptr, s->inend - s->inptr, s->inptr)); - /* set a sentinal, for the inner loops to check against */ - s->inend[0] = '\n'; - return s->inend-s->inptr; -} - -/* return the current absolute position of the data pointer */ -static off_t -folder_tell(struct _header_scan_state *s) -{ - return s->seek + (s->inptr - s->inbuf); -} - -/* - need some way to prime the parser state, so this actually works for - other than top-level messages -*/ -static off_t -folder_seek(struct _header_scan_state *s, off_t offset, int whence) -{ - off_t newoffset; - - if (s->stream) { - if (CAMEL_IS_SEEKABLE_STREAM(s->stream)) { - /* NOTE: assumes whence seekable stream == whence libc, which is probably - the case (or bloody well should've been) */ - newoffset = camel_seekable_stream_seek((CamelSeekableStream *)s->stream, offset, whence); - } else { - newoffset = -1; - errno = EINVAL; - } - } else { - newoffset = lseek(s->fd, offset, whence); - } -#ifdef PURIFY - purify_watch_remove(inend_id); - purify_watch_remove(inbuffer_id); -#endif - if (newoffset != -1) { - s->seek = newoffset; - s->inptr = s->inbuf; - s->inend = s->inbuf; - s->eof = FALSE; - } else { - s->ioerrno = errno?errno:EIO; - } -#ifdef PURIFY - inend_id = purify_watch(&s->inend); - inbuffer_id = purify_watch_n(s->inend+1, SCAN_HEAD-1, "rw"); -#endif - return newoffset; -} - -static void -folder_push_part(struct _header_scan_state *s, struct _header_scan_stack *h) -{ - if (s->parts && s->parts->atleast > h->boundarylenfinal) - h->atleast = s->parts->atleast; - else - h->atleast = MAX(h->boundarylenfinal, 1); - - h->parent = s->parts; - s->parts = h; -} - -static void -folder_pull_part(struct _header_scan_state *s) -{ - struct _header_scan_stack *h; - - h = s->parts; - if (h) { - s->parts = h->parent; - g_free(h->boundary); -#ifdef MEMPOOL - mempool_free(h->pool); -#else - camel_header_raw_clear(&h->headers); -#endif - camel_content_type_unref(h->content_type); - if (h->pretext) - g_byte_array_free(h->pretext, TRUE); - if (h->posttext) - g_byte_array_free(h->posttext, TRUE); - if (h->from_line) - g_byte_array_free(h->from_line, TRUE); - g_free(h); - } else { - g_warning("Header stack underflow!\n"); - } -} - -static int -folder_scan_skip_line(struct _header_scan_state *s, GByteArray *save) -{ - int atleast = s->atleast; - register char *inptr, *inend, c; - int len; - - s->atleast = 1; - - d(printf("skipping line\n")); - - while ( (len = folder_read(s)) > 0 && len > s->atleast) { /* ensure we have at least enough room here */ - inptr = s->inptr; - inend = s->inend-1; - - c = -1; - while (inptrinptr, inptr-s->inptr); - - s->inptr = inptr; - - if (c=='\n') { - s->atleast = atleast; - return 0; - } - } - - s->atleast = atleast; - - return -1; /* not found */ -} - -/* TODO: Is there any way to make this run faster? It gets called a lot ... */ -static struct _header_scan_stack * -folder_boundary_check(struct _header_scan_state *s, const char *boundary, int *lastone) -{ - struct _header_scan_stack *part; - int len = s->inend - boundary; /* make sure we dont access past the buffer */ - - h(printf("checking boundary marker upto %d bytes\n", len)); - part = s->parts; - while (part) { - h(printf(" boundary: %s\n", part->boundary)); - h(printf(" against: '%.*s'\n", part->boundarylen, boundary)); - if (part->boundary - && part->boundarylen <= len - && memcmp(boundary, part->boundary, part->boundarylen)==0) { - h(printf("matched boundary: %s\n", part->boundary)); - /* again, make sure we're in range */ - if (part->boundarylenfinal <= len) { - int extra = part->boundarylenfinal - part->boundarylen; - - /* check the extra stuff on an final boundary, normally -- for mime parts */ - if (extra>0) { - *lastone = memcmp(&boundary[part->boundarylen], - &part->boundary[part->boundarylen], - extra) == 0; - } else { - *lastone = TRUE; - } - h(printf("checking lastone = %s\n", *lastone?"TRUE":"FALSE")); - } else { - h(printf("not enough room to check last one?\n")); - *lastone = FALSE; - } - /*printf("ok, we found it! : %s \n", (*lastone)?"Last one":"More to come?");*/ - return part; - } - part = part->parent; - } - return NULL; -} - -#ifdef MEMPOOL -static void -header_append_mempool(struct _header_scan_state *s, struct _header_scan_stack *h, char *header, int offset) -{ - struct _camel_header_raw *l, *n; - char *content; - - content = strchr(header, ':'); - if (content) { - register int len; - n = mempool_alloc(h->pool, sizeof(*n)); - n->next = NULL; - - len = content-header; - n->name = mempool_alloc(h->pool, len+1); - memcpy(n->name, header, len); - n->name[len] = 0; - - content++; - - len = s->outptr - content; - n->value = mempool_alloc(h->pool, len+1); - memcpy(n->value, content, len); - n->value[len] = 0; - - n->offset = offset; - - l = (struct _camel_header_raw *)&h->headers; - while (l->next) { - l = l->next; - } - l->next = n; - } - -} - -#define header_raw_append_parse(a, b, c) (header_append_mempool(s, h, b, c)) - -#endif - -/* Copy the string start->inptr into the header buffer (s->outbuf), - grow if necessary - remove trailing \r chars (\n's assumed already removed) - and track the start offset of the header */ -/* Basically an optimised version of g_byte_array_append() */ -#define header_append(s, start, inptr) \ -{ \ - register int headerlen = inptr-start; \ - \ - if (headerlen > 0) { \ - if (headerlen >= (s->outend - s->outptr)) { \ - register char *outnew; \ - register int len = ((s->outend - s->outbuf)+headerlen)*2+1; \ - outnew = g_realloc(s->outbuf, len); \ - s->outptr = s->outptr - s->outbuf + outnew; \ - s->outbuf = outnew; \ - s->outend = outnew + len; \ - } \ - if (start[headerlen-1] == '\r') \ - headerlen--; \ - memcpy(s->outptr, start, headerlen); \ - s->outptr += headerlen; \ - } \ - if (s->header_start == -1) \ - s->header_start = (start-s->inbuf) + s->seek; \ -} - -static struct _header_scan_stack * -folder_scan_header(struct _header_scan_state *s, int *lastone) -{ - int atleast = s->atleast, newatleast; - char *start = NULL; - int len; - struct _header_scan_stack *h; - char *inend; - register char *inptr; - - h(printf("scanning first bit\n")); - - h = g_malloc0(sizeof(*h)); -#ifdef MEMPOOL - h->pool = mempool_new(8192, 4096); -#endif - - if (s->parts) - newatleast = s->parts->atleast; - else - newatleast = 1; - *lastone = FALSE; - - do { - s->atleast = newatleast; - - h(printf("atleast = %d\n", s->atleast)); - - while ((len = folder_read(s))>0 && len >= s->atleast) { /* ensure we have at least enough room here */ - inptr = s->inptr; - inend = s->inend-s->atleast+1; - - while (inptrmidline) { - if (folder_boundary_check(s, inptr, lastone)) { - if ((s->outptr>s->outbuf)) - goto header_truncated; /* may not actually be truncated */ - - goto header_done; - } - } - - start = inptr; - - /* goto next line/sentinal */ - while ((*inptr++)!='\n') - ; - - g_assert(inptr<=s->inend+1); - - /* check for sentinal or real end of line */ - if (inptr > inend) { - h(printf("not at end of line yet, going further\n")); - /* didn't find end of line within our allowed area */ - inptr = inend; - s->midline = TRUE; - header_append(s, start, inptr); - } else { - h(printf("got line part: '%.*s'\n", inptr-1-start, start)); - /* got a line, strip and add it, process it */ - s->midline = FALSE; -#ifdef PRESERVE_HEADERS - header_append(s, start, inptr); -#else - header_append(s, start, inptr-1); -#endif - /* check for end of headers */ - if (s->outbuf == s->outptr) - goto header_done; - - /* check for continuation/compress headers, we have atleast 1 char here to work with */ - if (inptr[0] == ' ' || inptr[0] == '\t') { - h(printf("continuation\n")); -#ifndef PRESERVE_HEADERS - /* TODO: this wont catch multiple space continuation across a read boundary, but - that is assumed rare, and not fatal anyway */ - do - inptr++; - while (*inptr == ' ' || *inptr == '\t'); - inptr--; - *inptr = ' '; -#endif - } else { - /* otherwise, complete header, add it */ -#ifdef PRESERVE_HEADERS - s->outptr--; - if (s->outptr[-1] == '\r') - s->outptr--; -#endif - s->outptr[0] = 0; - - h(printf("header '%s' at %d\n", s->outbuf, (int)s->header_start)); - - header_raw_append_parse(&h->headers, s->outbuf, s->header_start); - s->outptr = s->outbuf; - s->header_start = -1; - } - } - } - s->inptr = inptr; - } - h(printf("end of file? read %d bytes\n", len)); - newatleast = 1; - } while (s->atleast > 1); - - if ((s->outptr > s->outbuf) || s->inend > s->inptr) { - start = s->inptr; - inptr = s->inend; - if (inptr > start) { - if (inptr[-1] == '\n') - inptr--; - } - goto header_truncated; - } - - s->atleast = atleast; - - return h; - -header_truncated: - header_append(s, start, inptr); - - s->outptr[0] = 0; - if (s->outbuf == s->outptr) - goto header_done; - - header_raw_append_parse(&h->headers, s->outbuf, s->header_start); - - s->outptr = s->outbuf; -header_done: - s->inptr = inptr; - s->atleast = atleast; - s->header_start = -1; - return h; -} - -static struct _header_scan_stack * -folder_scan_content(struct _header_scan_state *s, int *lastone, char **data, size_t *length) -{ - int atleast = s->atleast, newatleast; - register char *inptr; - char *inend; - char *start; - int len; - struct _header_scan_stack *part; - int onboundary = FALSE; - - c(printf("scanning content\n")); - - part = s->parts; - if (part) - newatleast = part->atleast; - else - newatleast = 1; - *lastone = FALSE; - - c(printf("atleast = %d\n", newatleast)); - - do { - s->atleast = newatleast; - - while ((len = folder_read(s))>0 && len >= s->atleast) { /* ensure we have at least enough room here */ - inptr = s->inptr; - if (s->eof) - inend = s->inend; - else - inend = s->inend-s->atleast+1; - start = inptr; - - c(printf("inptr = %p, inend = %p\n", inptr, inend)); - - while (inptrmidline - && (part = folder_boundary_check(s, inptr, lastone))) { - onboundary = TRUE; - - /* since we truncate the boundary data, we need at least 1 char here spare, - to remain in the same state */ - if ( (inptr-start) > 1) - goto content; - - /* otherwise, jump to the state of the boundary we actually found */ - goto normal_exit; - } - - /* goto the next line */ - while ((*inptr++)!='\n') - ; - - /* check the sentinal, if we went past the atleast limit, and reset it to there */ - if (inptr > inend) { - s->midline = TRUE; - inptr = inend; - } else { - s->midline = FALSE; - } - } - - c(printf("ran out of input, dumping what i have (%d) bytes midline = %s\n", - inptr-start, s->midline?"TRUE":"FALSE")); - goto content; - } - newatleast = 1; - } while (s->atleast > 1); - - c(printf("length read = %d\n", len)); - - if (s->inend > s->inptr) { - start = s->inptr; - inptr = s->inend; - goto content; - } - - *length = 0; - s->atleast = atleast; - return NULL; - -content: - /* treat eof as the last boundary in From mode */ - if (s->scan_from && s->eof && s->atleast <= 1) { - onboundary = TRUE; - part = NULL; - } else { - part = s->parts; - } -normal_exit: - s->atleast = atleast; - s->inptr = inptr; - - *data = start; - /* if we hit a boundary, we should not include the closing \n */ - if (onboundary && (inptr-start)>0) - *length = inptr-start-1; - else - *length = inptr-start; - - /*printf("got %scontent: '%.*s'\n", s->midline?"partial ":"", inptr-start, start);*/ - - return part; -} - - -static void -folder_scan_close(struct _header_scan_state *s) -{ - g_free(s->realbuf); - g_free(s->outbuf); - while (s->parts) - folder_pull_part(s); - if (s->fd != -1) - close(s->fd); - if (s->stream) { - camel_object_unref((CamelObject *)s->stream); - } - g_free(s); -} - - -static struct _header_scan_state * -folder_scan_init(void) -{ - struct _header_scan_state *s; - - s = g_malloc(sizeof(*s)); - - s->fd = -1; - s->stream = NULL; - s->ioerrno = 0; - - s->outbuf = g_malloc(1024); - s->outptr = s->outbuf; - s->outend = s->outbuf+1024; - - s->realbuf = g_malloc(SCAN_BUF + SCAN_HEAD*2); - s->inbuf = s->realbuf + SCAN_HEAD; - s->inptr = s->inbuf; - s->inend = s->inbuf; - s->atleast = 0; - - s->seek = 0; /* current character position in file of the last read block */ - s->unstep = 0; - - s->header_start = -1; - - s->start_of_from = -1; - s->start_of_headers = -1; - - s->midline = FALSE; - s->scan_from = FALSE; - s->scan_pre_from = FALSE; - s->eof = FALSE; - - s->filters = NULL; - s->filterid = 1; - - s->parts = NULL; - - s->state = CAMEL_MIME_PARSER_STATE_INITIAL; - return s; -} - -static void -drop_states(struct _header_scan_state *s) -{ - while (s->parts) { - folder_scan_drop_step(s); - } - s->unstep = 0; - s->state = CAMEL_MIME_PARSER_STATE_INITIAL; -} - -static void -folder_scan_reset(struct _header_scan_state *s) -{ - drop_states(s); - s->inend = s->inbuf; - s->inptr = s->inbuf; - s->inend[0] = '\n'; - if (s->fd != -1) { - close(s->fd); - s->fd = -1; - } - if (s->stream) { - camel_object_unref((CamelObject *)s->stream); - s->stream = NULL; - } - s->ioerrno = 0; - s->eof = FALSE; -} - -static int -folder_scan_init_with_fd(struct _header_scan_state *s, int fd) -{ - folder_scan_reset(s); - s->fd = fd; - - return 0; -} - -static int -folder_scan_init_with_stream(struct _header_scan_state *s, CamelStream *stream) -{ - folder_scan_reset(s); - s->stream = stream; - camel_object_ref((CamelObject *)stream); - - return 0; -} - -#define USE_FROM - -static void -folder_scan_step(struct _header_scan_state *s, char **databuffer, size_t *datalength) -{ - struct _header_scan_stack *h, *hb; - const char *content; - const char *bound; - int type; - int state; - CamelContentType *ct = NULL; - struct _header_scan_filter *f; - size_t presize; - -/* printf("\nSCAN PASS: state = %d '%s'\n", s->state, states[s->state]);*/ - -tail_recurse: - d({ - printf("\nSCAN STACK:\n"); - printf(" '%s' :\n", states[s->state]); - hb = s->parts; - while (hb) { - printf(" '%s' : %s ", states[hb->savestate], hb->boundary); - if (hb->content_type) { - printf("(%s/%s)", hb->content_type->type, hb->content_type->subtype); - } else { - printf("(default)"); - } - printf("\n"); - hb = hb->parent; - } - printf("\n"); - }); - - switch (s->state) { - -#ifdef USE_FROM - case CAMEL_MIME_PARSER_STATE_INITIAL: - if (s->scan_from) { - h = g_malloc0(sizeof(*h)); - h->boundary = g_strdup("From "); - h->boundarylen = strlen(h->boundary); - h->boundarylenfinal = h->boundarylen; - h->from_line = g_byte_array_new(); - folder_push_part(s, h); - s->state = CAMEL_MIME_PARSER_STATE_PRE_FROM; - } else { - s->start_of_from = -1; - goto scan_header; - } - - case CAMEL_MIME_PARSER_STATE_PRE_FROM: - - h = s->parts; - do { - hb = folder_scan_content(s, &state, databuffer, datalength); - if (s->scan_pre_from && *datalength > 0) { - d(printf("got pre-from content %d bytes\n", *datalength)); - return; - } - } while (hb==h && *datalength>0); - - if (*datalength==0 && hb==h) { - d(printf("found 'From '\n")); - s->start_of_from = folder_tell(s); - folder_scan_skip_line(s, h->from_line); - h->savestate = CAMEL_MIME_PARSER_STATE_INITIAL; - s->state = CAMEL_MIME_PARSER_STATE_FROM; - } else { - folder_pull_part(s); - s->state = CAMEL_MIME_PARSER_STATE_EOF; - } - return; -#else - case CAMEL_MIME_PARSER_STATE_INITIAL: - case CAMEL_MIME_PARSER_STATE_PRE_FROM: -#endif /* !USE_FROM */ - - scan_header: - case CAMEL_MIME_PARSER_STATE_FROM: - s->start_of_headers = folder_tell(s); - h = folder_scan_header(s, &state); -#ifdef USE_FROM - if (s->scan_from) - h->savestate = CAMEL_MIME_PARSER_STATE_FROM_END; - else -#endif - h->savestate = CAMEL_MIME_PARSER_STATE_EOF; - - /* FIXME: should this check for MIME-Version: 1.0 as well? */ - - type = CAMEL_MIME_PARSER_STATE_HEADER; - if ( (content = camel_header_raw_find(&h->headers, "Content-Type", NULL)) - && (ct = camel_content_type_decode(content))) { - if (!strcasecmp(ct->type, "multipart")) { - if (!camel_content_type_is(ct, "multipart", "signed") - && (bound = camel_content_type_param(ct, "boundary"))) { - d(printf("multipart, boundary = %s\n", bound)); - h->boundarylen = strlen(bound)+2; - h->boundarylenfinal = h->boundarylen+2; - h->boundary = g_malloc(h->boundarylen+3); - sprintf(h->boundary, "--%s--", bound); - type = CAMEL_MIME_PARSER_STATE_MULTIPART; - } else { - /*camel_content_type_unref(ct); - ct = camel_content_type_decode("text/plain");*/ -/* We can't quite do this, as it will mess up all the offsets ... */ -/* camel_header_raw_replace(&h->headers, "Content-Type", "text/plain", offset);*/ - /*g_warning("Multipart with no boundary, treating as text/plain");*/ - } - } else if (!strcasecmp(ct->type, "message")) { - if (!strcasecmp(ct->subtype, "rfc822") - || !strcasecmp(ct->subtype, "news") - /*|| !strcasecmp(ct->subtype, "partial")*/) { - type = CAMEL_MIME_PARSER_STATE_MESSAGE; - } - } - } else { - /* make the default type for multipart/digest be message/rfc822 */ - if ((s->parts - && camel_content_type_is(s->parts->content_type, "multipart", "digest"))) { - ct = camel_content_type_decode("message/rfc822"); - type = CAMEL_MIME_PARSER_STATE_MESSAGE; - d(printf("parent was multipart/digest, autoupgrading to message/rfc822?\n")); - /* maybe we should do this too? - header_raw_append_parse(&h->headers, "Content-Type: message/rfc822", -1);*/ - } else { - ct = camel_content_type_decode("text/plain"); - } - } - h->content_type = ct; - folder_push_part(s, h); - s->state = type; - return; - - case CAMEL_MIME_PARSER_STATE_HEADER: - s->state = CAMEL_MIME_PARSER_STATE_BODY; - - case CAMEL_MIME_PARSER_STATE_BODY: - h = s->parts; - *datalength = 0; - presize = SCAN_HEAD; - f = s->filters; - - do { - hb = folder_scan_content (s, &state, databuffer, datalength); - - d(printf ("\n\nOriginal content: '")); - d(fwrite(*databuffer, sizeof(char), *datalength, stdout)); - d(printf("'\n")); - - if (*datalength > 0) { - while (f) { - camel_mime_filter_filter(f->filter, *databuffer, *datalength, presize, - databuffer, datalength, &presize); - d(printf("Filtered content (%s): '", ((CamelObject *)f->filter)->klass->name)); - d(fwrite(*databuffer, sizeof(char), *datalength, stdout)); - d(printf("'\n")); - f = f->next; - } - return; - } - } while (hb == h && *datalength > 0); - - /* check for any filter completion data */ - while (f) { - camel_mime_filter_complete(f->filter, *databuffer, *datalength, presize, - databuffer, datalength, &presize); - f = f->next; - } - - if (*datalength > 0) - return; - - s->state = CAMEL_MIME_PARSER_STATE_BODY_END; - break; - - case CAMEL_MIME_PARSER_STATE_MULTIPART: - h = s->parts; - do { - do { - hb = folder_scan_content(s, &state, databuffer, datalength); - if (*datalength>0) { - /* instead of a new state, we'll just store it locally and provide - an accessor function */ - d(printf("Multipart %s Content %p: '%.*s'\n", - h->prestage>0?"post":"pre", h, *datalength, *databuffer)); - if (h->prestage > 0) { - if (h->posttext == NULL) - h->posttext = g_byte_array_new(); - g_byte_array_append(h->posttext, *databuffer, *datalength); - } else { - if (h->pretext == NULL) - h->pretext = g_byte_array_new(); - g_byte_array_append(h->pretext, *databuffer, *datalength); - } - } - } while (hb==h && *datalength>0); - h->prestage++; - if (*datalength==0 && hb==h) { - d(printf("got boundary: %s\n", hb->boundary)); - folder_scan_skip_line(s, NULL); - if (!state) { - s->state = CAMEL_MIME_PARSER_STATE_FROM; - folder_scan_step(s, databuffer, datalength); - s->parts->savestate = CAMEL_MIME_PARSER_STATE_MULTIPART; /* set return state for the new head part */ - return; - } - } else { - break; - } - } while (1); - - s->state = CAMEL_MIME_PARSER_STATE_MULTIPART_END; - break; - - case CAMEL_MIME_PARSER_STATE_MESSAGE: - s->state = CAMEL_MIME_PARSER_STATE_FROM; - folder_scan_step(s, databuffer, datalength); - s->parts->savestate = CAMEL_MIME_PARSER_STATE_MESSAGE_END; - break; - - case CAMEL_MIME_PARSER_STATE_FROM_END: - case CAMEL_MIME_PARSER_STATE_BODY_END: - case CAMEL_MIME_PARSER_STATE_MULTIPART_END: - case CAMEL_MIME_PARSER_STATE_MESSAGE_END: - s->state = s->parts->savestate; - folder_pull_part(s); - if (s->state & CAMEL_MIME_PARSER_STATE_END) - return; - goto tail_recurse; - - case CAMEL_MIME_PARSER_STATE_EOF: - return; - - default: - g_warning("Invalid state in camel-mime-parser: %d", s->state); - break; - } - - return; -} - -/* drops the current state back one */ -static void -folder_scan_drop_step(struct _header_scan_state *s) -{ - switch (s->state) { - case CAMEL_MIME_PARSER_STATE_EOF: - s->state = CAMEL_MIME_PARSER_STATE_INITIAL; - case CAMEL_MIME_PARSER_STATE_INITIAL: - return; - - case CAMEL_MIME_PARSER_STATE_FROM: - case CAMEL_MIME_PARSER_STATE_PRE_FROM: - s->state = CAMEL_MIME_PARSER_STATE_INITIAL; - folder_pull_part(s); - return; - - case CAMEL_MIME_PARSER_STATE_MESSAGE: - case CAMEL_MIME_PARSER_STATE_HEADER: - case CAMEL_MIME_PARSER_STATE_MULTIPART: - - case CAMEL_MIME_PARSER_STATE_FROM_END: - case CAMEL_MIME_PARSER_STATE_BODY_END: - case CAMEL_MIME_PARSER_STATE_MULTIPART_END: - case CAMEL_MIME_PARSER_STATE_MESSAGE_END: - - s->state = s->parts->savestate; - folder_pull_part(s); - if (s->state & CAMEL_MIME_PARSER_STATE_END) { - s->state &= ~CAMEL_MIME_PARSER_STATE_END; - } - return; - default: - /* FIXME: not sure if this is entirely right */ - break; - } -} - -#ifdef STANDALONE -int main(int argc, char **argv) -{ - int fd; - struct _header_scan_state *s; - char *data; - size_t len; - int state; - char *name = "/tmp/evmail/Inbox"; - struct _header_scan_stack *h; - int i; - int attach = 0; - - if (argc==2) - name = argv[1]; - - printf("opening: %s", name); - - for (i=1;iscan_from = FALSE; -#if 0 - h = g_malloc0(sizeof(*h)); - h->savestate = CAMEL_MIME_PARSER_STATE_EOF; - folder_push_part(s, h); -#endif - while (s->state != CAMEL_MIME_PARSER_STATE_EOF) { - folder_scan_step(s, &data, &len); - printf("\n -- PARSER STEP RETURN -- %d '%s'\n\n", s->state, states[s->state]); - switch (s->state) { - case CAMEL_MIME_PARSER_STATE_HEADER: - if (s->parts->content_type - && (charset = camel_content_type_param(s->parts->content_type, "charset"))) { - if (strcasecmp(charset, "us-ascii")) { -#if 0 - folder_push_filter_charset(s, "UTF-8", charset); -#endif - } else { - charset = NULL; - } - } else { - charset = NULL; - } - - encoding = camel_header_raw_find(&s->parts->headers, "Content-transfer-encoding", 0); - printf("encoding = '%s'\n", encoding); - if (encoding && !strncasecmp(encoding, " base64", 7)) { - printf("adding base64 filter\n"); - attachname = g_strdup_printf("attach.%d.%d", i, attach++); -#if 0 - folder_push_filter_save(s, attachname); -#endif - g_free(attachname); -#if 0 - folder_push_filter_mime(s, 0); -#endif - } - if (encoding && !strncasecmp(encoding, " quoted-printable", 17)) { - printf("adding quoted-printable filter\n"); - attachname = g_strdup_printf("attach.%d.%d", i, attach++); -#if 0 - folder_push_filter_save(s, attachname); -#endif - g_free(attachname); -#if 0 - folder_push_filter_mime(s, 1); -#endif - } - - break; - case CAMEL_MIME_PARSER_STATE_BODY: - printf("got body %d '%.*s'\n", len, len, data); - break; - case CAMEL_MIME_PARSER_STATE_BODY_END: - printf("end body %d '%.*s'\n", len, len, data); - if (encoding && !strncasecmp(encoding, " base64", 7)) { - printf("removing filters\n"); -#if 0 - folder_filter_pull(s); - folder_filter_pull(s); -#endif - } - if (encoding && !strncasecmp(encoding, " quoted-printable", 17)) { - printf("removing filters\n"); -#if 0 - folder_filter_pull(s); - folder_filter_pull(s); -#endif - } - if (charset) { -#if 0 - folder_filter_pull(s); -#endif - charset = NULL; - } - encoding = NULL; - break; - default: - break; - } - } - folder_scan_close(s); - close(fd); - } - return 0; -} - -#endif /* STANDALONE */ - diff --git a/camel/camel-mime-parser.h b/camel/camel-mime-parser.h deleted file mode 100644 index db85133cbc..0000000000 --- a/camel/camel-mime-parser.h +++ /dev/null @@ -1,146 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000-2003 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_MIME_PARSER_H -#define _CAMEL_MIME_PARSER_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#include -#include -#include - -#define CAMEL_MIME_PARSER(obj) CAMEL_CHECK_CAST (obj, camel_mime_parser_get_type (), CamelMimeParser) -#define CAMEL_MIME_PARSER_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_mime_parser_get_type (), CamelMimeParserClass) -#define CAMEL_IS_MIME_PARSER(obj) CAMEL_CHECK_TYPE (obj, camel_mime_parser_get_type ()) - -typedef struct _CamelMimeParserClass CamelMimeParserClass; - -/* NOTE: if you add more states, you may need to bump the - start of the END tags to 16 or 32, etc - so they are - the same as the matching start tag, with a bit difference */ -enum _camel_mime_parser_state { - CAMEL_MIME_PARSER_STATE_INITIAL, - CAMEL_MIME_PARSER_STATE_PRE_FROM, /* data before a 'From' line */ - CAMEL_MIME_PARSER_STATE_FROM, /* got 'From' line */ - CAMEL_MIME_PARSER_STATE_HEADER, /* toplevel header */ - CAMEL_MIME_PARSER_STATE_BODY, /* scanning body of message */ - CAMEL_MIME_PARSER_STATE_MULTIPART, /* got multipart header */ - CAMEL_MIME_PARSER_STATE_MESSAGE, /* rfc822 message */ - - CAMEL_MIME_PARSER_STATE_PART, /* part of a multipart */ - - CAMEL_MIME_PARSER_STATE_END = 8, /* bit mask for 'end' flags */ - - CAMEL_MIME_PARSER_STATE_EOF = 8, /* end of file */ - CAMEL_MIME_PARSER_STATE_PRE_FROM_END, /* pre from end */ - CAMEL_MIME_PARSER_STATE_FROM_END, /* end of whole from bracket */ - CAMEL_MIME_PARSER_STATE_HEADER_END, /* dummy value */ - CAMEL_MIME_PARSER_STATE_BODY_END, /* end of message */ - CAMEL_MIME_PARSER_STATE_MULTIPART_END, /* end of multipart */ - CAMEL_MIME_PARSER_STATE_MESSAGE_END, /* end of message */ -}; - -struct _CamelMimeParser { - CamelObject parent; - - struct _CamelMimeParserPrivate *priv; -}; - -struct _CamelMimeParserClass { - CamelObjectClass parent_class; - - void (*message) (CamelMimeParser *parser, void *headers); - void (*part) (CamelMimeParser *parser); - void (*content) (CamelMimeParser *parser); -}; - -CamelType camel_mime_parser_get_type (void); -CamelMimeParser *camel_mime_parser_new (void); - -/* quick-fix for parser not erroring, we can find out if it had an error afterwards */ -int camel_mime_parser_errno (CamelMimeParser *parser); - -/* using an fd will be a little faster, but not much (over a simple stream) */ -int camel_mime_parser_init_with_fd (CamelMimeParser *parser, int fd); -int camel_mime_parser_init_with_stream (CamelMimeParser *parser, CamelStream *stream); - -/* get the stream or fd back of the parser */ -CamelStream *camel_mime_parser_stream (CamelMimeParser *parser); -int camel_mime_parser_fd (CamelMimeParser *parser); - -/* scan 'From' separators? */ -void camel_mime_parser_scan_from (CamelMimeParser *parser, gboolean scan_from); -/* Do we want to know about the pre-from data? */ -void camel_mime_parser_scan_pre_from (CamelMimeParser *parser, gboolean scan_pre_from); - -/* what headers to save, MUST include ^Content-Type: */ -int camel_mime_parser_set_header_regex (CamelMimeParser *parser, char *matchstr); - -/* normal interface */ -enum _camel_mime_parser_state camel_mime_parser_step (CamelMimeParser *parser, char **buf, size_t *buflen); -void camel_mime_parser_unstep (CamelMimeParser *parser); -void camel_mime_parser_drop_step (CamelMimeParser *parser); -enum _camel_mime_parser_state camel_mime_parser_state (CamelMimeParser *parser); - -/* read through the parser */ -int camel_mime_parser_read (CamelMimeParser *parser, const char **databuffer, int len); - -/* get content type for the current part/header */ -CamelContentType *camel_mime_parser_content_type (CamelMimeParser *parser); - -/* get/change raw header by name */ -const char *camel_mime_parser_header (CamelMimeParser *parser, const char *name, int *offset); - -/* get all raw headers. READ ONLY! */ -struct _camel_header_raw *camel_mime_parser_headers_raw (CamelMimeParser *parser); - -/* get multipart pre/postface */ -const char *camel_mime_parser_preface (CamelMimeParser *parser); -const char *camel_mime_parser_postface (CamelMimeParser *parser); - -/* return the from line content */ -const char *camel_mime_parser_from_line (CamelMimeParser *parser); - -/* add a processing filter for body contents */ -int camel_mime_parser_filter_add (CamelMimeParser *parser, CamelMimeFilter *filter); -void camel_mime_parser_filter_remove (CamelMimeParser *parser, int id); - -/* these should be used with caution, because the state will not - track the seeked position */ -/* FIXME: something to bootstrap the state? */ -off_t camel_mime_parser_tell (CamelMimeParser *parser); -off_t camel_mime_parser_seek (CamelMimeParser *parser, off_t offset, int whence); - -off_t camel_mime_parser_tell_start_headers (CamelMimeParser *parser); -off_t camel_mime_parser_tell_start_from (CamelMimeParser *parser); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_MIME_PARSER_H */ diff --git a/camel/camel-mime-part-utils.c b/camel/camel-mime-part-utils.c deleted file mode 100644 index f063b3af80..0000000000 --- a/camel/camel-mime-part-utils.c +++ /dev/null @@ -1,137 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* camel-mime-part-utils : Utility for mime parsing and so on - * - * Authors: Bertrand Guiheneuf - * Michael Zucchi - * Jeffrey Stedfast - * - * Copyright 1999-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include - -#include "camel-charset-map.h" -#include "camel-mime-part-utils.h" -#include "camel-mime-message.h" -#include "camel-multipart.h" -#include "camel-multipart-signed.h" -#include "camel-multipart-encrypted.h" -#include "camel-seekable-substream.h" -#include "camel-stream-fs.h" -#include "camel-stream-filter.h" -#include "camel-stream-mem.h" -#include "camel-mime-filter-basic.h" -#include "camel-mime-filter-charset.h" -#include "camel-mime-filter-crlf.h" -#include "camel-mime-filter-save.h" -#include "camel-html-parser.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x)) - #include */ - -/* simple data wrapper */ -static void -simple_data_wrapper_construct_from_parser (CamelDataWrapper *dw, CamelMimeParser *mp) -{ - char *buf; - GByteArray *buffer; - CamelStream *mem; - size_t len; - - d(printf ("simple_data_wrapper_construct_from_parser()\n")); - - /* read in the entire content */ - buffer = g_byte_array_new (); - while (camel_mime_parser_step (mp, &buf, &len) != CAMEL_MIME_PARSER_STATE_BODY_END) { - d(printf("appending o/p data: %d: %.*s\n", len, len, buf)); - g_byte_array_append (buffer, buf, len); - } - - d(printf("message part kept in memory!\n")); - - mem = camel_stream_mem_new_with_byte_array (buffer); - camel_data_wrapper_construct_from_stream (dw, mem); - camel_object_unref (mem); -} - -/* This replaces the data wrapper repository ... and/or could be replaced by it? */ -void -camel_mime_part_construct_content_from_parser (CamelMimePart *dw, CamelMimeParser *mp) -{ - CamelDataWrapper *content = NULL; - CamelContentType *ct; - char *encoding; - - ct = camel_mime_parser_content_type (mp); - - encoding = camel_content_transfer_encoding_decode (camel_mime_parser_header (mp, "Content-Transfer-Encoding", NULL)); - - switch (camel_mime_parser_state (mp)) { - case CAMEL_MIME_PARSER_STATE_HEADER: - d(printf("Creating body part\n")); - /* multipart/signed is some fucked up type that we must treat as binary data, fun huh, idiots. */ - if (camel_content_type_is (ct, "multipart", "signed")) { - content = (CamelDataWrapper *) camel_multipart_signed_new (); - camel_multipart_construct_from_parser ((CamelMultipart *) content, mp); - } else { - content = camel_data_wrapper_new (); - simple_data_wrapper_construct_from_parser (content, mp); - } - break; - case CAMEL_MIME_PARSER_STATE_MESSAGE: - d(printf("Creating message part\n")); - content = (CamelDataWrapper *) camel_mime_message_new (); - camel_mime_part_construct_from_parser ((CamelMimePart *)content, mp); - break; - case CAMEL_MIME_PARSER_STATE_MULTIPART: - d(printf("Creating multi-part\n")); - if (camel_content_type_is (ct, "multipart", "encrypted")) - content = (CamelDataWrapper *) camel_multipart_encrypted_new (); - else if (camel_content_type_is (ct, "multipart", "signed")) - content = (CamelDataWrapper *) camel_multipart_signed_new (); - else - content = (CamelDataWrapper *) camel_multipart_new (); - - camel_multipart_construct_from_parser((CamelMultipart *)content, mp); - d(printf("Created multi-part\n")); - break; - default: - g_warning("Invalid state encountered???: %d", camel_mime_parser_state (mp)); - } - - if (content) { - if (encoding) - content->encoding = camel_transfer_encoding_from_string (encoding); - - /* would you believe you have to set this BEFORE you set the content object??? oh my god !!!! */ - camel_data_wrapper_set_mime_type_field (content, camel_mime_part_get_content_type (dw)); - camel_medium_set_content_object ((CamelMedium *)dw, content); - camel_object_unref (content); - } - - g_free (encoding); -} diff --git a/camel/camel-mime-part-utils.h b/camel/camel-mime-part-utils.h deleted file mode 100644 index 576f7bd3e4..0000000000 --- a/camel/camel-mime-part-utils.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-mime-part-utils : Utility for mime parsing and so on */ - - -/* - * - * Author : - * Bertrand Guiheneuf - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_MIME_PART_UTILS_H -#define CAMEL_MIME_PART_UTILS_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include - -void camel_mime_part_construct_content_from_parser(CamelMimePart *, CamelMimeParser *mp); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_MIME_PART_UTILS_H */ - diff --git a/camel/camel-mime-part.c b/camel/camel-mime-part.c deleted file mode 100644 index 3a57a51970..0000000000 --- a/camel/camel-mime-part.c +++ /dev/null @@ -1,912 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* camelMimePart.c : Abstract class for a mime_part */ - -/* - * Authors: Bertrand Guiheneuf - * Michael Zucchi - * Jeffrey Stedfast - * - * Copyright 1999-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include - -#include "camel-mime-parser.h" -#include "camel-stream-mem.h" -#include "camel-stream-filter.h" -#include "camel-mime-filter-basic.h" -#include "camel-mime-filter-crlf.h" -#include "camel-mime-filter-charset.h" -#include "camel-mime-part.h" -#include "camel-mime-part-utils.h" -#include "camel-mime-utils.h" -#include "camel-exception.h" -#include "camel-charset-map.h" -#include "camel-string-utils.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -typedef enum { - HEADER_UNKNOWN, - HEADER_DESCRIPTION, - HEADER_DISPOSITION, - HEADER_CONTENT_ID, - HEADER_ENCODING, - HEADER_CONTENT_MD5, - HEADER_CONTENT_LOCATION, - HEADER_CONTENT_LANGUAGES, - HEADER_CONTENT_TYPE -} CamelHeaderType; - - -static GHashTable *header_name_table; -static GHashTable *header_formatted_table; - -static CamelMediumClass *parent_class=NULL; - -/* Returns the class for a CamelMimePart */ -#define CMP_CLASS(so) CAMEL_MIME_PART_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CDW_CLASS(so) CAMEL_DATA_WRAPPER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMD_CLASS(so) CAMEL_MEDIUM_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -/* from CamelDataWrapper */ -static ssize_t write_to_stream (CamelDataWrapper *dw, CamelStream *stream); -static int construct_from_stream (CamelDataWrapper *dw, CamelStream *stream); - -/* from CamelMedium */ -static void add_header (CamelMedium *medium, const char *name, const void *value); -static void set_header (CamelMedium *medium, const char *name, const void *value); -static void remove_header (CamelMedium *medium, const char *name); -static const void *get_header (CamelMedium *medium, const char *name); -static GArray *get_headers (CamelMedium *medium); -static void free_headers (CamelMedium *medium, GArray *headers); - -static void set_content_object (CamelMedium *medium, CamelDataWrapper *content); - -/* from camel mime parser */ -static int construct_from_parser (CamelMimePart *mime_part, CamelMimeParser *mp); - -/* forward references */ -static void set_disposition (CamelMimePart *mime_part, const char *disposition); - -/* format output of headers */ -static int write_references(CamelStream *stream, struct _camel_header_raw *h); -/*static int write_fold(CamelStream *stream, struct _camel_header_raw *h);*/ -static int write_raw(CamelStream *stream, struct _camel_header_raw *h); - - -/* loads in a hash table the set of header names we */ -/* recognize and associate them with a unique enum */ -/* identifier (see CamelHeaderType above) */ -static void -init_header_name_table() -{ - header_name_table = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); - g_hash_table_insert (header_name_table, "Content-Description", (gpointer)HEADER_DESCRIPTION); - g_hash_table_insert (header_name_table, "Content-Disposition", (gpointer)HEADER_DISPOSITION); - g_hash_table_insert (header_name_table, "Content-id", (gpointer)HEADER_CONTENT_ID); - g_hash_table_insert (header_name_table, "Content-Transfer-Encoding", (gpointer)HEADER_ENCODING); - g_hash_table_insert (header_name_table, "Content-MD5", (gpointer)HEADER_CONTENT_MD5); - g_hash_table_insert (header_name_table, "Content-Location", (gpointer)HEADER_CONTENT_LOCATION); - g_hash_table_insert (header_name_table, "Content-Type", (gpointer)HEADER_CONTENT_TYPE); - - header_formatted_table = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); - g_hash_table_insert(header_formatted_table, "Content-Type", write_raw); - g_hash_table_insert(header_formatted_table, "Content-Disposition", write_raw); - g_hash_table_insert(header_formatted_table, "To", write_raw); - g_hash_table_insert(header_formatted_table, "From", write_raw); - g_hash_table_insert(header_formatted_table, "Reply-To", write_raw); - g_hash_table_insert(header_formatted_table, "Cc", write_raw); - g_hash_table_insert(header_formatted_table, "Bcc", write_raw); - g_hash_table_insert(header_formatted_table, "Message-ID", write_raw); - g_hash_table_insert(header_formatted_table, "In-Reply-To", write_raw); - g_hash_table_insert(header_formatted_table, "References", write_references); -} - -static void -camel_mime_part_class_init (CamelMimePartClass *camel_mime_part_class) -{ - CamelMediumClass *camel_medium_class = CAMEL_MEDIUM_CLASS (camel_mime_part_class); - CamelDataWrapperClass *camel_data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (camel_mime_part_class); - - parent_class = CAMEL_MEDIUM_CLASS (camel_type_get_global_classfuncs (camel_medium_get_type ())); - init_header_name_table(); - - camel_mime_part_class->construct_from_parser = construct_from_parser; - - /* virtual method overload */ - camel_medium_class->add_header = add_header; - camel_medium_class->set_header = set_header; - camel_medium_class->get_header = get_header; - camel_medium_class->remove_header = remove_header; - camel_medium_class->get_headers = get_headers; - camel_medium_class->free_headers = free_headers; - camel_medium_class->set_content_object = set_content_object; - - camel_data_wrapper_class->write_to_stream = write_to_stream; - camel_data_wrapper_class->construct_from_stream= construct_from_stream; -} - -static void -camel_mime_part_init (gpointer object, gpointer klass) -{ - CamelMimePart *mime_part = CAMEL_MIME_PART (object); - - if (((CamelDataWrapper *) mime_part)->mime_type) - camel_content_type_unref (((CamelDataWrapper *) mime_part)->mime_type); - ((CamelDataWrapper *) mime_part)->mime_type = camel_content_type_new ("text", "plain"); - - mime_part->description = NULL; - mime_part->disposition = NULL; - mime_part->content_id = NULL; - mime_part->content_MD5 = NULL; - mime_part->content_location = NULL; - mime_part->content_languages = NULL; - mime_part->encoding = CAMEL_TRANSFER_ENCODING_DEFAULT; -} - - -static void -camel_mime_part_finalize (CamelObject *object) -{ - CamelMimePart *mime_part = CAMEL_MIME_PART (object); - - g_free (mime_part->description); - g_free (mime_part->content_id); - g_free (mime_part->content_MD5); - g_free (mime_part->content_location); - camel_string_list_free (mime_part->content_languages); - camel_content_disposition_unref(mime_part->disposition); - - camel_header_raw_clear(&mime_part->headers); -} - - - -CamelType -camel_mime_part_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (CAMEL_MEDIUM_TYPE, - "CamelMimePart", - sizeof (CamelMimePart), - sizeof (CamelMimePartClass), - (CamelObjectClassInitFunc) camel_mime_part_class_init, - NULL, - (CamelObjectInitFunc) camel_mime_part_init, - (CamelObjectFinalizeFunc) camel_mime_part_finalize); - } - - return type; -} - - -/* **** */ - -static gboolean -process_header(CamelMedium *medium, const char *name, const char *value) -{ - CamelMimePart *mime_part = CAMEL_MIME_PART (medium); - CamelHeaderType header_type; - const char *charset; - char *text; - - /* Try to parse the header pair. If it corresponds to something */ - /* known, the job is done in the parsing routine. If not, */ - /* we simply add the header in a raw fashion */ - - header_type = (CamelHeaderType) g_hash_table_lookup (header_name_table, name); - switch (header_type) { - case HEADER_DESCRIPTION: /* raw header->utf8 conversion */ - g_free (mime_part->description); - if (((CamelDataWrapper *) mime_part)->mime_type) { - charset = camel_content_type_param (((CamelDataWrapper *) mime_part)->mime_type, "charset"); - charset = e_iconv_charset_name (charset); - } else - charset = NULL; - mime_part->description = g_strstrip (camel_header_decode_string (value, charset)); - break; - case HEADER_DISPOSITION: - set_disposition (mime_part, value); - break; - case HEADER_CONTENT_ID: - g_free (mime_part->content_id); - mime_part->content_id = camel_header_contentid_decode (value); - break; - case HEADER_ENCODING: - text = camel_header_token_decode (value); - mime_part->encoding = camel_transfer_encoding_from_string (text); - g_free (text); - break; - case HEADER_CONTENT_MD5: - g_free (mime_part->content_MD5); - mime_part->content_MD5 = g_strdup (value); - break; - case HEADER_CONTENT_LOCATION: - g_free (mime_part->content_location); - mime_part->content_location = camel_header_location_decode (value); - break; - case HEADER_CONTENT_TYPE: - if (((CamelDataWrapper *) mime_part)->mime_type) - camel_content_type_unref (((CamelDataWrapper *) mime_part)->mime_type); - ((CamelDataWrapper *) mime_part)->mime_type = camel_content_type_decode (value); - break; - default: - return FALSE; - } - return TRUE; -} - -static void -set_header (CamelMedium *medium, const char *name, const void *value) -{ - CamelMimePart *part = CAMEL_MIME_PART (medium); - - process_header(medium, name, value); - camel_header_raw_replace(&part->headers, name, value, -1); -} - -static void -add_header (CamelMedium *medium, const char *name, const void *value) -{ - CamelMimePart *part = CAMEL_MIME_PART (medium); - - /* Try to parse the header pair. If it corresponds to something */ - /* known, the job is done in the parsing routine. If not, */ - /* we simply add the header in a raw fashion */ - - /* If it was one of the headers we handled, it must be unique, set it instead of add */ - if (process_header(medium, name, value)) - camel_header_raw_replace(&part->headers, name, value, -1); - else - camel_header_raw_append(&part->headers, name, value, -1); -} - -static void -remove_header (CamelMedium *medium, const char *name) -{ - CamelMimePart *part = (CamelMimePart *)medium; - - process_header(medium, name, NULL); - camel_header_raw_remove(&part->headers, name); -} - -static const void * -get_header (CamelMedium *medium, const char *name) -{ - CamelMimePart *part = (CamelMimePart *)medium; - - return camel_header_raw_find(&part->headers, name, NULL); -} - -static GArray * -get_headers (CamelMedium *medium) -{ - CamelMimePart *part = (CamelMimePart *)medium; - GArray *headers; - CamelMediumHeader header; - struct _camel_header_raw *h; - - headers = g_array_new (FALSE, FALSE, sizeof (CamelMediumHeader)); - for (h = part->headers; h; h = h->next) { - header.name = h->name; - header.value = h->value; - g_array_append_val (headers, header); - } - - return headers; -} - -static void -free_headers (CamelMedium *medium, GArray *gheaders) -{ - g_array_free (gheaders, TRUE); -} - -/* **** Content-Description */ -void -camel_mime_part_set_description (CamelMimePart *mime_part, const char *description) -{ - char *text = camel_header_encode_string (description); - - camel_medium_set_header (CAMEL_MEDIUM (mime_part), - "Content-Description", text); - g_free (text); -} - -const char * -camel_mime_part_get_description (CamelMimePart *mime_part) -{ - return mime_part->description; -} - -/* **** Content-Disposition */ - -static void -set_disposition (CamelMimePart *mime_part, const char *disposition) -{ - camel_content_disposition_unref(mime_part->disposition); - if (disposition) - mime_part->disposition = camel_content_disposition_decode(disposition); - else - mime_part->disposition = NULL; -} - - -void -camel_mime_part_set_disposition (CamelMimePart *mime_part, const char *disposition) -{ - char *text; - - /* we poke in a new disposition (so we dont lose 'filename', etc) */ - if (mime_part->disposition == NULL) { - set_disposition(mime_part, disposition); - } - if (mime_part->disposition != NULL) { - g_free(mime_part->disposition->disposition); - mime_part->disposition->disposition = g_strdup(disposition); - } - text = camel_content_disposition_format(mime_part->disposition); - - camel_medium_set_header (CAMEL_MEDIUM (mime_part), - "Content-Disposition", text); - - g_free(text); -} - -const char * -camel_mime_part_get_disposition (CamelMimePart *mime_part) -{ - if (mime_part->disposition) - return (mime_part->disposition)->disposition; - else - return NULL; -} - - -/* **** Content-Disposition: filename="xxx" */ - -void -camel_mime_part_set_filename (CamelMimePart *mime_part, const char *filename) -{ - char *str; - - if (mime_part->disposition == NULL) - mime_part->disposition = camel_content_disposition_decode("attachment"); - - camel_header_set_param(&mime_part->disposition->params, "filename", filename); - str = camel_content_disposition_format(mime_part->disposition); - - camel_medium_set_header (CAMEL_MEDIUM (mime_part), - "Content-Disposition", str); - g_free(str); - - camel_content_type_set_param (((CamelDataWrapper *) mime_part)->mime_type, "name", filename); - str = camel_content_type_format (((CamelDataWrapper *) mime_part)->mime_type); - camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-Type", str); - g_free (str); -} - -const char * -camel_mime_part_get_filename (CamelMimePart *mime_part) -{ - if (mime_part->disposition) { - const char *name = camel_header_param (mime_part->disposition->params, "filename"); - if (name) - return name; - } - - return camel_content_type_param (((CamelDataWrapper *) mime_part)->mime_type, "name"); -} - - -/* **** Content-ID: */ - -void -camel_mime_part_set_content_id (CamelMimePart *mime_part, const char *contentid) -{ - char *cid, *id; - - if (contentid) - id = g_strstrip (g_strdup (contentid)); - else - id = camel_header_msgid_generate (); - - cid = g_strdup_printf ("<%s>", id); - g_free (id); - camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-ID", cid); - g_free (cid); -} - -const char * -camel_mime_part_get_content_id (CamelMimePart *mime_part) -{ - return mime_part->content_id; -} - -/* **** Content-MD5: */ - -void -camel_mime_part_set_content_MD5 (CamelMimePart *mime_part, const char *md5) -{ - camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-MD5", md5); -} - -const char * -camel_mime_part_get_content_MD5 (CamelMimePart *mime_part) -{ - return mime_part->content_MD5; -} - -/* **** Content-MD5: */ - -void -camel_mime_part_set_content_location (CamelMimePart *mime_part, const char *location) -{ - camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-Location", location); -} - -const char * -camel_mime_part_get_content_location (CamelMimePart *mime_part) -{ - return mime_part->content_location; -} - -/* **** Content-Transfer-Encoding: */ - -void -camel_mime_part_set_encoding (CamelMimePart *mime_part, - CamelTransferEncoding encoding) -{ - const char *text; - - text = camel_transfer_encoding_to_string (encoding); - camel_medium_set_header (CAMEL_MEDIUM (mime_part), - "Content-Transfer-Encoding", text); -} - -CamelTransferEncoding -camel_mime_part_get_encoding (CamelMimePart *mime_part) -{ - return mime_part->encoding; -} - -/* FIXME: do something with this stuff ... */ - -void -camel_mime_part_set_content_languages (CamelMimePart *mime_part, GList *content_languages) -{ - if (mime_part->content_languages) - camel_string_list_free (mime_part->content_languages); - - mime_part->content_languages = content_languages; - - /* FIXME: translate to a header and set it */ -} - -const GList * -camel_mime_part_get_content_languages (CamelMimePart *mime_part) -{ - return mime_part->content_languages; -} - - -/* **** */ - -/* **** Content-Type: */ - -void -camel_mime_part_set_content_type (CamelMimePart *mime_part, const char *content_type) -{ - camel_medium_set_header (CAMEL_MEDIUM (mime_part), - "Content-Type", content_type); -} - -CamelContentType * -camel_mime_part_get_content_type (CamelMimePart *mime_part) -{ - return ((CamelDataWrapper *) mime_part)->mime_type; -} - - -static void -set_content_object (CamelMedium *medium, CamelDataWrapper *content) -{ - CamelDataWrapper *mime_part = CAMEL_DATA_WRAPPER (medium); - CamelContentType *content_type; - - parent_class->set_content_object (medium, content); - - content_type = camel_data_wrapper_get_mime_type_field (content); - if (mime_part->mime_type != content_type) { - char *txt; - - txt = camel_content_type_format (content_type); - camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-Type", txt); - g_free (txt); - } -} - -/**********************************************************************/ - -static ssize_t -write_references(CamelStream *stream, struct _camel_header_raw *h) -{ - ssize_t len, out, total; - char *v, *ids, *ide; - - /* this is only approximate, based on the next >, this way it retains any content - from the original which may not be properly formatted, etc. It also doesn't handle - the case where an individual messageid is too long, however thats a bad mail to - start with ... */ - - v = h->value; - len = strlen(h->name)+1; - total = camel_stream_printf(stream, "%s%s", h->name, isspace(v[0])?":":": "); - if (total == -1) - return -1; - while (*v) { - ids = v; - ide = strchr(ids+1, '>'); - if (ide) - v = ++ide; - else - ide = v = strlen(ids)+ids; - - if (len>0 && len + (ide - ids) >= CAMEL_FOLD_SIZE) { - out = camel_stream_printf(stream, "\n\t"); - if (out == -1) - return -1; - total += out; - len = 0; - } - out = camel_stream_write(stream, ids, ide-ids); - if (out == -1) - return -1; - len += out; - total += out; - } - camel_stream_write(stream, "\n", 1); - - return total; -} - -#if 0 -/* not needed - yet - handled by default case */ -static ssize_t -write_fold(CamelStream *stream, struct _camel_header_raw *h) -{ - char *val; - int count; - - val = camel_header_fold(h->value, strlen(h->name)); - count = camel_stream_printf(stream, "%s%s%s\n", h->name, isspace(val[0]) ? ":" : ": ", val); - g_free(val); - - return count; -} -#endif - -static ssize_t -write_raw(CamelStream *stream, struct _camel_header_raw *h) -{ - char *val = h->value; - - return camel_stream_printf(stream, "%s%s%s\n", h->name, isspace(val[0]) ? ":" : ": ", val); -} - -static ssize_t -write_to_stream (CamelDataWrapper *dw, CamelStream *stream) -{ - CamelMimePart *mp = CAMEL_MIME_PART (dw); - CamelMedium *medium = CAMEL_MEDIUM (dw); - CamelStream *ostream = stream; - CamelDataWrapper *content; - ssize_t total = 0; - ssize_t count; - int errnosav; - - d(printf("mime_part::write_to_stream\n")); - - /* FIXME: something needs to be done about this ... */ - /* TODO: content-languages header? */ - - if (mp->headers) { - struct _camel_header_raw *h = mp->headers; - char *val; - ssize_t (*writefn)(CamelStream *stream, struct _camel_header_raw *); - - /* fold/write the headers. But dont fold headers that are already formatted - (e.g. ones with parameter-lists, that we know about, and have created) */ - while (h) { - val = h->value; - if (val == NULL) { - g_warning("h->value is NULL here for %s", h->name); - count = 0; - } else if ((writefn = g_hash_table_lookup(header_formatted_table, h->name)) == NULL) { - val = camel_header_fold(val, strlen(h->name)); - count = camel_stream_printf(stream, "%s%s%s\n", h->name, isspace(val[0]) ? ":" : ": ", val); - g_free(val); - } else { - count = writefn(stream, h); - } - if (count == -1) - return -1; - total += count; - h = h->next; - } - } - - count = camel_stream_write(stream, "\n", 1); - if (count == -1) - return -1; - total += count; - - content = camel_medium_get_content_object(medium); - if (content) { - CamelMimeFilter *filter = NULL; - CamelStreamFilter *filter_stream = NULL; - CamelMimeFilter *charenc = NULL; - const char *content_charset = NULL; - const char *part_charset = NULL; - gboolean reencode = FALSE; - const char *filename; - - if (camel_content_type_is (dw->mime_type, "text", "*")) { - content_charset = camel_content_type_param (content->mime_type, "charset"); - part_charset = camel_content_type_param (dw->mime_type, "charset"); - - if (content_charset && part_charset) { - content_charset = e_iconv_charset_name (content_charset); - part_charset = e_iconv_charset_name (part_charset); - } - } - - if (mp->encoding != content->encoding) { - switch (mp->encoding) { - case CAMEL_TRANSFER_ENCODING_BASE64: - filter = (CamelMimeFilter *) camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_BASE64_ENC); - break; - case CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE: - filter = (CamelMimeFilter *) camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_QP_ENC); - break; - case CAMEL_TRANSFER_ENCODING_UUENCODE: - filename = camel_mime_part_get_filename (mp); - count = camel_stream_printf (ostream, "begin 644 %s\n", filename ? filename : "untitled"); - if (count == -1) - return -1; - total += count; - filter = (CamelMimeFilter *) camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_UU_ENC); - break; - default: - /* content is encoded but the part doesn't want to be... */ - reencode = TRUE; - break; - } - } - - if (content_charset && part_charset && part_charset != content_charset) - charenc = (CamelMimeFilter *) camel_mime_filter_charset_new_convert (content_charset, part_charset); - - if (filter || charenc) { - filter_stream = camel_stream_filter_new_with_stream(stream); - - /* if we have a character encoder, add that always */ - if (charenc) { - camel_stream_filter_add(filter_stream, charenc); - camel_object_unref (charenc); - } - - /* we only re-do crlf on encoded blocks */ - if (filter && camel_content_type_is (dw->mime_type, "text", "*")) { - CamelMimeFilter *crlf = camel_mime_filter_crlf_new(CAMEL_MIME_FILTER_CRLF_ENCODE, - CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - - camel_stream_filter_add(filter_stream, crlf); - camel_object_unref (crlf); - } - - if (filter) { - camel_stream_filter_add(filter_stream, filter); - camel_object_unref (filter); - } - - stream = (CamelStream *)filter_stream; - - reencode = TRUE; - } - - if (reencode) - count = camel_data_wrapper_decode_to_stream (content, stream); - else - count = camel_data_wrapper_write_to_stream (content, stream); - - if (filter_stream) { - errnosav = errno; - camel_stream_flush (stream); - camel_object_unref (filter_stream); - errno = errnosav; - } - - if (count == -1) - return -1; - - total += count; - - if (reencode && mp->encoding == CAMEL_TRANSFER_ENCODING_UUENCODE) { - count = camel_stream_write (ostream, "end\n", 4); - if (count == -1) - return -1; - total += count; - } - } else { - g_warning("No content for medium, nothing to write"); - } - - return total; -} - -/* mime_part */ -static int -construct_from_parser (CamelMimePart *mime_part, CamelMimeParser *mp) -{ - CamelDataWrapper *dw = (CamelDataWrapper *) mime_part; - struct _camel_header_raw *headers; - const char *content; - char *buf; - size_t len; - int err; - - d(printf("mime_part::construct_from_parser()\n")); - - switch (camel_mime_parser_step(mp, &buf, &len)) { - case CAMEL_MIME_PARSER_STATE_MESSAGE: - /* set the default type of a message always */ - if (dw->mime_type) - camel_content_type_unref (dw->mime_type); - dw->mime_type = camel_content_type_decode ("message/rfc822"); - case CAMEL_MIME_PARSER_STATE_HEADER: - case CAMEL_MIME_PARSER_STATE_MULTIPART: - /* we have the headers, build them into 'us' */ - headers = camel_mime_parser_headers_raw(mp); - - /* if content-type exists, process it first, set for fallback charset in headers */ - content = camel_header_raw_find(&headers, "content-type", NULL); - if (content) - process_header((CamelMedium *)dw, "content-type", content); - - while (headers) { - if (strcasecmp(headers->name, "content-type") == 0 - && headers->value != content) - camel_medium_add_header((CamelMedium *)dw, "X-Invalid-Content-Type", headers->value); - else - camel_medium_add_header((CamelMedium *)dw, headers->name, headers->value); - headers = headers->next; - } - - camel_mime_part_construct_content_from_parser (mime_part, mp); - break; - default: - g_warning("Invalid state encountered???: %d", camel_mime_parser_state(mp)); - } - - d(printf("mime_part::construct_from_parser() leaving\n")); - err = camel_mime_parser_errno(mp); - if (err != 0) { - errno = err; - return -1; - } - - return 0; -} - -/** - * camel_mime_part_construct_from_parser: - * @mime_part: - * @mp: - * - * - * - * Return value: - **/ -int -camel_mime_part_construct_from_parser(CamelMimePart *mime_part, CamelMimeParser *mp) -{ - return CMP_CLASS (mime_part)->construct_from_parser (mime_part, mp); -} - -static int -construct_from_stream(CamelDataWrapper *dw, CamelStream *s) -{ - CamelMimeParser *mp; - int ret; - - d(printf("mime_part::construct_from_stream()\n")); - - mp = camel_mime_parser_new(); - if (camel_mime_parser_init_with_stream(mp, s) == -1) { - g_warning("Cannot create parser for stream"); - ret = -1; - } else { - ret = camel_mime_part_construct_from_parser((CamelMimePart *)dw, mp); - } - camel_object_unref((CamelObject *)mp); - return ret; -} - -/******************************/ -/** Misc utility functions **/ - -/** - * camel_mime_part_new: - * - * Return value: a new CamelMimePart - **/ -CamelMimePart * -camel_mime_part_new (void) -{ - return (CamelMimePart *)camel_object_new (CAMEL_MIME_PART_TYPE); -} - -/** - * camel_mime_part_set_content: - * @camel_mime_part: Mime part - * @data: data to put into the part - * @length: length of @data - * @type: Content-Type of the data - * - * Utility function used to set the content of a mime part object to - * be the provided data. If @length is 0, this routine can be used as - * a way to remove old content (in which case @data and @type are - * ignored and may be %NULL). - **/ -void -camel_mime_part_set_content (CamelMimePart *camel_mime_part, - const char *data, int length, - const char *type) /* why on earth is the type last? */ -{ - CamelMedium *medium = CAMEL_MEDIUM (camel_mime_part); - - if (length) { - CamelDataWrapper *dw; - CamelStream *stream; - - dw = camel_data_wrapper_new (); - camel_data_wrapper_set_mime_type (dw, type); - stream = camel_stream_mem_new_with_buffer (data, length); - camel_data_wrapper_construct_from_stream (dw, stream); - camel_object_unref (stream); - camel_medium_set_content_object (medium, dw); - camel_object_unref (dw); - } else { - if (medium->content) - camel_object_unref (medium->content); - medium->content = NULL; - } -} diff --git a/camel/camel-mime-part.h b/camel/camel-mime-part.h deleted file mode 100644 index 2e7ea48a9c..0000000000 --- a/camel/camel-mime-part.h +++ /dev/null @@ -1,115 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* camel-mime-part.h : class for a mime part */ - -/* - * - * Authors: Bertrand Guiheneuf - * Michael Zucchi - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_MIME_PART_H -#define CAMEL_MIME_PART_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include -#include - -#define CAMEL_MIME_PART_TYPE (camel_mime_part_get_type ()) -#define CAMEL_MIME_PART(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MIME_PART_TYPE, CamelMimePart)) -#define CAMEL_MIME_PART_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MIME_PART_TYPE, CamelMimePartClass)) -#define CAMEL_IS_MIME_PART(o) (CAMEL_CHECK_TYPE((o), CAMEL_MIME_PART_TYPE)) - -/* Do not change these values directly, you would regret it one day */ -struct _CamelMimePart { - CamelMedium parent_object; - - struct _camel_header_raw *headers; /* mime headers */ - - /* All fields here are -** PRIVATE **- */ - /* TODO: these should be in a camelcontentinfo */ - char *description; - CamelContentDisposition *disposition; - char *content_id; - char *content_MD5; - char *content_location; - GList *content_languages; - CamelTransferEncoding encoding; -}; - -typedef struct _CamelMimePartClass { - CamelMediumClass parent_class; - - /* Virtual methods */ - int (*construct_from_parser) (CamelMimePart *, CamelMimeParser *); -} CamelMimePartClass; - -/* Standard Camel function */ -CamelType camel_mime_part_get_type (void); - -/* public methods */ -CamelMimePart * camel_mime_part_new (void); - -void camel_mime_part_set_description (CamelMimePart *mime_part, const char *description); -const char *camel_mime_part_get_description (CamelMimePart *mime_part); - -void camel_mime_part_set_disposition (CamelMimePart *mime_part, const char *disposition); -const char *camel_mime_part_get_disposition (CamelMimePart *mime_part); - -void camel_mime_part_set_filename (CamelMimePart *mime_part, const char *filename); -const char *camel_mime_part_get_filename (CamelMimePart *mime_part); - -void camel_mime_part_set_content_id (CamelMimePart *mime_part, const char *contentid); -const char *camel_mime_part_get_content_id (CamelMimePart *mime_part); - -void camel_mime_part_set_content_MD5 (CamelMimePart *mime_part, const char *); -const char *camel_mime_part_get_content_MD5 (CamelMimePart *mime_part); - -void camel_mime_part_set_content_location (CamelMimePart *mime_part, const char *); -const char *camel_mime_part_get_content_location (CamelMimePart *mime_part); - -void camel_mime_part_set_encoding (CamelMimePart *mime_part, CamelTransferEncoding type); -CamelTransferEncoding camel_mime_part_get_encoding (CamelMimePart *mime_part); - -void camel_mime_part_set_content_languages (CamelMimePart *mime_part, GList *content_languages); -const GList *camel_mime_part_get_content_languages (CamelMimePart *mime_part); - -/* FIXME: what about content-type parameters? what about major/minor parts? */ -void camel_mime_part_set_content_type (CamelMimePart *mime_part, const char *content_type); -CamelContentType *camel_mime_part_get_content_type (CamelMimePart *mime_part); - -/* construction */ -int camel_mime_part_construct_from_parser (CamelMimePart *, CamelMimeParser *); - -/* utility functions */ -void camel_mime_part_set_content (CamelMimePart *camel_mime_part, - const char *content, int length, const char *type); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_MIME_PART_H */ - diff --git a/camel/camel-mime-utils.c b/camel/camel-mime-utils.c deleted file mode 100644 index 88a7c2ad9b..0000000000 --- a/camel/camel-mime-utils.c +++ /dev/null @@ -1,4346 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000-2003 Ximian Inc. - * - * Authors: Michael Zucchi - * Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* dont touch this file without my permission - Michael */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include /* for MAXHOSTNAMELEN */ -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 1024 -#endif - -#include -#include -#include - -#include "camel-mime-utils.h" -#include "camel-charset-map.h" -#include "camel-service.h" /* for camel_gethostbyname() */ - -#ifndef CLEAN_DATE -#include "broken-date-parser.h" -#endif - -#if 0 -int strdup_count = 0; -int malloc_count = 0; -int free_count = 0; - -#define g_strdup(x) (strdup_count++, g_strdup(x)) -#define g_malloc(x) (malloc_count++, g_malloc(x)) -#define g_free(x) (free_count++, g_free(x)) -#endif - -/* for all non-essential warnings ... */ -#define w(x) - -#define d(x) -#define d2(x) - -#define CAMEL_UUENCODE_CHAR(c) ((c) ? (c) + ' ' : '`') -#define CAMEL_UUDECODE_CHAR(c) (((c) - ' ') & 077) - -static char *base64_alphabet = -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -static unsigned char tohex[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; - -unsigned short camel_mime_special_table[256]; -static unsigned char camel_mime_base64_rank[256]; - -/* Used by table initialisation code for special characters */ -#define CHARS_LWSP " \t\n\r" -#define CHARS_TSPECIAL "()<>@,;:\\\"/[]?=" -#define CHARS_SPECIAL "()<>@,;:\\\".[]" -#define CHARS_CSPECIAL "()\\\r" /* not in comments */ -#define CHARS_DSPECIAL "[]\\\r \t" /* not in domains */ -#define CHARS_ESPECIAL "()<>@,;:\"/[]?.=_" /* list of characters that must be encoded. - encoded word in text specials: rfc 2047 5(1)*/ -#define CHARS_PSPECIAL "!*+-/" /* list of additional characters that can be left unencoded. - encoded word in phrase specials: rfc 2047 5(3) */ - -static void -header_remove_bits(unsigned short bit, unsigned char *vals) -{ - int i; - - for (i=0;vals[i];i++) - camel_mime_special_table[vals[i]] &= ~ bit; -} - -static void -header_init_bits(unsigned short bit, unsigned short bitcopy, int remove, unsigned char *vals) -{ - int i; - int len = strlen(vals); - - if (!remove) { - for (i=0;i=32 && i<=60) || (i>=62 && i<=126) || i==9) - camel_mime_special_table[i] |= (CAMEL_MIME_IS_QPSAFE|CAMEL_MIME_IS_ESAFE); - if ((i>='0' && i<='9') || (i>='a' && i<='z') || (i>='A' && i<= 'Z')) - camel_mime_special_table[i] |= CAMEL_MIME_IS_PSAFE; - } - camel_mime_special_table[127] |= CAMEL_MIME_IS_CTRL; - camel_mime_special_table[' '] |= CAMEL_MIME_IS_SPACE; - header_init_bits(CAMEL_MIME_IS_LWSP, 0, 0, CHARS_LWSP); - header_init_bits(CAMEL_MIME_IS_TSPECIAL, CAMEL_MIME_IS_CTRL, 0, CHARS_TSPECIAL); - header_init_bits(CAMEL_MIME_IS_SPECIAL, 0, 0, CHARS_SPECIAL); - header_init_bits(CAMEL_MIME_IS_DSPECIAL, 0, FALSE, CHARS_DSPECIAL); - header_remove_bits(CAMEL_MIME_IS_ESAFE, CHARS_ESPECIAL); - header_init_bits(CAMEL_MIME_IS_PSAFE, 0, 0, CHARS_PSPECIAL); -} - -static void -base64_init(void) -{ - int i; - - memset(camel_mime_base64_rank, 0xff, sizeof(camel_mime_base64_rank)); - for (i=0;i<64;i++) { - camel_mime_base64_rank[(unsigned int)base64_alphabet[i]] = i; - } - camel_mime_base64_rank['='] = 0; -} - -/* call this when finished encoding everything, to - flush off the last little bit */ -size_t -camel_base64_encode_close(unsigned char *in, size_t inlen, gboolean break_lines, unsigned char *out, int *state, int *save) -{ - int c1, c2; - unsigned char *outptr = out; - - if (inlen>0) - outptr += camel_base64_encode_step(in, inlen, break_lines, outptr, state, save); - - c1 = ((unsigned char *)save)[1]; - c2 = ((unsigned char *)save)[2]; - - d(printf("mode = %d\nc1 = %c\nc2 = %c\n", - (int)((char *)save)[0], - (int)((char *)save)[1], - (int)((char *)save)[2])); - - switch (((char *)save)[0]) { - case 2: - outptr[2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ]; - g_assert(outptr[2] != 0); - goto skip; - case 1: - outptr[2] = '='; - skip: - outptr[0] = base64_alphabet[ c1 >> 2 ]; - outptr[1] = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 )]; - outptr[3] = '='; - outptr += 4; - break; - } - if (break_lines) - *outptr++ = '\n'; - - *save = 0; - *state = 0; - - return outptr-out; -} - -/* - performs an 'encode step', only encodes blocks of 3 characters to the - output at a time, saves left-over state in state and save (initialise to - 0 on first invocation). -*/ -size_t -camel_base64_encode_step(unsigned char *in, size_t len, gboolean break_lines, unsigned char *out, int *state, int *save) -{ - register unsigned char *inptr, *outptr; - - if (len<=0) - return 0; - - inptr = in; - outptr = out; - - d(printf("we have %d chars, and %d saved chars\n", len, ((char *)save)[0])); - - if (len + ((char *)save)[0] > 2) { - unsigned char *inend = in+len-2; - register int c1, c2, c3; - register int already; - - already = *state; - - switch (((char *)save)[0]) { - case 1: c1 = ((unsigned char *)save)[1]; goto skip1; - case 2: c1 = ((unsigned char *)save)[1]; - c2 = ((unsigned char *)save)[2]; goto skip2; - } - - /* yes, we jump into the loop, no i'm not going to change it, it's beautiful! */ - while (inptr < inend) { - c1 = *inptr++; - skip1: - c2 = *inptr++; - skip2: - c3 = *inptr++; - *outptr++ = base64_alphabet[ c1 >> 2 ]; - *outptr++ = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 ) ]; - *outptr++ = base64_alphabet[ ( (c2 &0x0f) << 2 ) | (c3 >> 6) ]; - *outptr++ = base64_alphabet[ c3 & 0x3f ]; - /* this is a bit ugly ... */ - if (break_lines && (++already)>=19) { - *outptr++='\n'; - already = 0; - } - } - - ((char *)save)[0] = 0; - len = 2-(inptr-inend); - *state = already; - } - - d(printf("state = %d, len = %d\n", - (int)((char *)save)[0], - len)); - - if (len>0) { - register char *saveout; - - /* points to the slot for the next char to save */ - saveout = & (((char *)save)[1]) + ((char *)save)[0]; - - /* len can only be 0 1 or 2 */ - switch(len) { - case 2: *saveout++ = *inptr++; - case 1: *saveout++ = *inptr++; - } - ((char *)save)[0]+=len; - } - - d(printf("mode = %d\nc1 = %c\nc2 = %c\n", - (int)((char *)save)[0], - (int)((char *)save)[1], - (int)((char *)save)[2])); - - return outptr-out; -} - - -/** - * camel_base64_decode_step: decode a chunk of base64 encoded data - * @in: input stream - * @len: max length of data to decode - * @out: output stream - * @state: holds the number of bits that are stored in @save - * @save: leftover bits that have not yet been decoded - * - * Decodes a chunk of base64 encoded data - **/ -size_t -camel_base64_decode_step(unsigned char *in, size_t len, unsigned char *out, int *state, unsigned int *save) -{ - register unsigned char *inptr, *outptr; - unsigned char *inend, c; - register unsigned int v; - int i; - - inend = in+len; - outptr = out; - - /* convert 4 base64 bytes to 3 normal bytes */ - v=*save; - i=*state; - inptr = in; - while (inptr>16; - *outptr++ = v>>8; - *outptr++ = v; - i=0; - } - } - } - - *save = v; - *state = i; - - /* quick scan back for '=' on the end somewhere */ - /* fortunately we can drop 1 output char for each trailing = (upto 2) */ - i=2; - while (inptr>in && i) { - inptr--; - if (camel_mime_base64_rank[*inptr] != 0xff) { - if (*inptr == '=' && outptr>out) - outptr--; - i--; - } - } - - /* if i!= 0 then there is a truncation error! */ - return outptr-out; -} - -char * -camel_base64_encode_simple (const char *data, size_t len) -{ - unsigned char *out; - int state = 0, outlen; - unsigned int save = 0; - - out = g_malloc (len * 4 / 3 + 5); - outlen = camel_base64_encode_close ((unsigned char *)data, len, FALSE, - out, &state, &save); - out[outlen] = '\0'; - return (char *)out; -} - -size_t -camel_base64_decode_simple (char *data, size_t len) -{ - int state = 0; - unsigned int save = 0; - - return camel_base64_decode_step ((unsigned char *)data, len, - (unsigned char *)data, &state, &save); -} - -/** - * camel_uuencode_close: uuencode a chunk of data - * @in: input stream - * @len: input stream length - * @out: output stream - * @uubuf: temporary buffer of 60 bytes - * @state: holds the number of bits that are stored in @save - * @save: leftover bits that have not yet been encoded - * - * Returns the number of bytes encoded. Call this when finished - * encoding data with camel_uuencode_step to flush off the last little - * bit. - **/ -size_t -camel_uuencode_close (unsigned char *in, size_t len, unsigned char *out, unsigned char *uubuf, int *state, guint32 *save) -{ - register unsigned char *outptr, *bufptr; - register guint32 saved; - int uulen, uufill, i; - - outptr = out; - - if (len > 0) - outptr += camel_uuencode_step (in, len, out, uubuf, state, save); - - uufill = 0; - - saved = *save; - i = *state & 0xff; - uulen = (*state >> 8) & 0xff; - - bufptr = uubuf + ((uulen / 3) * 4); - - if (i > 0) { - while (i < 3) { - saved <<= 8 | 0; - uufill++; - i++; - } - - if (i == 3) { - /* convert 3 normal bytes into 4 uuencoded bytes */ - unsigned char b0, b1, b2; - - b0 = saved >> 16; - b1 = saved >> 8 & 0xff; - b2 = saved & 0xff; - - *bufptr++ = CAMEL_UUENCODE_CHAR ((b0 >> 2) & 0x3f); - *bufptr++ = CAMEL_UUENCODE_CHAR (((b0 << 4) | ((b1 >> 4) & 0xf)) & 0x3f); - *bufptr++ = CAMEL_UUENCODE_CHAR (((b1 << 2) | ((b2 >> 6) & 0x3)) & 0x3f); - *bufptr++ = CAMEL_UUENCODE_CHAR (b2 & 0x3f); - - i = 0; - saved = 0; - uulen += 3; - } - } - - if (uulen > 0) { - int cplen = ((uulen / 3) * 4); - - *outptr++ = CAMEL_UUENCODE_CHAR ((uulen - uufill) & 0xff); - memcpy (outptr, uubuf, cplen); - outptr += cplen; - *outptr++ = '\n'; - uulen = 0; - } - - *outptr++ = CAMEL_UUENCODE_CHAR (uulen & 0xff); - *outptr++ = '\n'; - - *save = 0; - *state = 0; - - return outptr - out; -} - - -/** - * camel_uuencode_step: uuencode a chunk of data - * @in: input stream - * @len: input stream length - * @out: output stream - * @uubuf: temporary buffer of 60 bytes - * @state: holds the number of bits that are stored in @save - * @save: leftover bits that have not yet been encoded - * - * Returns the number of bytes encoded. Performs an 'encode step', - * only encodes blocks of 45 characters to the output at a time, saves - * left-over state in @uubuf, @state and @save (initialize to 0 on first - * invocation). - **/ -size_t -camel_uuencode_step (unsigned char *in, size_t len, unsigned char *out, unsigned char *uubuf, int *state, guint32 *save) -{ - register unsigned char *inptr, *outptr, *bufptr; - unsigned char *inend; - register guint32 saved; - int uulen, i; - - saved = *save; - i = *state & 0xff; - uulen = (*state >> 8) & 0xff; - - inptr = in; - inend = in + len; - - outptr = out; - - bufptr = uubuf + ((uulen / 3) * 4); - - while (inptr < inend) { - while (uulen < 45 && inptr < inend) { - while (i < 3 && inptr < inend) { - saved = (saved << 8) | *inptr++; - i++; - } - - if (i == 3) { - /* convert 3 normal bytes into 4 uuencoded bytes */ - unsigned char b0, b1, b2; - - b0 = saved >> 16; - b1 = saved >> 8 & 0xff; - b2 = saved & 0xff; - - *bufptr++ = CAMEL_UUENCODE_CHAR ((b0 >> 2) & 0x3f); - *bufptr++ = CAMEL_UUENCODE_CHAR (((b0 << 4) | ((b1 >> 4) & 0xf)) & 0x3f); - *bufptr++ = CAMEL_UUENCODE_CHAR (((b1 << 2) | ((b2 >> 6) & 0x3)) & 0x3f); - *bufptr++ = CAMEL_UUENCODE_CHAR (b2 & 0x3f); - - i = 0; - saved = 0; - uulen += 3; - } - } - - if (uulen >= 45) { - *outptr++ = CAMEL_UUENCODE_CHAR (uulen & 0xff); - memcpy (outptr, uubuf, ((uulen / 3) * 4)); - outptr += ((uulen / 3) * 4); - *outptr++ = '\n'; - uulen = 0; - bufptr = uubuf; - } - } - - *save = saved; - *state = ((uulen & 0xff) << 8) | (i & 0xff); - - return outptr - out; -} - - -/** - * camel_uudecode_step: uudecode a chunk of data - * @in: input stream - * @inlen: max length of data to decode ( normally strlen(in) ??) - * @out: output stream - * @state: holds the number of bits that are stored in @save - * @save: leftover bits that have not yet been decoded - * - * Returns the number of bytes decoded. Performs a 'decode step' on - * a chunk of uuencoded data. Assumes the "begin " - * line has been stripped off. - **/ -size_t -camel_uudecode_step (unsigned char *in, size_t len, unsigned char *out, int *state, guint32 *save) -{ - register unsigned char *inptr, *outptr; - unsigned char *inend, ch; - register guint32 saved; - gboolean last_was_eoln; - int uulen, i; - - if (*state & CAMEL_UUDECODE_STATE_END) - return 0; - - saved = *save; - i = *state & 0xff; - uulen = (*state >> 8) & 0xff; - if (uulen == 0) - last_was_eoln = TRUE; - else - last_was_eoln = FALSE; - - inend = in + len; - outptr = out; - - inptr = in; - while (inptr < inend) { - if (*inptr == '\n' || last_was_eoln) { - if (last_was_eoln && *inptr != '\n') { - uulen = CAMEL_UUDECODE_CHAR (*inptr); - last_was_eoln = FALSE; - if (uulen == 0) { - *state |= CAMEL_UUDECODE_STATE_END; - break; - } - } else { - last_was_eoln = TRUE; - } - - inptr++; - continue; - } - - ch = *inptr++; - - if (uulen > 0) { - /* save the byte */ - saved = (saved << 8) | ch; - i++; - if (i == 4) { - /* convert 4 uuencoded bytes to 3 normal bytes */ - unsigned char b0, b1, b2, b3; - - b0 = saved >> 24; - b1 = saved >> 16 & 0xff; - b2 = saved >> 8 & 0xff; - b3 = saved & 0xff; - - if (uulen >= 3) { - *outptr++ = CAMEL_UUDECODE_CHAR (b0) << 2 | CAMEL_UUDECODE_CHAR (b1) >> 4; - *outptr++ = CAMEL_UUDECODE_CHAR (b1) << 4 | CAMEL_UUDECODE_CHAR (b2) >> 2; - *outptr++ = CAMEL_UUDECODE_CHAR (b2) << 6 | CAMEL_UUDECODE_CHAR (b3); - } else { - if (uulen >= 1) { - *outptr++ = CAMEL_UUDECODE_CHAR (b0) << 2 | CAMEL_UUDECODE_CHAR (b1) >> 4; - } - if (uulen >= 2) { - *outptr++ = CAMEL_UUDECODE_CHAR (b1) << 4 | CAMEL_UUDECODE_CHAR (b2) >> 2; - } - } - - i = 0; - saved = 0; - uulen -= 3; - } - } else { - break; - } - } - - *save = saved; - *state = (*state & CAMEL_UUDECODE_STATE_MASK) | ((uulen & 0xff) << 8) | (i & 0xff); - - return outptr - out; -} - - -/* complete qp encoding */ -size_t -camel_quoted_decode_close(unsigned char *in, size_t len, unsigned char *out, int *state, int *save) -{ - register unsigned char *outptr = out; - int last; - - if (len>0) - outptr += camel_quoted_encode_step(in, len, outptr, state, save); - - last = *state; - if (last != -1) { - /* space/tab must be encoded if it's the last character on - the line */ - if (camel_mime_is_qpsafe(last) && last!=' ' && last!=9) { - *outptr++ = last; - } else { - *outptr++ = '='; - *outptr++ = tohex[(last>>4) & 0xf]; - *outptr++ = tohex[last & 0xf]; - } - } - - *save = 0; - *state = -1; - - return outptr-out; -} - -/* perform qp encoding, initialise state to -1 and save to 0 on first invocation */ -size_t -camel_quoted_encode_step (unsigned char *in, size_t len, unsigned char *out, int *statep, int *save) -{ - register guchar *inptr, *outptr, *inend; - unsigned char c; - register int sofar = *save; /* keeps track of how many chars on a line */ - register int last = *statep; /* keeps track if last char to end was a space cr etc */ - - inptr = in; - inend = in + len; - outptr = out; - while (inptr < inend) { - c = *inptr++; - if (c == '\r') { - if (last != -1) { - *outptr++ = '='; - *outptr++ = tohex[(last >> 4) & 0xf]; - *outptr++ = tohex[last & 0xf]; - sofar += 3; - } - last = c; - } else if (c == '\n') { - if (last != -1 && last != '\r') { - *outptr++ = '='; - *outptr++ = tohex[(last >> 4) & 0xf]; - *outptr++ = tohex[last & 0xf]; - } - *outptr++ = '\n'; - sofar = 0; - last = -1; - } else { - if (last != -1) { - if (camel_mime_is_qpsafe(last)) { - *outptr++ = last; - sofar++; - } else { - *outptr++ = '='; - *outptr++ = tohex[(last >> 4) & 0xf]; - *outptr++ = tohex[last & 0xf]; - sofar += 3; - } - } - - if (camel_mime_is_qpsafe(c)) { - if (sofar > 74) { - *outptr++ = '='; - *outptr++ = '\n'; - sofar = 0; - } - - /* delay output of space char */ - if (c==' ' || c=='\t') { - last = c; - } else { - *outptr++ = c; - sofar++; - last = -1; - } - } else { - if (sofar > 72) { - *outptr++ = '='; - *outptr++ = '\n'; - sofar = 3; - } else - sofar += 3; - - *outptr++ = '='; - *outptr++ = tohex[(c >> 4) & 0xf]; - *outptr++ = tohex[c & 0xf]; - last = -1; - } - } - } - *save = sofar; - *statep = last; - - return (outptr - out); -} - -/* - FIXME: this does not strip trailing spaces from lines (as it should, rfc 2045, section 6.7) - Should it also canonicalise the end of line to CR LF?? - - Note: Trailing rubbish (at the end of input), like = or =x or =\r will be lost. -*/ - -size_t -camel_quoted_decode_step(unsigned char *in, size_t len, unsigned char *out, int *savestate, int *saveme) -{ - register unsigned char *inptr, *outptr; - unsigned char *inend, c; - int state, save; - - inend = in+len; - outptr = out; - - d(printf("quoted-printable, decoding text '%.*s'\n", len, in)); - - state = *savestate; - save = *saveme; - inptr = in; - while (inptr='A'?save-'A'+10:save-'0')&0x0f) << 4) - | ((c>='A'?c-'A'+10:c-'0')&0x0f); - } else if (c=='\n' && save == '\r') { - /* soft break ... canonical end of line */ - } else { - /* just output the data */ - *outptr++ = '='; - *outptr++ = save; - *outptr++ = c; - } - state = 0; - break; -#ifdef CANONICALISE_EOL - case 3: - /* convert \r -> to \r\n, leaves \r\n alone */ - c = *inptr++; - if (c=='\n') { - *outptr++ = '\r'; - *outptr++ = c; - } else { - *outptr++ = '\r'; - *outptr++ = '\n'; - *outptr++ = c; - } - state = 0; - break; -#endif - } - } - - *savestate = state; - *saveme = save; - - return outptr-out; -} - -/* - this is for the "Q" encoding of international words, - which is slightly different than plain quoted-printable (mainly by allowing 0x20 <> _) -*/ -static size_t -quoted_decode(const unsigned char *in, size_t len, unsigned char *out) -{ - register const unsigned char *inptr; - register unsigned char *outptr; - unsigned const char *inend; - unsigned char c, c1; - int ret = 0; - - inend = in+len; - outptr = out; - - d(printf("decoding text '%.*s'\n", len, in)); - - inptr = in; - while (inptr=2) { - c = toupper(*inptr++); - c1 = toupper(*inptr++); - *outptr++ = (((c>='A'?c-'A'+10:c-'0')&0x0f) << 4) - | ((c1>='A'?c1-'A'+10:c1-'0')&0x0f); - } else { - ret = -1; - break; - } - } else if (c=='_') { - *outptr++ = 0x20; - } else if (c==' ' || c==0x09) { - /* FIXME: this is an error! ignore for now ... */ - ret = -1; - break; - } else { - *outptr++ = c; - } - } - if (ret==0) { - return outptr-out; - } - return 0; -} - -/* rfc2047 version of quoted-printable */ -/* safemask is the mask to apply to the camel_mime_special_table to determine what - characters can safely be included without encoding */ -static size_t -quoted_encode (const unsigned char *in, size_t len, unsigned char *out, unsigned short safemask) -{ - register const unsigned char *inptr, *inend; - unsigned char *outptr; - unsigned char c; - - inptr = in; - inend = in + len; - outptr = out; - while (inptr < inend) { - c = *inptr++; - if (c==' ') { - *outptr++ = '_'; - } else if (camel_mime_special_table[c] & safemask) { - *outptr++ = c; - } else { - *outptr++ = '='; - *outptr++ = tohex[(c >> 4) & 0xf]; - *outptr++ = tohex[c & 0xf]; - } - } - - d(printf("encoding '%.*s' = '%.*s'\n", len, in, outptr-out, out)); - - return (outptr - out); -} - - -static void -header_decode_lwsp(const char **in) -{ - const char *inptr = *in; - char c; - - d2(printf("is ws: '%s'\n", *in)); - - while (camel_mime_is_lwsp(*inptr) || (*inptr =='(' && *inptr != '\0')) { - while (camel_mime_is_lwsp(*inptr) && inptr != '\0') { - d2(printf("(%c)", *inptr)); - inptr++; - } - d2(printf("\n")); - - /* check for comments */ - if (*inptr == '(') { - int depth = 1; - inptr++; - while (depth && (c=*inptr) && *inptr != '\0') { - if (c=='\\' && inptr[1]) { - inptr++; - } else if (c=='(') { - depth++; - } else if (c==')') { - depth--; - } - inptr++; - } - } - } - *in = inptr; -} - -/* decode rfc 2047 encoded string segment */ -static char * -rfc2047_decode_word(const char *in, size_t len) -{ - const char *inptr = in+2; - const char *inend = in+len-2; - const char *inbuf; - const char *charset; - char *encname, *p; - int tmplen; - size_t ret; - char *decword = NULL; - char *decoded = NULL; - char *outbase = NULL; - char *outbuf; - size_t inlen, outlen; - gboolean retried = FALSE; - iconv_t ic; - - d(printf("rfc2047: decoding '%.*s'\n", len, in)); - - /* quick check to see if this could possibly be a real encoded word */ - if (len < 8 || !(in[0] == '=' && in[1] == '?' && in[len-1] == '=' && in[len-2] == '?')) { - d(printf("invalid\n")); - return NULL; - } - - /* skip past the charset to the encoding type */ - inptr = memchr (inptr, '?', inend-inptr); - if (inptr != NULL && inptr < inend + 2 && inptr[2] == '?') { - d(printf("found ?, encoding is '%c'\n", inptr[0])); - inptr++; - tmplen = inend-inptr-2; - decword = g_alloca (tmplen); /* this will always be more-than-enough room */ - switch(toupper(inptr[0])) { - case 'Q': - inlen = quoted_decode(inptr+2, tmplen, decword); - break; - case 'B': { - int state = 0; - unsigned int save = 0; - - inlen = camel_base64_decode_step((char *)inptr+2, tmplen, decword, &state, &save); - /* if state != 0 then error? */ - break; - } - default: - /* uhhh, unknown encoding type - probably an invalid encoded word string */ - return NULL; - } - d(printf("The encoded length = %d\n", inlen)); - if (inlen > 0) { - /* yuck, all this snot is to setup iconv! */ - tmplen = inptr - in - 3; - encname = g_alloca (tmplen + 1); - memcpy (encname, in + 2, tmplen); - encname[tmplen] = '\0'; - - /* rfc2231 updates rfc2047 encoded words... - * The ABNF given in RFC 2047 for encoded-words is: - * encoded-word := "=?" charset "?" encoding "?" encoded-text "?=" - * This specification changes this ABNF to: - * encoded-word := "=?" charset ["*" language] "?" encoding "?" encoded-text "?=" - */ - - /* trim off the 'language' part if it's there... */ - p = strchr (encname, '*'); - if (p) - *p = '\0'; - - charset = e_iconv_charset_name (encname); - - inbuf = decword; - - outlen = inlen * 6 + 16; - outbase = g_alloca (outlen); - outbuf = outbase; - - retry: - ic = e_iconv_open ("UTF-8", charset); - if (ic != (iconv_t) -1) { - ret = e_iconv (ic, &inbuf, &inlen, &outbuf, &outlen); - if (ret != (size_t) -1) { - e_iconv (ic, NULL, 0, &outbuf, &outlen); - *outbuf = 0; - decoded = g_strdup (outbase); - } - e_iconv_close (ic); - } else { - w(g_warning ("Cannot decode charset, header display may be corrupt: %s: %s", - charset, strerror (errno))); - - if (!retried) { - charset = e_iconv_locale_charset (); - if (!charset) - charset = "iso-8859-1"; - - retried = TRUE; - goto retry; - } - - /* we return the encoded word here because we've got to return valid utf8 */ - decoded = g_strndup (in, inlen); - } - } - } - - d(printf("decoded '%s'\n", decoded)); - - return decoded; -} - -/* ok, a lot of mailers are BROKEN, and send iso-latin1 encoded - headers, when they should just be sticking to US-ASCII - according to the rfc's. Anyway, since the conversion to utf-8 - is trivial, just do it here without iconv */ -static GString * -append_latin1 (GString *out, const char *in, size_t len) -{ - unsigned int c; - - while (len) { - c = (unsigned int)*in++; - len--; - if (c & 0x80) { - out = g_string_append_c (out, 0xc0 | ((c >> 6) & 0x3)); /* 110000xx */ - out = g_string_append_c (out, 0x80 | (c & 0x3f)); /* 10xxxxxx */ - } else { - out = g_string_append_c (out, c); - } - } - return out; -} - -static int -append_8bit (GString *out, const char *inbuf, size_t inlen, const char *charset) -{ - char *outbase, *outbuf; - size_t outlen; - iconv_t ic; - - ic = e_iconv_open ("UTF-8", charset); - if (ic == (iconv_t) -1) - return FALSE; - - outlen = inlen * 6 + 16; - outbuf = outbase = g_malloc(outlen); - - if (e_iconv (ic, &inbuf, &inlen, &outbuf, &outlen) == (size_t) -1) { - w(g_warning("Conversion to '%s' failed: %s", charset, strerror (errno))); - g_free(outbase); - e_iconv_close (ic); - return FALSE; - } - - e_iconv (ic, NULL, NULL, &outbuf, &outlen); - - *outbuf = 0; - g_string_append(out, outbase); - g_free(outbase); - e_iconv_close (ic); - - return TRUE; - -} - -/* decodes a simple text, rfc822 + rfc2047 */ -static char * -header_decode_text (const char *in, size_t inlen, const char *default_charset) -{ - GString *out; - const char *inptr, *inend, *start, *chunk, *locale_charset; - char *dword = NULL; - - locale_charset = e_iconv_locale_charset (); - - out = g_string_new (""); - inptr = in; - inend = inptr + inlen; - chunk = NULL; - - while (inptr < inend) { - start = inptr; - while (inptr < inend && camel_mime_is_lwsp(*inptr)) - inptr++; - - if (inptr == inend) { - g_string_append_len(out, start, inptr-start); - break; - } else if (dword == NULL) { - g_string_append_len(out, start, inptr-start); - } else { - chunk = start; - } - - start = inptr; - while (inptr < inend && !camel_mime_is_lwsp(*inptr)) - inptr++; - - dword = rfc2047_decode_word(start, inptr-start); - if (dword) { - g_string_append(out, dword); - g_free(dword); - } else { - if (!chunk) - chunk = start; - - if ((default_charset == NULL || !append_8bit (out, chunk, inptr-chunk, default_charset)) - && (locale_charset == NULL || !append_8bit(out, chunk, inptr-chunk, locale_charset))) - append_latin1(out, chunk, inptr-chunk); - } - - chunk = NULL; - } - - dword = out->str; - g_string_free (out, FALSE); - - return dword; -} - -char * -camel_header_decode_string (const char *in, const char *default_charset) -{ - if (in == NULL) - return NULL; - return header_decode_text (in, strlen (in), default_charset); -} - -/* how long a sequence of pre-encoded words should be less than, to attempt to - fit into a properly folded word. Only a guide. */ -#define CAMEL_FOLD_PREENCODED (24) - -/* FIXME: needs a way to cache iconv opens for different charsets? */ -static void -rfc2047_encode_word(GString *outstring, const char *in, size_t len, const char *type, unsigned short safemask) -{ - iconv_t ic = (iconv_t) -1; - char *buffer, *out, *ascii; - size_t inlen, outlen, enclen, bufflen; - const char *inptr, *p; - int first = 1; - - d(printf("Converting [%d] '%.*s' to %s\n", len, len, in, type)); - - /* convert utf8->encoding */ - bufflen = len * 6 + 16; - buffer = g_alloca (bufflen); - inlen = len; - inptr = in; - - ascii = g_alloca (bufflen); - - if (strcasecmp (type, "UTF-8") != 0) - ic = e_iconv_open (type, "UTF-8"); - - while (inlen) { - size_t convlen, proclen; - int i; - - /* break up words into smaller bits, what we really want is encoded + overhead < 75, - but we'll just guess what that means in terms of input chars, and assume its good enough */ - - out = buffer; - outlen = bufflen; - - if (ic == (iconv_t) -1) { - /* native encoding case, the easy one (?) */ - /* we work out how much we can convert, and still be in length */ - /* proclen will be the result of input characters that we can convert, to the nearest - (approximated) valid utf8 char */ - convlen = 0; - proclen = 0; - p = inptr; - i = 0; - while (p < (in+len) && convlen < (75 - strlen("=?utf-8?q\?\?="))) { - unsigned char c = *p++; - - if (c >= 0xc0) - proclen = i; - i++; - if (c < 0x80) - proclen = i; - if (camel_mime_special_table[c] & safemask) - convlen += 1; - else - convlen += 3; - } - /* well, we probably have broken utf8, just copy it anyway what the heck */ - if (proclen == 0) { - w(g_warning("Appear to have truncated utf8 sequence")); - proclen = inlen; - } - memcpy(out, inptr, proclen); - inptr += proclen; - inlen -= proclen; - out += proclen; - } else { - /* well we could do similar, but we can't (without undue effort), we'll just break it up into - hopefully-small-enough chunks, and leave it at that */ - convlen = MIN(inlen, CAMEL_FOLD_PREENCODED); - p = inptr; - if (e_iconv (ic, &inptr, &convlen, &out, &outlen) == (size_t) -1) { - w(g_warning("Conversion problem: conversion truncated: %s", strerror (errno))); - /* blah, we include it anyway, better than infinite loop ... */ - inptr = p + convlen; - } else { - /* make sure we flush out any shift state */ - e_iconv (ic, NULL, 0, &out, &outlen); - } - inlen -= (inptr - p); - } - - enclen = out-buffer; - - if (enclen) { - /* create token */ - out = ascii; - if (first) - first = 0; - else - *out++ = ' '; - out += sprintf (out, "=?%s?Q?", type); - out += quoted_encode (buffer, enclen, out, safemask); - sprintf (out, "?="); - - d(printf("converted part = %s\n", ascii)); - - g_string_append (outstring, ascii); - } - } - - if (ic != (iconv_t) -1) - e_iconv_close (ic); -} - - -/* TODO: Should this worry about quotes?? */ -char * -camel_header_encode_string (const unsigned char *in) -{ - const unsigned char *inptr = in, *start, *word; - gboolean last_was_encoded = FALSE; - gboolean last_was_space = FALSE; - int encoding; - GString *out; - char *outstr; - - g_return_val_if_fail (g_utf8_validate (in, -1, NULL), NULL); - - if (in == NULL) - return NULL; - - /* do a quick us-ascii check (the common case?) */ - while (*inptr) { - if (*inptr > 127) - break; - inptr++; - } - if (*inptr == '\0') - return g_strdup (in); - - /* This gets each word out of the input, and checks to see what charset - can be used to encode it. */ - /* TODO: Work out when to merge subsequent words, or across word-parts */ - out = g_string_new (""); - inptr = in; - encoding = 0; - word = NULL; - start = inptr; - while (inptr && *inptr) { - gunichar c; - const char *newinptr; - - newinptr = g_utf8_next_char (inptr); - c = g_utf8_get_char (inptr); - if (newinptr == NULL || !g_unichar_validate (c)) { - w(g_warning ("Invalid UTF-8 sequence encountered (pos %d, char '%c'): %s", - (inptr-in), inptr[0], in)); - inptr++; - continue; - } - - if (g_unichar_isspace (c) && !last_was_space) { - /* we've reached the end of a 'word' */ - if (word && !(last_was_encoded && encoding)) { - g_string_append_len (out, start, word - start); - start = word; - } - - switch (encoding) { - case 0: - out = g_string_append_len (out, word, inptr - start); - last_was_encoded = FALSE; - break; - case 1: - if (last_was_encoded) - g_string_append_c (out, ' '); - - rfc2047_encode_word (out, start, inptr - start, "ISO-8859-1", CAMEL_MIME_IS_ESAFE); - last_was_encoded = TRUE; - break; - case 2: - if (last_was_encoded) - g_string_append_c (out, ' '); - - rfc2047_encode_word (out, start, inptr - start, - camel_charset_best (start, inptr - start), CAMEL_MIME_IS_ESAFE); - last_was_encoded = TRUE; - break; - } - - last_was_space = TRUE; - start = inptr; - word = NULL; - encoding = 0; - } else if (c > 127 && c < 256) { - encoding = MAX (encoding, 1); - last_was_space = FALSE; - } else if (c >= 256) { - encoding = MAX (encoding, 2); - last_was_space = FALSE; - } else if (!g_unichar_isspace (c)) { - last_was_space = FALSE; - } - - if (!g_unichar_isspace (c) && !word) - word = inptr; - - inptr = newinptr; - } - - if (inptr - start) { - if (word && !(last_was_encoded && encoding)) { - g_string_append_len (out, start, word - start); - start = word; - } - - switch (encoding) { - case 0: - out = g_string_append_len (out, start, inptr - start); - break; - case 1: - if (last_was_encoded) - g_string_append_c (out, ' '); - - rfc2047_encode_word (out, start, inptr - start, "ISO-8859-1", CAMEL_MIME_IS_ESAFE); - break; - case 2: - if (last_was_encoded) - g_string_append_c (out, ' '); - - rfc2047_encode_word (out, start, inptr - start, - camel_charset_best (start, inptr - start - 1), CAMEL_MIME_IS_ESAFE); - break; - } - } - - outstr = out->str; - g_string_free (out, FALSE); - - return outstr; -} - -/* apply quoted-string rules to a string */ -static void -quote_word(GString *out, gboolean do_quotes, const char *start, size_t len) -{ - int i, c; - - /* TODO: What about folding on long lines? */ - if (do_quotes) - g_string_append_c(out, '"'); - for (i=0;i 0) { - word = g_new0 (struct _phrase_word, 1); - word->start = start; - word->end = last; - word->type = type; - word->encoding = encoding; - words = g_list_append (words, word); - count = 0; - } - - start = inptr; - type = WORD_ATOM; - encoding = 0; - } else { - count++; - if (c < 128) { - if (!camel_mime_is_atom (c)) - type = MAX (type, WORD_QSTRING); - } else if (c > 127 && c < 256) { - type = WORD_2047; - encoding = MAX (encoding, 1); - } else if (c >= 256) { - type = WORD_2047; - encoding = MAX (encoding, 2); - } - } - - last = inptr; - } - - if (count > 0) { - word = g_new0 (struct _phrase_word, 1); - word->start = start; - word->end = last; - word->type = type; - word->encoding = encoding; - words = g_list_append (words, word); - } - - return words; -} - -#define MERGED_WORD_LT_FOLDLEN(wordlen, type) ((type) == WORD_2047 ? (wordlen) < CAMEL_FOLD_PREENCODED : (wordlen) < (CAMEL_FOLD_SIZE - 8)) - -static gboolean -header_encode_phrase_merge_words (GList **wordsp) -{ - GList *wordl, *nextl, *words = *wordsp; - struct _phrase_word *word, *next; - gboolean merged = FALSE; - - /* scan the list, checking for words of similar types that can be merged */ - wordl = words; - while (wordl) { - word = wordl->data; - nextl = g_list_next (wordl); - - while (nextl) { - next = nextl->data; - /* merge nodes of the same type AND we are not creating too long a string */ - if (word_types_compatable (word->type, next->type)) { - if (MERGED_WORD_LT_FOLDLEN (next->end - word->start, MAX (word->type, next->type))) { - /* the resulting word type is the MAX of the 2 types */ - word->type = MAX(word->type, next->type); - - word->end = next->end; - words = g_list_remove_link (words, nextl); - g_list_free_1 (nextl); - g_free (next); - - nextl = g_list_next (wordl); - - merged = TRUE; - } else { - /* if it is going to be too long, make sure we include the - separating whitespace */ - word->end = next->start; - break; - } - } else { - break; - } - } - - wordl = g_list_next (wordl); - } - - *wordsp = words; - - return merged; -} - -/* encodes a phrase sequence (different quoting/encoding rules to strings) */ -char * -camel_header_encode_phrase (const unsigned char *in) -{ - struct _phrase_word *word = NULL, *last_word = NULL; - GList *words, *wordl; - GString *out; - char *outstr; - - if (in == NULL) - return NULL; - - words = header_encode_phrase_get_words (in); - if (!words) - return NULL; - - while (header_encode_phrase_merge_words (&words)) - ; - - out = g_string_new (""); - - /* output words now with spaces between them */ - wordl = words; - while (wordl) { - const char *start; - size_t len; - - word = wordl->data; - - /* append correct number of spaces between words */ - if (last_word && !(last_word->type == WORD_2047 && word->type == WORD_2047)) { - /* one or both of the words are not encoded so we write the spaces out untouched */ - len = word->start - last_word->end; - out = g_string_append_len (out, last_word->end, len); - } - - switch (word->type) { - case WORD_ATOM: - out = g_string_append_len (out, word->start, word->end - word->start); - break; - case WORD_QSTRING: - quote_word (out, TRUE, word->start, word->end - word->start); - break; - case WORD_2047: - if (last_word && last_word->type == WORD_2047) { - /* include the whitespace chars between these 2 words in the - resulting rfc2047 encoded word. */ - len = word->end - last_word->end; - start = last_word->end; - - /* encoded words need to be separated by linear whitespace */ - g_string_append_c (out, ' '); - } else { - len = word->end - word->start; - start = word->start; - } - - if (word->encoding == 1) - rfc2047_encode_word (out, start, len, "ISO-8859-1", CAMEL_MIME_IS_PSAFE); - else - rfc2047_encode_word (out, start, len, - camel_charset_best (start, len), CAMEL_MIME_IS_PSAFE); - break; - } - - g_free (last_word); - wordl = g_list_next (wordl); - - last_word = word; - } - - /* and we no longer need the list */ - g_free (word); - g_list_free (words); - - outstr = out->str; - g_string_free (out, FALSE); - - return outstr; -} - - -/* these are all internal parser functions */ - -static char * -decode_token (const char **in) -{ - const char *inptr = *in; - const char *start; - - header_decode_lwsp (&inptr); - start = inptr; - while (camel_mime_is_ttoken (*inptr)) - inptr++; - if (inptr > start) { - *in = inptr; - return g_strndup (start, inptr - start); - } else { - return NULL; - } -} - -char * -camel_header_token_decode(const char *in) -{ - if (in == NULL) - return NULL; - - return decode_token(&in); -} - -/* - <"> * ( \, cr / \ ) <"> -*/ -static char * -header_decode_quoted_string(const char **in) -{ - const char *inptr = *in; - char *out = NULL, *outptr; - size_t outlen; - int c; - - header_decode_lwsp(&inptr); - if (*inptr == '"') { - const char *intmp; - int skip = 0; - - /* first, calc length */ - inptr++; - intmp = inptr; - while ( (c = *intmp++) && c!= '"') { - if (c=='\\' && *intmp) { - intmp++; - skip++; - } - } - outlen = intmp-inptr-skip; - out = outptr = g_malloc(outlen+1); - while ( (c = *inptr++) && c!= '"') { - if (c=='\\' && *inptr) { - c = *inptr++; - } - *outptr++ = c; - } - *outptr = '\0'; - } - *in = inptr; - return out; -} - -static char * -header_decode_atom(const char **in) -{ - const char *inptr = *in, *start; - - header_decode_lwsp(&inptr); - start = inptr; - while (camel_mime_is_atom(*inptr)) - inptr++; - *in = inptr; - if (inptr > start) - return g_strndup(start, inptr-start); - else - return NULL; -} - -static char * -header_decode_word (const char **in) -{ - const char *inptr = *in; - - header_decode_lwsp (&inptr); - if (*inptr == '"') { - *in = inptr; - return header_decode_quoted_string (in); - } else { - *in = inptr; - return header_decode_atom (in); - } -} - -static char * -header_decode_value(const char **in) -{ - const char *inptr = *in; - - header_decode_lwsp(&inptr); - if (*inptr == '"') { - d(printf("decoding quoted string\n")); - return header_decode_quoted_string(in); - } else if (camel_mime_is_ttoken(*inptr)) { - d(printf("decoding token\n")); - /* this may not have the right specials for all params? */ - return decode_token(in); - } - return NULL; -} - -/* should this return -1 for no int? */ -int -camel_header_decode_int(const char **in) -{ - const char *inptr = *in; - int c, v=0; - - header_decode_lwsp(&inptr); - while ( (c=*inptr++ & 0xff) - && isdigit(c) ) { - v = v*10+(c-'0'); - } - *in = inptr-1; - return v; -} - -#define HEXVAL(c) (isdigit (c) ? (c) - '0' : tolower (c) - 'a' + 10) - -static char * -hex_decode (const char *in, size_t len) -{ - const unsigned char *inend = in + len; - unsigned char *inptr, *outptr; - char *outbuf; - - outptr = outbuf = g_malloc (len + 1); - - inptr = (unsigned char *) in; - while (inptr < inend) { - if (*inptr == '%') { - if (isxdigit (inptr[1]) && isxdigit (inptr[2])) { - *outptr++ = HEXVAL (inptr[1]) * 16 + HEXVAL (inptr[2]); - inptr += 3; - } else - *outptr++ = *inptr++; - } else - *outptr++ = *inptr++; - } - - *outptr = '\0'; - - return outbuf; -} - -/* an rfc2184 encoded string looks something like: - * us-ascii'en'This%20is%20even%20more%20 - */ - -static char * -rfc2184_decode (const char *in, size_t len) -{ - const char *inptr = in; - const char *inend = in + len; - const char *charset; - char *decoded = NULL; - char *encoding; - - inptr = memchr (inptr, '\'', len); - if (!inptr) - return NULL; - - encoding = g_strndup (in, inptr - in); - charset = e_iconv_charset_name (encoding); - g_free (encoding); - - inptr = memchr (inptr + 1, '\'', inend - inptr - 1); - if (!inptr) - return NULL; - - inptr++; - if (inptr < inend) { - char *decword, *outbase, *outbuf; - const char *inbuf; - size_t inlen, outlen; - iconv_t ic; - - inbuf = decword = hex_decode (inptr, inend - inptr); - inlen = strlen (inbuf); - - ic = e_iconv_open ("UTF-8", charset); - if (ic != (iconv_t) -1) { - size_t ret; - - outlen = inlen * 6 + 16; - outbuf = outbase = g_malloc (outlen); - - ret = e_iconv (ic, &inbuf, &inlen, &outbuf, &outlen); - if (ret != (size_t) -1) { - e_iconv (ic, NULL, 0, &outbuf, &outlen); - *outbuf = '\0'; - g_free (decoded); - decoded = outbase; - } - - e_iconv_close (ic); - } else { - decoded = decword; - } - } - - return decoded; -} - -/* This function is basically the same as decode_token() - * except that it will not accept *'s which have a special - * meaning for rfc2184 params */ -static char * -decode_param_token (const char **in) -{ - const char *inptr = *in; - const char *start; - - header_decode_lwsp (&inptr); - start = inptr; - while (camel_mime_is_ttoken (*inptr) && *inptr != '*') - inptr++; - if (inptr > start) { - *in = inptr; - return g_strndup (start, inptr - start); - } else { - return NULL; - } -} - -static gboolean -header_decode_rfc2184_param (const char **in, char **paramp, gboolean *is_encoded, int *part) -{ - gboolean is_rfc2184 = FALSE; - const char *inptr = *in; - char *param; - - *is_encoded = FALSE; - *part = -1; - - param = decode_param_token (&inptr); - header_decode_lwsp (&inptr); - - if (*inptr == '*') { - is_rfc2184 = TRUE; - inptr++; - header_decode_lwsp (&inptr); - if (*inptr == '=') { - /* form := param*=value */ - if (is_encoded) - *is_encoded = TRUE; - } else { - /* form := param*#=value or param*#*=value */ - *part = camel_header_decode_int (&inptr); - header_decode_lwsp (&inptr); - if (*inptr == '*') { - /* form := param*#*=value */ - if (is_encoded) - *is_encoded = TRUE; - inptr++; - header_decode_lwsp (&inptr); - } - } - } - - if (paramp) - *paramp = param; - - if (param) - *in = inptr; - - return is_rfc2184; -} - -static int -header_decode_param (const char **in, char **paramp, char **valuep, int *is_rfc2184_param, int *rfc2184_part) -{ - gboolean is_rfc2184_encoded = FALSE; - gboolean is_rfc2184 = FALSE; - const char *inptr = *in; - char *param = NULL; - char *value = NULL; - - *is_rfc2184_param = FALSE; - *rfc2184_part = -1; - - is_rfc2184 = header_decode_rfc2184_param (&inptr, ¶m, &is_rfc2184_encoded, rfc2184_part); - - if (*inptr == '=') { - inptr++; - value = header_decode_value (&inptr); - - if (value && is_rfc2184) { - /* We have ourselves an rfc2184 parameter */ - - if (*rfc2184_part == -1) { - /* rfc2184 allows the value to be broken into - * multiple parts - this isn't one of them so - * it is safe to decode it. - */ - char *val; - - val = rfc2184_decode (value, strlen (value)); - if (val) { - g_free (value); - value = val; - } - } else { - /* Since we are expecting to find the rest of - * this paramter value later, let our caller know. - */ - *is_rfc2184_param = TRUE; - } - } else if (value && !strncmp (value, "=?", 2)) { - /* We have a broken param value that is rfc2047 encoded. - * Since both Outlook and Netscape/Mozilla do this, we - * should handle this case. - */ - char *val; - - val = rfc2047_decode_word (value, strlen (value)); - if (val) { - g_free (value); - value = val; - } - } - } - - if (value && !g_utf8_validate (value, -1, NULL)) { - /* The (broken) mailer sent us an unencoded 8bit value - * attempt to save it by assuming it's in the user's - * locale and converting to utf8 */ - char *outbase, *outbuf, *p; - const char *charset, *inbuf; - size_t inlen, outlen; - iconv_t ic; - - inbuf = value; - inlen = strlen (inbuf); - - charset = e_iconv_locale_charset (); - ic = e_iconv_open ("UTF-8", charset ? charset : "ISO-8859-1"); - if (ic != (iconv_t) -1) { - size_t ret; - - outlen = inlen * 6 + 16; - outbuf = outbase = g_malloc (outlen); - - ret = e_iconv (ic, &inbuf, &inlen, &outbuf, &outlen); - if (ret != (size_t) -1) { - e_iconv (ic, NULL, 0, &outbuf, &outlen); - *outbuf = '\0'; - } - - e_iconv_close (ic); - - g_free (value); - value = outbase; - } else { - /* Okay, so now what? I guess we convert invalid chars to _'s? */ - for (p = value; *p; p++) - if (!isascii ((unsigned) *p)) - *p = '_'; - } - } - - if (param && value) { - *paramp = param; - *valuep = value; - *in = inptr; - return 0; - } else { - g_free (param); - g_free (value); - return 1; - } -} - -char * -camel_header_param (struct _camel_header_param *p, const char *name) -{ - while (p && strcasecmp (p->name, name) != 0) - p = p->next; - if (p) - return p->value; - return NULL; -} - -struct _camel_header_param * -camel_header_set_param (struct _camel_header_param **l, const char *name, const char *value) -{ - struct _camel_header_param *p = (struct _camel_header_param *)l, *pn; - - if (name == NULL) - return NULL; - - while (p->next) { - pn = p->next; - if (!strcasecmp (pn->name, name)) { - g_free (pn->value); - if (value) { - pn->value = g_strdup (value); - return pn; - } else { - p->next = pn->next; - g_free (pn->name); - g_free (pn); - return NULL; - } - } - p = pn; - } - - if (value == NULL) - return NULL; - - pn = g_malloc (sizeof (*pn)); - pn->next = 0; - pn->name = g_strdup (name); - pn->value = g_strdup (value); - p->next = pn; - - return pn; -} - -const char * -camel_content_type_param (CamelContentType *t, const char *name) -{ - if (t==NULL) - return NULL; - return camel_header_param (t->params, name); -} - -void -camel_content_type_set_param (CamelContentType *t, const char *name, const char *value) -{ - camel_header_set_param (&t->params, name, value); -} - -/** - * camel_content_type_is: - * @ct: A content type specifier, or #NULL. - * @type: A type to check against. - * @subtype: A subtype to check against, or "*" to match any subtype. - * - * Returns #TRUE if the content type @ct is of type @type/@subtype. - * The subtype of "*" will match any subtype. If @ct is #NULL, then - * it will match the type "text/plain". - * - * Return value: #TRUE or #FALSE depending on the matching of the type. - **/ -int -camel_content_type_is(CamelContentType *ct, const char *type, const char *subtype) -{ - /* no type == text/plain or text/"*" */ - if (ct==NULL || (ct->type == NULL && ct->subtype == NULL)) { - return (!strcasecmp(type, "text") - && (!strcasecmp(subtype, "plain") - || !strcasecmp(subtype, "*"))); - } - - return (ct->type != NULL - && (!strcasecmp(ct->type, type) - && ((ct->subtype != NULL - && !strcasecmp(ct->subtype, subtype)) - || !strcasecmp("*", subtype)))); -} - -void -camel_header_param_list_free(struct _camel_header_param *p) -{ - struct _camel_header_param *n; - - while (p) { - n = p->next; - g_free(p->name); - g_free(p->value); - g_free(p); - p = n; - } -} - -CamelContentType * -camel_content_type_new(const char *type, const char *subtype) -{ - CamelContentType *t = g_malloc(sizeof(*t)); - - t->type = g_strdup(type); - t->subtype = g_strdup(subtype); - t->params = NULL; - t->refcount = 1; - return t; -} - -void -camel_content_type_ref(CamelContentType *ct) -{ - if (ct) - ct->refcount++; -} - - -void -camel_content_type_unref(CamelContentType *ct) -{ - if (ct) { - if (ct->refcount <= 1) { - camel_header_param_list_free(ct->params); - g_free(ct->type); - g_free(ct->subtype); - g_free(ct); - } else { - ct->refcount--; - } - } -} - -/* for decoding email addresses, canonically */ -static char * -header_decode_domain(const char **in) -{ - const char *inptr = *in, *start; - int go = TRUE; - char *ret; - GString *domain = g_string_new(""); - - /* domain ref | domain literal */ - header_decode_lwsp(&inptr); - while (go) { - if (*inptr == '[') { /* domain literal */ - domain = g_string_append_c(domain, '['); - inptr++; - header_decode_lwsp(&inptr); - start = inptr; - while (camel_mime_is_dtext(*inptr)) { - domain = g_string_append_c(domain, *inptr); - inptr++; - } - if (*inptr == ']') { - domain = g_string_append_c(domain, ']'); - inptr++; - } else { - w(g_warning("closing ']' not found in domain: %s", *in)); - } - } else { - char *a = header_decode_atom(&inptr); - if (a) { - domain = g_string_append(domain, a); - g_free(a); - } else { - w(g_warning("missing atom from domain-ref")); - break; - } - } - header_decode_lwsp(&inptr); - if (*inptr == '.') { /* next sub-domain? */ - domain = g_string_append_c(domain, '.'); - inptr++; - header_decode_lwsp(&inptr); - } else - go = FALSE; - } - - *in = inptr; - - ret = domain->str; - g_string_free(domain, FALSE); - return ret; -} - -static char * -header_decode_addrspec(const char **in) -{ - const char *inptr = *in; - char *word; - GString *addr = g_string_new(""); - - header_decode_lwsp(&inptr); - - /* addr-spec */ - word = header_decode_word (&inptr); - if (word) { - addr = g_string_append(addr, word); - header_decode_lwsp(&inptr); - g_free(word); - while (*inptr == '.' && word) { - inptr++; - addr = g_string_append_c(addr, '.'); - word = header_decode_word (&inptr); - if (word) { - addr = g_string_append(addr, word); - header_decode_lwsp(&inptr); - g_free(word); - } else { - w(g_warning("Invalid address spec: %s", *in)); - } - } - if (*inptr == '@') { - inptr++; - addr = g_string_append_c(addr, '@'); - word = header_decode_domain(&inptr); - if (word) { - addr = g_string_append(addr, word); - g_free(word); - } else { - w(g_warning("Invalid address, missing domain: %s", *in)); - } - } else { - w(g_warning("Invalid addr-spec, missing @: %s", *in)); - } - } else { - w(g_warning("invalid addr-spec, no local part")); - } - - /* FIXME: return null on error? */ - - *in = inptr; - word = addr->str; - g_string_free(addr, FALSE); - return word; -} - -/* - address: - word *('.' word) @ domain | - *(word) '<' [ *('@' domain ) ':' ] word *( '.' word) @ domain | - - 1*word ':' [ word ... etc (mailbox, as above) ] ';' - */ - -/* mailbox: - word *( '.' word ) '@' domain - *(word) '<' [ *('@' domain ) ':' ] word *( '.' word) @ domain - */ - -static struct _camel_header_address * -header_decode_mailbox(const char **in, const char *charset) -{ - const char *inptr = *in; - char *pre; - int closeme = FALSE; - GString *addr; - GString *name = NULL; - struct _camel_header_address *address = NULL; - const char *comment = NULL; - - addr = g_string_new(""); - - /* for each address */ - pre = header_decode_word (&inptr); - header_decode_lwsp(&inptr); - if (!(*inptr == '.' || *inptr == '@' || *inptr==',' || *inptr=='\0')) { - /* ',' and '\0' required incase it is a simple address, no @ domain part (buggy writer) */ - name = g_string_new (""); - while (pre) { - char *text, *last; - - /* perform internationalised decoding, and append */ - text = camel_header_decode_string (pre, charset); - g_string_append (name, text); - last = pre; - g_free(text); - - pre = header_decode_word (&inptr); - if (pre) { - size_t l = strlen (last); - size_t p = strlen (pre); - - /* dont append ' ' between sucsessive encoded words */ - if ((l>6 && last[l-2] == '?' && last[l-1] == '=') - && (p>6 && pre[0] == '=' && pre[1] == '?')) { - /* dont append ' ' */ - } else { - name = g_string_append_c(name, ' '); - } - } else { - /* Fix for stupidly-broken-mailers that like to put '.''s in names unquoted */ - /* see bug #8147 */ - while (!pre && *inptr && *inptr != '<') { - w(g_warning("Working around stupid mailer bug #5: unescaped characters in names")); - name = g_string_append_c(name, *inptr++); - pre = header_decode_word (&inptr); - } - } - g_free(last); - } - header_decode_lwsp(&inptr); - if (*inptr == '<') { - closeme = TRUE; - try_address_again: - inptr++; - header_decode_lwsp(&inptr); - if (*inptr == '@') { - while (*inptr == '@') { - inptr++; - header_decode_domain(&inptr); - header_decode_lwsp(&inptr); - if (*inptr == ',') { - inptr++; - header_decode_lwsp(&inptr); - } - } - if (*inptr == ':') { - inptr++; - } else { - w(g_warning("broken route-address, missing ':': %s", *in)); - } - } - pre = header_decode_word (&inptr); - header_decode_lwsp(&inptr); - } else { - w(g_warning("broken address? %s", *in)); - } - } - - if (pre) { - addr = g_string_append(addr, pre); - } else { - w(g_warning("No local-part for email address: %s", *in)); - } - - /* should be at word '.' localpart */ - while (*inptr == '.' && pre) { - inptr++; - g_free(pre); - pre = header_decode_word (&inptr); - addr = g_string_append_c(addr, '.'); - if (pre) - addr = g_string_append(addr, pre); - comment = inptr; - header_decode_lwsp(&inptr); - } - g_free(pre); - - /* now at '@' domain part */ - if (*inptr == '@') { - char *dom; - - inptr++; - addr = g_string_append_c(addr, '@'); - comment = inptr; - dom = header_decode_domain(&inptr); - addr = g_string_append(addr, dom); - g_free(dom); - } else if (*inptr != '>' || !closeme) { - /* If we get a <, the address was probably a name part, lets try again shall we? */ - /* Another fix for seriously-broken-mailers */ - if (*inptr && *inptr != ',') { - char *text; - - w(g_warning("We didn't get an '@' where we expected in '%s', trying again", *in)); - w(g_warning("Name is '%s', Addr is '%s' we're at '%s'\n", name?name->str:"", addr->str, inptr)); - - /* need to keep *inptr, as try_address_again will drop the current character */ - if (*inptr == '<') - closeme = TRUE; - else - g_string_append_c(addr, *inptr); - - /* check for address is encoded word ... */ - text = camel_header_decode_string(addr->str, charset); - if (name == NULL) { - name = addr; - addr = g_string_new(""); - if (text) { - g_string_truncate(name, 0); - g_string_append(name, text); - } - } else { - g_string_append(name, text?text:addr->str); - g_string_truncate(addr, 0); - } - g_free(text); - - /* or maybe that we've added up a bunch of broken bits to make an encoded word */ - text = rfc2047_decode_word(name->str, name->len); - if (text) { - g_string_truncate(name, 0); - g_string_append(name, text); - g_free(text); - } - - goto try_address_again; - } - w(g_warning("invalid address, no '@' domain part at %c: %s", *inptr, *in)); - } - - if (closeme) { - header_decode_lwsp(&inptr); - if (*inptr == '>') { - inptr++; - } else { - w(g_warning("invalid route address, no closing '>': %s", *in)); - } - } else if (name == NULL && comment != NULL && inptr>comment) { /* check for comment after address */ - char *text, *tmp; - const char *comstart, *comend; - - /* this is a bit messy, we go from the last known position, because - decode_domain/etc skip over any comments on the way */ - /* FIXME: This wont detect comments inside the domain itself, - but nobody seems to use that feature anyway ... */ - - d(printf("checking for comment from '%s'\n", comment)); - - comstart = strchr(comment, '('); - if (comstart) { - comstart++; - header_decode_lwsp(&inptr); - comend = inptr-1; - while (comend > comstart && comend[0] != ')') - comend--; - - if (comend > comstart) { - d(printf(" looking at subset '%.*s'\n", comend-comstart, comstart)); - tmp = g_strndup (comstart, comend-comstart); - text = camel_header_decode_string (tmp, charset); - name = g_string_new (text); - g_free (tmp); - g_free (text); - } - } - } - - *in = inptr; - - if (addr->len > 0) { - if (!g_utf8_validate (addr->str, addr->len, NULL)) { - /* workaround for invalid addr-specs containing 8bit chars (see bug #42170 for details) */ - const char *locale_charset; - GString *out; - - locale_charset = e_iconv_locale_charset (); - - out = g_string_new (""); - - if ((charset == NULL || !append_8bit (out, addr->str, addr->len, charset)) - && (locale_charset == NULL || !append_8bit (out, addr->str, addr->len, locale_charset))) - append_latin1 (out, addr->str, addr->len); - - g_string_free (addr, TRUE); - addr = out; - } - - address = camel_header_address_new_name(name ? name->str : "", addr->str); - } - - d(printf("got mailbox: %s\n", addr->str)); - - g_string_free(addr, TRUE); - if (name) - g_string_free(name, TRUE); - - return address; -} - -static struct _camel_header_address * -header_decode_address(const char **in, const char *charset) -{ - const char *inptr = *in; - char *pre; - GString *group = g_string_new(""); - struct _camel_header_address *addr = NULL, *member; - - /* pre-scan, trying to work out format, discard results */ - header_decode_lwsp(&inptr); - while ((pre = header_decode_word (&inptr))) { - group = g_string_append(group, pre); - group = g_string_append(group, " "); - g_free(pre); - } - header_decode_lwsp(&inptr); - if (*inptr == ':') { - d(printf("group detected: %s\n", group->str)); - addr = camel_header_address_new_group(group->str); - /* that was a group spec, scan mailbox's */ - inptr++; - /* FIXME: check rfc 2047 encodings of words, here or above in the loop */ - header_decode_lwsp(&inptr); - if (*inptr != ';') { - int go = TRUE; - do { - member = header_decode_mailbox(&inptr, charset); - if (member) - camel_header_address_add_member(addr, member); - header_decode_lwsp(&inptr); - if (*inptr == ',') - inptr++; - else - go = FALSE; - } while (go); - if (*inptr == ';') { - inptr++; - } else { - w(g_warning("Invalid group spec, missing closing ';': %s", *in)); - } - } else { - inptr++; - } - *in = inptr; - } else { - addr = header_decode_mailbox(in, charset); - } - - g_string_free(group, TRUE); - - return addr; -} - -static char * -header_msgid_decode_internal(const char **in) -{ - const char *inptr = *in; - char *msgid = NULL; - - d(printf("decoding Message-ID: '%s'\n", *in)); - - header_decode_lwsp(&inptr); - if (*inptr == '<') { - inptr++; - header_decode_lwsp(&inptr); - msgid = header_decode_addrspec(&inptr); - if (msgid) { - header_decode_lwsp(&inptr); - if (*inptr == '>') { - inptr++; - } else { - w(g_warning("Missing closing '>' on message id: %s", *in)); - } - } else { - w(g_warning("Cannot find message id in: %s", *in)); - } - } else { - w(g_warning("missing opening '<' on message id: %s", *in)); - } - *in = inptr; - - return msgid; -} - -char * -camel_header_msgid_decode(const char *in) -{ - if (in == NULL) - return NULL; - - return header_msgid_decode_internal(&in); -} - -char * -camel_header_contentid_decode (const char *in) -{ - const char *inptr = in; - gboolean at = FALSE; - GString *addr; - char *buf; - - d(printf("decoding Content-ID: '%s'\n", in)); - - header_decode_lwsp (&inptr); - - /* some lame mailers quote the Content-Id */ - if (*inptr == '"') - inptr++; - - /* make sure the content-id is not "" which can happen if we get a - * content-id such as <.@> (which Eudora likes to use...) */ - if ((buf = camel_header_msgid_decode (inptr)) != NULL && *buf) - return buf; - - g_free (buf); - - /* ugh, not a valid msg-id - try to get something useful out of it then? */ - inptr = in; - header_decode_lwsp (&inptr); - if (*inptr == '<') { - inptr++; - header_decode_lwsp (&inptr); - } - - /* Eudora has been known to use <.@> as a content-id */ - if (!(buf = header_decode_word (&inptr)) && !strchr (".@", *inptr)) - return NULL; - - addr = g_string_new (""); - header_decode_lwsp (&inptr); - while (buf != NULL || *inptr == '.' || (*inptr == '@' && !at)) { - if (buf != NULL) { - g_string_append (addr, buf); - g_free (buf); - buf = NULL; - } - - if (!at) { - if (*inptr == '.') { - g_string_append_c (addr, *inptr++); - buf = header_decode_word (&inptr); - } else if (*inptr == '@') { - g_string_append_c (addr, *inptr++); - buf = header_decode_word (&inptr); - at = TRUE; - } - } else if (strchr (".[]", *inptr)) { - g_string_append_c (addr, *inptr++); - buf = header_decode_atom (&inptr); - } - - header_decode_lwsp (&inptr); - } - - buf = addr->str; - g_string_free (addr, FALSE); - - return buf; -} - -void -camel_header_references_list_append_asis(struct _camel_header_references **list, char *ref) -{ - struct _camel_header_references *w = (struct _camel_header_references *)list, *n; - while (w->next) - w = w->next; - n = g_malloc(sizeof(*n)); - n->id = ref; - n->next = 0; - w->next = n; -} - -int -camel_header_references_list_size(struct _camel_header_references **list) -{ - int count = 0; - struct _camel_header_references *w = *list; - while (w) { - count++; - w = w->next; - } - return count; -} - -void -camel_header_references_list_clear(struct _camel_header_references **list) -{ - struct _camel_header_references *w = *list, *n; - while (w) { - n = w->next; - g_free(w->id); - g_free(w); - w = n; - } - *list = NULL; -} - -static void -header_references_decode_single (const char **in, struct _camel_header_references **head) -{ - struct _camel_header_references *ref; - const char *inptr = *in; - char *id, *word; - - while (*inptr) { - header_decode_lwsp (&inptr); - if (*inptr == '<') { - id = header_msgid_decode_internal (&inptr); - if (id) { - ref = g_malloc (sizeof (struct _camel_header_references)); - ref->next = *head; - ref->id = id; - *head = ref; - break; - } - } else { - word = header_decode_word (&inptr); - if (word) - g_free (word); - else if (*inptr != '\0') - inptr++; /* Stupid mailer tricks */ - } - } - - *in = inptr; -} - -struct _camel_header_references * -camel_header_references_inreplyto_decode (const char *in) -{ - struct _camel_header_references *ref = NULL; - - if (in == NULL || in[0] == '\0') - return NULL; - - header_references_decode_single (&in, &ref); - - return ref; -} - -/* generate a list of references, from most recent up */ -struct _camel_header_references * -camel_header_references_decode (const char *in) -{ - struct _camel_header_references *refs = NULL; - - if (in == NULL || in[0] == '\0') - return NULL; - - while (*in) - header_references_decode_single (&in, &refs); - - return refs; -} - -struct _camel_header_references * -camel_header_references_dup(const struct _camel_header_references *list) -{ - struct _camel_header_references *new = NULL, *tmp; - - while (list) { - tmp = g_new(struct _camel_header_references, 1); - tmp->next = new; - tmp->id = g_strdup(list->id); - new = tmp; - list = list->next; - } - return new; -} - -struct _camel_header_address * -camel_header_mailbox_decode(const char *in, const char *charset) -{ - if (in == NULL) - return NULL; - - return header_decode_mailbox(&in, charset); -} - -struct _camel_header_address * -camel_header_address_decode(const char *in, const char *charset) -{ - const char *inptr = in, *last; - struct _camel_header_address *list = NULL, *addr; - - d(printf("decoding To: '%s'\n", in)); - - if (in == NULL) - return NULL; - - header_decode_lwsp(&inptr); - if (*inptr == 0) - return NULL; - - do { - last = inptr; - addr = header_decode_address(&inptr, charset); - if (addr) - camel_header_address_list_append(&list, addr); - header_decode_lwsp(&inptr); - if (*inptr == ',') - inptr++; - else - break; - } while (inptr != last); - - if (*inptr) { - w(g_warning("Invalid input detected at %c (%d): %s\n or at: %s", *inptr, inptr-in, in, inptr)); - } - - if (inptr == last) { - w(g_warning("detected invalid input loop at : %s", last)); - } - - return list; -} - -/* this must be kept in sync with the header */ -static const char *encodings[] = { - "", - "7bit", - "8bit", - "base64", - "quoted-printable", - "binary", - "x-uuencode", -}; - -const char * -camel_transfer_encoding_to_string (CamelTransferEncoding encoding) -{ - if (encoding >= sizeof (encodings) / sizeof (encodings[0])) - encoding = 0; - - return encodings[encoding]; -} - -CamelTransferEncoding -camel_transfer_encoding_from_string (const char *string) -{ - int i; - - if (string != NULL) { - for (i = 0; i < sizeof (encodings) / sizeof (encodings[0]); i++) - if (!strcasecmp (string, encodings[i])) - return i; - } - - return CAMEL_TRANSFER_ENCODING_DEFAULT; -} - -void -camel_header_mime_decode(const char *in, int *maj, int *min) -{ - const char *inptr = in; - int major=-1, minor=-1; - - d(printf("decoding MIME-Version: '%s'\n", in)); - - if (in != NULL) { - header_decode_lwsp(&inptr); - if (isdigit(*inptr)) { - major = camel_header_decode_int(&inptr); - header_decode_lwsp(&inptr); - if (*inptr == '.') { - inptr++; - header_decode_lwsp(&inptr); - if (isdigit(*inptr)) - minor = camel_header_decode_int(&inptr); - } - } - } - - if (maj) - *maj = major; - if (min) - *min = minor; - - d(printf("major = %d, minor = %d\n", major, minor)); -} - -static struct _camel_header_param * -header_decode_param_list (const char **in) -{ - const char *inptr = *in; - struct _camel_header_param *head = NULL, *tail = NULL; - gboolean last_was_rfc2184 = FALSE; - gboolean is_rfc2184 = FALSE; - - header_decode_lwsp (&inptr); - - while (*inptr == ';') { - struct _camel_header_param *param; - char *name, *value; - int rfc2184_part; - - inptr++; - /* invalid format? */ - if (header_decode_param (&inptr, &name, &value, &is_rfc2184, &rfc2184_part) != 0) - break; - - if (is_rfc2184 && tail && !strcasecmp (name, tail->name)) { - /* rfc2184 allows a parameter to be broken into multiple parts - * and it looks like we've found one. Append this value to the - * last value. - */ - /* FIXME: we should be ordering these based on rfc2184_part id */ - GString *gvalue; - - gvalue = g_string_new (tail->value); - g_string_append (gvalue, value); - g_free (tail->value); - g_free (value); - g_free (name); - - tail->value = gvalue->str; - g_string_free (gvalue, FALSE); - } else { - if (last_was_rfc2184) { - /* We've finished gathering the values for the last param - * so it is now safe to decode it. - */ - char *val; - - val = rfc2184_decode (tail->value, strlen (tail->value)); - if (val) { - g_free (tail->value); - tail->value = val; - } - } - - param = g_malloc (sizeof (struct _camel_header_param)); - param->name = name; - param->value = value; - param->next = NULL; - if (head == NULL) - head = param; - if (tail) - tail->next = param; - tail = param; - } - - last_was_rfc2184 = is_rfc2184; - - header_decode_lwsp (&inptr); - } - - if (last_was_rfc2184) { - /* We've finished gathering the values for the last param - * so it is now safe to decode it. - */ - char *val; - - val = rfc2184_decode (tail->value, strlen (tail->value)); - if (val) { - g_free (tail->value); - tail->value = val; - } - } - - *in = inptr; - - return head; -} - -struct _camel_header_param * -camel_header_param_list_decode(const char *in) -{ - if (in == NULL) - return NULL; - - return header_decode_param_list(&in); -} - - -static char * -header_encode_param (const unsigned char *in, gboolean *encoded) -{ - register const unsigned char *inptr = in; - unsigned char *outbuf = NULL; - const unsigned char *inend; - iconv_t cd = (iconv_t) -1; - const char *charset; - char *outstr; - int encoding; - GString *out; - - *encoded = FALSE; - - g_return_val_if_fail (in != NULL, NULL); - g_return_val_if_fail (g_utf8_validate (in, -1, NULL), NULL); - - /* do a quick us-ascii check (the common case?) */ - while (*inptr) { - if (*inptr > 127) - break; - inptr++; - } - - if (*inptr == '\0') - return g_strdup (in); - - inptr = in; - encoding = 0; - while (inptr && *inptr) { - const char *newinptr; - gunichar c; - - newinptr = g_utf8_next_char (inptr); - c = g_utf8_get_char (inptr); - if (newinptr == NULL || !g_unichar_validate (c)) { - w(g_warning ("Invalid UTF-8 sequence encountered (pos %d, char '%c'): %s", - (inptr-in), inptr[0], in)); - inptr++; - continue; - } - - if (c > 127 && c < 256) { - encoding = MAX (encoding, 1); - } else if (c >= 256) { - encoding = MAX (encoding, 2); - } - - inptr = newinptr; - } - - if (encoding == 2) - charset = camel_charset_best (in, inptr - in); - else - charset = "iso-8859-1"; - - if (strcasecmp (charset, "UTF-8") != 0) - cd = e_iconv_open (charset, "UTF-8"); - - if (cd == (iconv_t) -1) { - charset = "UTF-8"; - inptr = in; - inend = inptr + strlen (in); - } else { - size_t inleft, outleft; - const char *inbuf; - char *outptr; - - inleft = (inptr - in); - outleft = inleft * 6 + 20; - outptr = outbuf = g_malloc (outleft); - inbuf = in; - - if (e_iconv (cd, &inbuf, &inleft, &outptr, &outleft) == (size_t) -1) { - w(g_warning ("Conversion problem: conversion truncated: %s", strerror (errno))); - } else { - e_iconv (cd, NULL, 0, &outptr, &outleft); - } - - e_iconv_close (cd); - - inptr = outbuf; - inend = outptr; - } - - /* FIXME: set the 'language' as well, assuming we can get that info...? */ - out = g_string_new (""); - g_string_append_printf (out, "%s''", charset); - - while (inptr < inend) { - unsigned char c = *inptr++; - - /* FIXME: make sure that '\'', '*', and ';' are also encoded */ - - if (c > 127) { - g_string_append_printf (out, "%%%c%c", tohex[(c >> 4) & 0xf], tohex[c & 0xf]); - } else if (camel_mime_is_lwsp (c) || !(camel_mime_special_table[c] & CAMEL_MIME_IS_ESAFE)) { - g_string_append_printf (out, "%%%c%c", tohex[(c >> 4) & 0xf], tohex[c & 0xf]); - } else { - g_string_append_c (out, c); - } - } - - g_free (outbuf); - - outstr = out->str; - g_string_free (out, FALSE); - *encoded = TRUE; - - return outstr; -} - -void -camel_header_param_list_format_append (GString *out, struct _camel_header_param *p) -{ - int used = out->len; - - while (p) { - gboolean encoded = FALSE; - gboolean quote = FALSE; - int here = out->len; - size_t nlen, vlen; - char *value; - - if (!p->value) { - p = p->next; - continue; - } - - value = header_encode_param (p->value, &encoded); - if (!value) { - w(g_warning ("appending parameter %s=%s violates rfc2184", p->name, p->value)); - value = g_strdup (p->value); - } - - if (!encoded) { - char *ch; - - for (ch = value; *ch; ch++) { - if (camel_mime_is_tspecial (*ch) || camel_mime_is_lwsp (*ch)) - break; - } - - quote = ch && *ch; - } - - nlen = strlen (p->name); - vlen = strlen (value); - - if (used + nlen + vlen > CAMEL_FOLD_SIZE - 8) { - out = g_string_append (out, ";\n\t"); - here = out->len; - used = 0; - } else - out = g_string_append (out, "; "); - - if (nlen + vlen > CAMEL_FOLD_SIZE - 8) { - /* we need to do special rfc2184 parameter wrapping */ - int maxlen = CAMEL_FOLD_SIZE - (nlen + 8); - char *inptr, *inend; - int i = 0; - - inptr = value; - inend = value + vlen; - - while (inptr < inend) { - char *ptr = inptr + MIN (inend - inptr, maxlen); - - if (encoded && ptr < inend) { - /* be careful not to break an encoded char (ie %20) */ - char *q = ptr; - int j = 2; - - for ( ; j > 0 && q > inptr && *q != '%'; j--, q--); - if (*q == '%') - ptr = q; - } - - if (i != 0) { - g_string_append (out, ";\n\t"); - here = out->len; - used = 0; - } - - g_string_append_printf (out, "%s*%d%s=", p->name, i++, encoded ? "*" : ""); - if (encoded || !quote) - g_string_append_len (out, inptr, ptr - inptr); - else - quote_word (out, TRUE, inptr, ptr - inptr); - - d(printf ("wrote: %s\n", out->str + here)); - - used += (out->len - here); - - inptr = ptr; - } - } else { - g_string_append_printf (out, "%s%s=", p->name, encoded ? "*" : ""); - - if (encoded || !quote) - g_string_append (out, value); - else - quote_word (out, TRUE, value, vlen); - - used += (out->len - here); - } - - g_free (value); - - p = p->next; - } -} - -char * -camel_header_param_list_format(struct _camel_header_param *p) -{ - GString *out = g_string_new(""); - char *ret; - - camel_header_param_list_format_append(out, p); - ret = out->str; - g_string_free(out, FALSE); - return ret; -} - -CamelContentType * -camel_content_type_decode(const char *in) -{ - const char *inptr = in; - char *type, *subtype = NULL; - CamelContentType *t = NULL; - - if (in==NULL) - return NULL; - - type = decode_token(&inptr); - header_decode_lwsp(&inptr); - if (type) { - if (*inptr == '/') { - inptr++; - subtype = decode_token(&inptr); - } - if (subtype == NULL && (!strcasecmp(type, "text"))) { - w(g_warning("text type with no subtype, resorting to text/plain: %s", in)); - subtype = g_strdup("plain"); - } - if (subtype == NULL) { - w(g_warning("MIME type with no subtype: %s", in)); - } - - t = camel_content_type_new(type, subtype); - t->params = header_decode_param_list(&inptr); - g_free(type); - g_free(subtype); - } else { - g_free(type); - d(printf("cannot find MIME type in header (2) '%s'", in)); - } - return t; -} - -void -camel_content_type_dump(CamelContentType *ct) -{ - struct _camel_header_param *p; - - printf("Content-Type: "); - if (ct==NULL) { - printf("\n"); - return; - } - printf("%s / %s", ct->type, ct->subtype); - p = ct->params; - if (p) { - while (p) { - printf(";\n\t%s=\"%s\"", p->name, p->value); - p = p->next; - } - } - printf("\n"); -} - -char * -camel_content_type_format (CamelContentType *ct) -{ - GString *out; - char *ret; - - if (ct == NULL) - return NULL; - - out = g_string_new (""); - if (ct->type == NULL) { - g_string_append_printf (out, "text/plain"); - w(g_warning ("Content-Type with no main type")); - } else if (ct->subtype == NULL) { - w(g_warning ("Content-Type with no sub type: %s", ct->type)); - if (!strcasecmp (ct->type, "multipart")) - g_string_append_printf (out, "%s/mixed", ct->type); - else - g_string_append_printf (out, "%s", ct->type); - } else { - g_string_append_printf (out, "%s/%s", ct->type, ct->subtype); - } - camel_header_param_list_format_append (out, ct->params); - - ret = out->str; - g_string_free (out, FALSE); - - return ret; -} - -char * -camel_content_type_simple (CamelContentType *ct) -{ - if (ct->type == NULL) { - w(g_warning ("Content-Type with no main type")); - return g_strdup ("text/plain"); - } else if (ct->subtype == NULL) { - w(g_warning ("Content-Type with no sub type: %s", ct->type)); - if (!strcasecmp (ct->type, "multipart")) - return g_strdup_printf ("%s/mixed", ct->type); - else - return g_strdup (ct->type); - } else - return g_strdup_printf ("%s/%s", ct->type, ct->subtype); -} - -char * -camel_content_transfer_encoding_decode (const char *in) -{ - if (in) - return decode_token (&in); - - return NULL; -} - -CamelContentDisposition * -camel_content_disposition_decode(const char *in) -{ - CamelContentDisposition *d = NULL; - const char *inptr = in; - - if (in == NULL) - return NULL; - - d = g_malloc(sizeof(*d)); - d->refcount = 1; - d->disposition = decode_token(&inptr); - if (d->disposition == NULL) - w(g_warning("Empty disposition type")); - d->params = header_decode_param_list(&inptr); - return d; -} - -void -camel_content_disposition_ref(CamelContentDisposition *d) -{ - if (d) - d->refcount++; -} - -void -camel_content_disposition_unref(CamelContentDisposition *d) -{ - if (d) { - if (d->refcount<=1) { - camel_header_param_list_free(d->params); - g_free(d->disposition); - g_free(d); - } else { - d->refcount--; - } - } -} - -char * -camel_content_disposition_format(CamelContentDisposition *d) -{ - GString *out; - char *ret; - - if (d==NULL) - return NULL; - - out = g_string_new(""); - if (d->disposition) - out = g_string_append(out, d->disposition); - else - out = g_string_append(out, "attachment"); - camel_header_param_list_format_append(out, d->params); - - ret = out->str; - g_string_free(out, FALSE); - return ret; -} - -/* hrm, is there a library for this shit? */ -static struct { - char *name; - int offset; -} tz_offsets [] = { - { "UT", 0 }, - { "GMT", 0 }, - { "EST", -500 }, /* these are all US timezones. bloody yanks */ - { "EDT", -400 }, - { "CST", -600 }, - { "CDT", -500 }, - { "MST", -700 }, - { "MDT", -600 }, - { "PST", -800 }, - { "PDT", -700 }, - { "Z", 0 }, - { "A", -100 }, - { "M", -1200 }, - { "N", 100 }, - { "Y", 1200 }, -}; - -static char *tz_months [] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static char *tz_days [] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - -char * -camel_header_format_date(time_t time, int offset) -{ - struct tm tm; - - d(printf("offset = %d\n", offset)); - - d(printf("converting date %s", ctime(&time))); - - time += ((offset / 100) * (60*60)) + (offset % 100)*60; - - d(printf("converting date %s", ctime(&time))); - - gmtime_r (&time, &tm); - - return g_strdup_printf("%s, %02d %s %04d %02d:%02d:%02d %+05d", - tz_days[tm.tm_wday], - tm.tm_mday, tz_months[tm.tm_mon], - tm.tm_year + 1900, - tm.tm_hour, tm.tm_min, tm.tm_sec, - offset); -} - -/* convert a date to time_t representation */ -/* this is an awful mess oh well */ -time_t -camel_header_decode_date(const char *in, int *saveoffset) -{ - const char *inptr = in; - char *monthname; - gboolean foundmonth; - int year, offset = 0; - struct tm tm; - int i; - time_t t; - - if (in == NULL) { - if (saveoffset) - *saveoffset = 0; - return 0; - } - - d(printf ("\ndecoding date '%s'\n", inptr)); - - memset (&tm, 0, sizeof(tm)); - - header_decode_lwsp (&inptr); - if (!isdigit (*inptr)) { - char *day = decode_token (&inptr); - /* we dont really care about the day, it's only for display */ - if (day) { - d(printf ("got day: %s\n", day)); - g_free (day); - header_decode_lwsp (&inptr); - if (*inptr == ',') { - inptr++; - } else { -#ifndef CLEAN_DATE - return parse_broken_date (in, saveoffset); -#else - if (saveoffset) - *saveoffset = 0; - return 0; -#endif /* ! CLEAN_DATE */ - } - } - } - tm.tm_mday = camel_header_decode_int(&inptr); -#ifndef CLEAN_DATE - if (tm.tm_mday == 0) { - return parse_broken_date (in, saveoffset); - } -#endif /* ! CLEAN_DATE */ - - monthname = decode_token(&inptr); - foundmonth = FALSE; - if (monthname) { - for (i=0;i= 100 && year < 1900) { - tm.tm_year = year; - } else { - tm.tm_year = year - 1900; - } - /* get the time ... yurck */ - tm.tm_hour = camel_header_decode_int(&inptr); - header_decode_lwsp(&inptr); - if (*inptr == ':') - inptr++; - tm.tm_min = camel_header_decode_int(&inptr); - header_decode_lwsp(&inptr); - if (*inptr == ':') - inptr++; - tm.tm_sec = camel_header_decode_int(&inptr); - header_decode_lwsp(&inptr); - if (*inptr == '+' - || *inptr == '-') { - offset = (*inptr++)=='-'?-1:1; - offset = offset * camel_header_decode_int(&inptr); - d(printf("abs signed offset = %d\n", offset)); - if (offset < -1200 || offset > 1400) - offset = 0; - } else if (isdigit(*inptr)) { - offset = camel_header_decode_int(&inptr); - d(printf("abs offset = %d\n", offset)); - if (offset < -1200 || offset > 1400) - offset = 0; - } else { - char *tz = decode_token(&inptr); - - if (tz) { - for (i=0;ivalue; - while (p && *p) { - if (!isascii(*p)) { - w(g_warning("Appending header violates rfc: %s: %s", h->name, h->value)); - return; - } - p++; - } -} -#endif - -void -camel_header_raw_append_parse(struct _camel_header_raw **list, const char *header, int offset) -{ - register const char *in; - size_t fieldlen; - char *name; - - in = header; - while (camel_mime_is_fieldname(*in) || *in==':') - in++; - fieldlen = in-header-1; - while (camel_mime_is_lwsp(*in)) - in++; - if (fieldlen == 0 || header[fieldlen] != ':') { - printf("Invalid header line: '%s'\n", header); - return; - } - name = g_alloca (fieldlen + 1); - memcpy(name, header, fieldlen); - name[fieldlen] = 0; - - camel_header_raw_append(list, name, in, offset); -} - -void -camel_header_raw_append(struct _camel_header_raw **list, const char *name, const char *value, int offset) -{ - struct _camel_header_raw *l, *n; - - d(printf("Header: %s: %s\n", name, value)); - - n = g_malloc(sizeof(*n)); - n->next = NULL; - n->name = g_strdup(name); - n->value = g_strdup(value); - n->offset = offset; -#ifdef CHECKS - check_header(n); -#endif - l = (struct _camel_header_raw *)list; - while (l->next) { - l = l->next; - } - l->next = n; - - /* debug */ -#if 0 - if (!strcasecmp(name, "To")) { - printf("- Decoding To\n"); - camel_header_to_decode(value); - } else if (!strcasecmp(name, "Content-type")) { - printf("- Decoding content-type\n"); - camel_content_type_dump(camel_content_type_decode(value)); - } else if (!strcasecmp(name, "MIME-Version")) { - printf("- Decoding mime version\n"); - camel_header_mime_decode(value); - } -#endif -} - -static struct _camel_header_raw * -header_raw_find_node(struct _camel_header_raw **list, const char *name) -{ - struct _camel_header_raw *l; - - l = *list; - while (l) { - if (!strcasecmp(l->name, name)) - break; - l = l->next; - } - return l; -} - -const char * -camel_header_raw_find(struct _camel_header_raw **list, const char *name, int *offset) -{ - struct _camel_header_raw *l; - - l = header_raw_find_node(list, name); - if (l) { - if (offset) - *offset = l->offset; - return l->value; - } else - return NULL; -} - -const char * -camel_header_raw_find_next(struct _camel_header_raw **list, const char *name, int *offset, const char *last) -{ - struct _camel_header_raw *l; - - if (last == NULL || name == NULL) - return NULL; - - l = *list; - while (l && l->value != last) - l = l->next; - return camel_header_raw_find(&l, name, offset); -} - -static void -header_raw_free(struct _camel_header_raw *l) -{ - g_free(l->name); - g_free(l->value); - g_free(l); -} - -void -camel_header_raw_remove(struct _camel_header_raw **list, const char *name) -{ - struct _camel_header_raw *l, *p; - - /* the next pointer is at the head of the structure, so this is safe */ - p = (struct _camel_header_raw *)list; - l = *list; - while (l) { - if (!strcasecmp(l->name, name)) { - p->next = l->next; - header_raw_free(l); - l = p->next; - } else { - p = l; - l = l->next; - } - } -} - -void -camel_header_raw_replace(struct _camel_header_raw **list, const char *name, const char *value, int offset) -{ - camel_header_raw_remove(list, name); - camel_header_raw_append(list, name, value, offset); -} - -void -camel_header_raw_clear(struct _camel_header_raw **list) -{ - struct _camel_header_raw *l, *n; - l = *list; - while (l) { - n = l->next; - header_raw_free(l); - l = n; - } - *list = NULL; -} - -char * -camel_header_msgid_generate (void) -{ - static pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER; -#define COUNT_LOCK() pthread_mutex_lock (&count_lock) -#define COUNT_UNLOCK() pthread_mutex_unlock (&count_lock) - char host[MAXHOSTNAMELEN]; - struct hostent *h = NULL; - static int count = 0; - char *msgid; - int retval; - - retval = gethostname (host, sizeof (host)); - - if (retval == 0 && *host) - h = camel_gethostbyname (host, NULL); - else - host[0] = '\0'; - - COUNT_LOCK (); - msgid = g_strdup_printf ("%d.%d.%d.camel@%s", (int) time (NULL), getpid (), count++, - h ? h->h_name : (*host ? host : "localhost.localdomain")); - COUNT_UNLOCK (); - - if (h) - camel_free_host (h); - - return msgid; -} - - -static struct { - char *name; - char *pattern; - regex_t regex; -} mail_list_magic[] = { - /* List-Post: */ - /* List-Post: */ - { "List-Post", "[ \t]*]+)@?([^ \n\t\r>]*)" }, - /* List-Id: GNOME stuff */ - /* List-Id: */ - /* List-Id: */ - /* This old one wasn't very useful: { "List-Id", " *([^<]+)" },*/ - { "List-Id", "[^<]*<([^\\.>]+)\\.?([^ \n\t\r>]*)" }, - /* Mailing-List: list gnome-hackers@gnome.org; contact gnome-hackers-owner@gnome.org */ - { "Mailing-List", "[ \t]*list ([^@]+)@?([^ \n\t\r>;]*)" }, - /* Originator: gnome-hackers@gnome.org */ - { "Originator", "[ \t]*([^@]+)@?([^ \n\t\r>]*)" }, - /* X-Mailing-List: arcive/latest/100 */ - /* X-Mailing-List: gnome-hackers@gnome.org */ - /* X-Mailing-List: gnome-hackers */ - /* X-Mailing-List: */ - { "X-Mailing-List", "[ \t]*]+)@?([^ \n\t\r>]*)" }, - /* X-Loop: gnome-hackers@gnome.org */ - { "X-Loop", "[ \t]*([^@]+)@?([^ \n\t\r>]*)" }, - /* X-List: gnome-hackers */ - /* X-List: gnome-hackers@gnome.org */ - { "X-List", "[ \t]*([^@]+)@?([^ \n\t\r>]*)" }, - /* Sender: owner-gnome-hackers@gnome.org */ - /* Sender: owner-gnome-hacekrs */ - { "Sender", "[ \t]*owner-([^@]+)@?([^ @\n\t\r>]*)" }, - /* Sender: gnome-hackers-owner@gnome.org */ - /* Sender: gnome-hackers-owner */ - { "Sender", "[ \t]*([^@]+)-owner@?([^ @\n\t\r>]*)" }, - /* Delivered-To: mailing list gnome-hackers@gnome.org */ - /* Delivered-To: mailing list gnome-hackers */ - { "Delivered-To", "[ \t]*mailing list ([^@]+)@?([^ \n\t\r>]*)" }, - /* Sender: owner-gnome-hackers@gnome.org */ - /* Sender: */ - /* Sender: owner-gnome-hackers */ - /* Sender: */ - { "Return-Path", "[ \t]*]+)@?([^ \n\t\r>]*)" }, - /* X-BeenThere: gnome-hackers@gnome.org */ - /* X-BeenThere: gnome-hackers */ - { "X-BeenThere", "[ \t]*([^@]+)@?([^ \n\t\r>]*)" }, - /* List-Unsubscribe: */ - { "List-Unsubscribe", "]*)" }, -}; - -char * -camel_header_raw_check_mailing_list(struct _camel_header_raw **list) -{ - const char *v; - regmatch_t match[3]; - int i; - - for (i = 0; i < sizeof (mail_list_magic) / sizeof (mail_list_magic[0]); i++) { - v = camel_header_raw_find (list, mail_list_magic[i].name, NULL); - if (v != NULL && regexec (&mail_list_magic[i].regex, v, 3, match, 0) == 0 && match[1].rm_so != -1) { - char *list; - int len1, len2; - - len1 = match[1].rm_eo - match[1].rm_so; - len2 = match[2].rm_eo - match[2].rm_so; - - list = g_malloc(len1+len2+2); - memcpy(list, v + match[1].rm_so, len1); - if (len2) { - list[len1] = '@'; - memcpy(list+len1+1, v+match[2].rm_so, len2); - list[len1+len2+1]=0; - } else { - list[len1] = 0; - } - - return list; - } - } - - return NULL; -} - -/* ok, here's the address stuff, what a mess ... */ -struct _camel_header_address * -camel_header_address_new (void) -{ - struct _camel_header_address *h; - h = g_malloc0(sizeof(*h)); - h->type = HEADER_ADDRESS_NONE; - h->refcount = 1; - return h; -} - -struct _camel_header_address * -camel_header_address_new_name(const char *name, const char *addr) -{ - struct _camel_header_address *h; - h = camel_header_address_new(); - h->type = HEADER_ADDRESS_NAME; - h->name = g_strdup(name); - h->v.addr = g_strdup(addr); - return h; -} - -struct _camel_header_address * -camel_header_address_new_group (const char *name) -{ - struct _camel_header_address *h; - - h = camel_header_address_new(); - h->type = HEADER_ADDRESS_GROUP; - h->name = g_strdup(name); - return h; -} - -void -camel_header_address_ref(struct _camel_header_address *h) -{ - if (h) - h->refcount++; -} - -void -camel_header_address_unref(struct _camel_header_address *h) -{ - if (h) { - if (h->refcount <= 1) { - if (h->type == HEADER_ADDRESS_GROUP) { - camel_header_address_list_clear(&h->v.members); - } else if (h->type == HEADER_ADDRESS_NAME) { - g_free(h->v.addr); - } - g_free(h->name); - g_free(h); - } else { - h->refcount--; - } - } -} - -void -camel_header_address_set_name(struct _camel_header_address *h, const char *name) -{ - if (h) { - g_free(h->name); - h->name = g_strdup(name); - } -} - -void -camel_header_address_set_addr(struct _camel_header_address *h, const char *addr) -{ - if (h) { - if (h->type == HEADER_ADDRESS_NAME - || h->type == HEADER_ADDRESS_NONE) { - h->type = HEADER_ADDRESS_NAME; - g_free(h->v.addr); - h->v.addr = g_strdup(addr); - } else { - g_warning("Trying to set the address on a group"); - } - } -} - -void -camel_header_address_set_members(struct _camel_header_address *h, struct _camel_header_address *group) -{ - if (h) { - if (h->type == HEADER_ADDRESS_GROUP - || h->type == HEADER_ADDRESS_NONE) { - h->type = HEADER_ADDRESS_GROUP; - camel_header_address_list_clear(&h->v.members); - /* should this ref them? */ - h->v.members = group; - } else { - g_warning("Trying to set the members on a name, not group"); - } - } -} - -void -camel_header_address_add_member(struct _camel_header_address *h, struct _camel_header_address *member) -{ - if (h) { - if (h->type == HEADER_ADDRESS_GROUP - || h->type == HEADER_ADDRESS_NONE) { - h->type = HEADER_ADDRESS_GROUP; - camel_header_address_list_append(&h->v.members, member); - } - } -} - -void -camel_header_address_list_append_list(struct _camel_header_address **l, struct _camel_header_address **h) -{ - if (l) { - struct _camel_header_address *n = (struct _camel_header_address *)l; - - while (n->next) - n = n->next; - n->next = *h; - } -} - - -void -camel_header_address_list_append(struct _camel_header_address **l, struct _camel_header_address *h) -{ - if (h) { - camel_header_address_list_append_list(l, &h); - h->next = NULL; - } -} - -void -camel_header_address_list_clear(struct _camel_header_address **l) -{ - struct _camel_header_address *a, *n; - a = *l; - while (a) { - n = a->next; - camel_header_address_unref(a); - a = n; - } - *l = NULL; -} - -/* if encode is true, then the result is suitable for mailing, otherwise - the result is suitable for display only (and may not even be re-parsable) */ -static void -header_address_list_encode_append (GString *out, int encode, struct _camel_header_address *a) -{ - char *text; - - while (a) { - switch (a->type) { - case HEADER_ADDRESS_NAME: - if (encode) - text = camel_header_encode_phrase (a->name); - else - text = a->name; - if (text && *text) - g_string_append_printf (out, "%s <%s>", text, a->v.addr); - else - g_string_append (out, a->v.addr); - if (encode) - g_free (text); - break; - case HEADER_ADDRESS_GROUP: - if (encode) - text = camel_header_encode_phrase (a->name); - else - text = a->name; - g_string_append_printf (out, "%s: ", text); - header_address_list_encode_append (out, encode, a->v.members); - g_string_append_printf (out, ";"); - if (encode) - g_free (text); - break; - default: - g_warning ("Invalid address type"); - break; - } - a = a->next; - if (a) - g_string_append (out, ", "); - } -} - -char * -camel_header_address_list_encode (struct _camel_header_address *a) -{ - GString *out; - char *ret; - - if (a == NULL) - return NULL; - - out = g_string_new (""); - header_address_list_encode_append (out, TRUE, a); - ret = out->str; - g_string_free (out, FALSE); - - return ret; -} - -char * -camel_header_address_list_format (struct _camel_header_address *a) -{ - GString *out; - char *ret; - - if (a == NULL) - return NULL; - - out = g_string_new (""); - - header_address_list_encode_append (out, FALSE, a); - ret = out->str; - g_string_free (out, FALSE); - - return ret; -} - -char * -camel_header_address_fold (const char *in, size_t headerlen) -{ - size_t len, outlen; - const char *inptr = in, *space, *p, *n; - GString *out; - char *ret; - int i, needunfold = FALSE; - - if (in == NULL) - return NULL; - - /* first, check to see if we even need to fold */ - len = headerlen + 2; - p = in; - while (*p) { - n = strchr (p, '\n'); - if (n == NULL) { - len += strlen (p); - break; - } - - needunfold = TRUE; - len += n-p; - - if (len >= CAMEL_FOLD_SIZE) - break; - len = 0; - p = n + 1; - } - if (len < CAMEL_FOLD_SIZE) - return g_strdup (in); - - /* we need to fold, so first unfold (if we need to), then process */ - if (needunfold) - inptr = in = camel_header_unfold (in); - - out = g_string_new (""); - outlen = headerlen + 2; - while (*inptr) { - space = strchr (inptr, ' '); - if (space) { - len = space - inptr + 1; - } else { - len = strlen (inptr); - } - - d(printf("next word '%.*s'\n", len, inptr)); - - if (outlen + len > CAMEL_FOLD_SIZE) { - d(printf("outlen = %d wordlen = %d\n", outlen, len)); - /* strip trailing space */ - if (out->len > 0 && out->str[out->len-1] == ' ') - g_string_truncate (out, out->len-1); - g_string_append (out, "\n\t"); - outlen = 1; - } - - outlen += len; - for (i = 0; i < len; i++) { - g_string_append_c (out, inptr[i]); - } - - inptr += len; - } - ret = out->str; - g_string_free (out, FALSE); - - if (needunfold) - g_free ((char *)in); - - return ret; -} - -/* simple header folding */ -/* will work even if the header is already folded */ -char * -camel_header_fold(const char *in, size_t headerlen) -{ - size_t len, outlen, i; - const char *inptr = in, *space, *p, *n; - GString *out; - char *ret; - int needunfold = FALSE; - - if (in == NULL) - return NULL; - - /* first, check to see if we even need to fold */ - len = headerlen + 2; - p = in; - while (*p) { - n = strchr(p, '\n'); - if (n == NULL) { - len += strlen (p); - break; - } - - needunfold = TRUE; - len += n-p; - - if (len >= CAMEL_FOLD_SIZE) - break; - len = 0; - p = n + 1; - } - if (len < CAMEL_FOLD_SIZE) - return g_strdup(in); - - /* we need to fold, so first unfold (if we need to), then process */ - if (needunfold) - inptr = in = camel_header_unfold(in); - - out = g_string_new(""); - outlen = headerlen+2; - while (*inptr) { - space = strchr(inptr, ' '); - if (space) { - len = space-inptr+1; - } else { - len = strlen(inptr); - } - d(printf("next word '%.*s'\n", len, inptr)); - if (outlen + len > CAMEL_FOLD_SIZE) { - d(printf("outlen = %d wordlen = %d\n", outlen, len)); - /* strip trailing space */ - if (out->len > 0 && out->str[out->len-1] == ' ') - g_string_truncate(out, out->len-1); - g_string_append(out, "\n\t"); - outlen = 1; - /* check for very long words, just cut them up */ - while (outlen+len > CAMEL_FOLD_MAX_SIZE) { - for (i=0;istr; - g_string_free(out, FALSE); - - if (needunfold) - g_free((char *)in); - - return ret; -} - -char * -camel_header_unfold(const char *in) -{ - char *out = g_malloc(strlen(in)+1); - const char *inptr = in; - char c, *o = out; - - o = out; - while ((c = *inptr++)) { - if (c == '\n') { - if (camel_mime_is_lwsp(*inptr)) { - do { - inptr++; - } while (camel_mime_is_lwsp(*inptr)); - *o++ = ' '; - } else { - *o++ = c; - } - } else { - *o++ = c; - } - } - *o = 0; - - return out; -} - -void -camel_mime_utils_init(void) -{ - int i, errcode, regex_compilation_failed=0; - - /* Init tables */ - header_decode_init(); - base64_init(); - - /* precompile regex's for speed at runtime */ - for (i = 0; i < sizeof(mail_list_magic) / sizeof(mail_list_magic[0]); i++) { - errcode = regcomp(&mail_list_magic[i].regex, mail_list_magic[i].pattern, REG_EXTENDED|REG_ICASE); - if (errcode != 0) { - char *errstr; - size_t len; - - len = regerror(errcode, &mail_list_magic[i].regex, NULL, 0); - errstr = g_malloc0(len + 1); - regerror(errcode, &mail_list_magic[i].regex, errstr, len); - - g_warning("Internal error, compiling regex failed: %s: %s", mail_list_magic[i].pattern, errstr); - g_free(errstr); - regex_compilation_failed++; - } - } - - g_assert(regex_compilation_failed == 0); -} diff --git a/camel/camel-mime-utils.h b/camel/camel-mime-utils.h deleted file mode 100644 index efa5b7835a..0000000000 --- a/camel/camel-mime-utils.h +++ /dev/null @@ -1,273 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000-2003 Ximian Inc. - * - * Authors: Michael Zucchi - * Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_MIME_UTILS_H -#define _CAMEL_MIME_UTILS_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include - -/* maximum recommended size of a line from camel_header_fold() */ -#define CAMEL_FOLD_SIZE (77) -/* maximum hard size of a line from camel_header_fold() */ -#define CAMEL_FOLD_MAX_SIZE (998) - -#define CAMEL_UUDECODE_STATE_INIT (0) -#define CAMEL_UUDECODE_STATE_BEGIN (1 << 16) -#define CAMEL_UUDECODE_STATE_END (1 << 17) -#define CAMEL_UUDECODE_STATE_MASK (CAMEL_UUDECODE_STATE_BEGIN | CAMEL_UUDECODE_STATE_END) - -/* note, if you change this, make sure you change the 'encodings' array in camel-mime-part.c */ -typedef enum _CamelTransferEncoding { - CAMEL_TRANSFER_ENCODING_DEFAULT, - CAMEL_TRANSFER_ENCODING_7BIT, - CAMEL_TRANSFER_ENCODING_8BIT, - CAMEL_TRANSFER_ENCODING_BASE64, - CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE, - CAMEL_TRANSFER_ENCODING_BINARY, - CAMEL_TRANSFER_ENCODING_UUENCODE, - CAMEL_TRANSFER_NUM_ENCODINGS -} CamelTransferEncoding; - -/* a list of references for this message */ -struct _camel_header_references { - struct _camel_header_references *next; - char *id; -}; - -struct _camel_header_param { - struct _camel_header_param *next; - char *name; - char *value; -}; - -/* describes a content-type */ -typedef struct { - char *type; - char *subtype; - struct _camel_header_param *params; - unsigned int refcount; -} CamelContentType; - -/* a raw rfc822 header */ -/* the value MUST be US-ASCII */ -struct _camel_header_raw { - struct _camel_header_raw *next; - char *name; - char *value; - int offset; /* in file, if known */ -}; - -typedef struct _CamelContentDisposition { - char *disposition; - struct _camel_header_param *params; - unsigned int refcount; -} CamelContentDisposition; - -enum _camel_header_address_t { - HEADER_ADDRESS_NONE, /* uninitialised */ - HEADER_ADDRESS_NAME, - HEADER_ADDRESS_GROUP -}; - -struct _camel_header_address { - struct _camel_header_address *next; - enum _camel_header_address_t type; - char *name; - union { - char *addr; - struct _camel_header_address *members; - } v; - unsigned int refcount; -}; - -/* MUST be called before everything else */ -void camel_mime_utils_init(void); - -/* Address lists */ -struct _camel_header_address *camel_header_address_new (void); -struct _camel_header_address *camel_header_address_new_name (const char *name, const char *addr); -struct _camel_header_address *camel_header_address_new_group (const char *name); -void camel_header_address_ref (struct _camel_header_address *); -void camel_header_address_unref (struct _camel_header_address *); -void camel_header_address_set_name (struct _camel_header_address *, const char *name); -void camel_header_address_set_addr (struct _camel_header_address *, const char *addr); -void camel_header_address_set_members (struct _camel_header_address *, struct _camel_header_address *group); -void camel_header_address_add_member (struct _camel_header_address *, struct _camel_header_address *member); -void camel_header_address_list_append_list (struct _camel_header_address **l, struct _camel_header_address **h); -void camel_header_address_list_append (struct _camel_header_address **, struct _camel_header_address *); -void camel_header_address_list_clear (struct _camel_header_address **); - -struct _camel_header_address *camel_header_address_decode (const char *in, const char *charset); -struct _camel_header_address *camel_header_mailbox_decode (const char *in, const char *charset); -/* for mailing */ -char *camel_header_address_list_encode (struct _camel_header_address *a); -/* for display */ -char *camel_header_address_list_format (struct _camel_header_address *a); - -/* structured header prameters */ -struct _camel_header_param *camel_header_param_list_decode (const char *in); -char *camel_header_param (struct _camel_header_param *p, const char *name); -struct _camel_header_param *camel_header_set_param (struct _camel_header_param **l, const char *name, const char *value); -void camel_header_param_list_format_append (GString *out, struct _camel_header_param *p); -char *camel_header_param_list_format (struct _camel_header_param *p); -void camel_header_param_list_free (struct _camel_header_param *p); - -/* Content-Type header */ -CamelContentType *camel_content_type_new (const char *type, const char *subtype); -CamelContentType *camel_content_type_decode (const char *in); -void camel_content_type_unref (CamelContentType *ct); -void camel_content_type_ref (CamelContentType *ct); -const char *camel_content_type_param (CamelContentType *t, const char *name); -void camel_content_type_set_param (CamelContentType *t, const char *name, const char *value); -int camel_content_type_is (CamelContentType *ct, const char *type, const char *subtype); -char *camel_content_type_format (CamelContentType *ct); -char *camel_content_type_simple (CamelContentType *ct); - -/* DEBUGGING function */ -void camel_content_type_dump (CamelContentType *ct); - -/* Content-Disposition header */ -CamelContentDisposition *camel_content_disposition_decode (const char *in); -void camel_content_disposition_ref (CamelContentDisposition *); -void camel_content_disposition_unref (CamelContentDisposition *); -char *camel_content_disposition_format (CamelContentDisposition *d); - -/* decode the contents of a content-encoding header */ -char *camel_content_transfer_encoding_decode (const char *in); - -/* raw headers */ -void camel_header_raw_append (struct _camel_header_raw **list, const char *name, const char *value, int offset); -void camel_header_raw_append_parse (struct _camel_header_raw **list, const char *header, int offset); -const char *camel_header_raw_find (struct _camel_header_raw **list, const char *name, int *offset); -const char *camel_header_raw_find_next (struct _camel_header_raw **list, const char *name, int *offset, const char *last); -void camel_header_raw_replace (struct _camel_header_raw **list, const char *name, const char *value, int offset); -void camel_header_raw_remove (struct _camel_header_raw **list, const char *name); -void camel_header_raw_fold (struct _camel_header_raw **list); -void camel_header_raw_clear (struct _camel_header_raw **list); - -char *camel_header_raw_check_mailing_list (struct _camel_header_raw **list); - -/* fold a header */ -char *camel_header_address_fold (const char *in, size_t headerlen); -char *camel_header_fold (const char *in, size_t headerlen); -char *camel_header_unfold (const char *in); - -/* decode a header which is a simple token */ -char *camel_header_token_decode (const char *in); - -int camel_header_decode_int (const char **in); - -/* decode/encode a string type, like a subject line */ -char *camel_header_decode_string (const char *in, const char *default_charset); -char *camel_header_encode_string (const unsigned char *in); - -/* encode a phrase, like the real name of an address */ -char *camel_header_encode_phrase (const unsigned char *in); - -/* decode an email date field into a GMT time, + optional offset */ -time_t camel_header_decode_date (const char *in, int *saveoffset); -char *camel_header_format_date (time_t time, int offset); - -/* decode a message id */ -char *camel_header_msgid_decode (const char *in); -char *camel_header_contentid_decode (const char *in); - -/* generate msg id */ -char *camel_header_msgid_generate (void); - -/* decode a References or In-Reply-To header */ -struct _camel_header_references *camel_header_references_inreplyto_decode (const char *in); -struct _camel_header_references *camel_header_references_decode (const char *in); -void camel_header_references_list_clear (struct _camel_header_references **list); -void camel_header_references_list_append_asis (struct _camel_header_references **list, char *ref); -int camel_header_references_list_size (struct _camel_header_references **list); -struct _camel_header_references *camel_header_references_dup (const struct _camel_header_references *list); - -/* decode content-location */ -char *camel_header_location_decode (const char *in); - -const char *camel_transfer_encoding_to_string (CamelTransferEncoding encoding); -CamelTransferEncoding camel_transfer_encoding_from_string (const char *string); - -/* decode the mime-type header */ -void camel_header_mime_decode (const char *in, int *maj, int *min); - -/* do incremental base64/quoted-printable (de/en)coding */ -size_t camel_base64_decode_step (unsigned char *in, size_t len, unsigned char *out, int *state, unsigned int *save); - -size_t camel_base64_encode_step (unsigned char *in, size_t len, gboolean break_lines, unsigned char *out, int *state, int *save); -size_t camel_base64_encode_close (unsigned char *in, size_t len, gboolean break_lines, unsigned char *out, int *state, int *save); - -size_t camel_uudecode_step (unsigned char *in, size_t len, unsigned char *out, int *state, guint32 *save); - -size_t camel_uuencode_step (unsigned char *in, size_t len, unsigned char *out, unsigned char *uubuf, int *state, - guint32 *save); -size_t camel_uuencode_close (unsigned char *in, size_t len, unsigned char *out, unsigned char *uubuf, int *state, - guint32 *save); - -size_t camel_quoted_decode_step (unsigned char *in, size_t len, unsigned char *out, int *savestate, int *saveme); - -size_t camel_quoted_encode_step (unsigned char *in, size_t len, unsigned char *out, int *state, int *save); -size_t camel_quoted_decode_close (unsigned char *in, size_t len, unsigned char *out, int *state, int *save); - -char *camel_base64_encode_simple (const char *data, size_t len); -size_t camel_base64_decode_simple (char *data, size_t len); - -/* camel ctype type functions for rfc822/rfc2047/other, which are non-locale specific */ -enum { - CAMEL_MIME_IS_CTRL = 1<<0, - CAMEL_MIME_IS_LWSP = 1<<1, - CAMEL_MIME_IS_TSPECIAL = 1<<2, - CAMEL_MIME_IS_SPECIAL = 1<<3, - CAMEL_MIME_IS_SPACE = 1<<4, - CAMEL_MIME_IS_DSPECIAL = 1<<5, - CAMEL_MIME_IS_QPSAFE = 1<<6, - CAMEL_MIME_IS_ESAFE = 1<<7, /* encoded word safe */ - CAMEL_MIME_IS_PSAFE = 1<<8, /* encoded word in phrase safe */ -}; - -extern unsigned short camel_mime_special_table[256]; - -#define camel_mime_is_ctrl(x) ((camel_mime_special_table[(unsigned char)(x)] & CAMEL_MIME_IS_CTRL) != 0) -#define camel_mime_is_lwsp(x) ((camel_mime_special_table[(unsigned char)(x)] & CAMEL_MIME_IS_LWSP) != 0) -#define camel_mime_is_tspecial(x) ((camel_mime_special_table[(unsigned char)(x)] & CAMEL_MIME_IS_TSPECIAL) != 0) -#define camel_mime_is_type(x, t) ((camel_mime_special_table[(unsigned char)(x)] & (t)) != 0) -#define camel_mime_is_ttoken(x) ((camel_mime_special_table[(unsigned char)(x)] & (CAMEL_MIME_IS_TSPECIAL|CAMEL_MIME_IS_LWSP|CAMEL_MIME_IS_CTRL)) == 0) -#define camel_mime_is_atom(x) ((camel_mime_special_table[(unsigned char)(x)] & (CAMEL_MIME_IS_SPECIAL|CAMEL_MIME_IS_SPACE|CAMEL_MIME_IS_CTRL)) == 0) -#define camel_mime_is_dtext(x) ((camel_mime_special_table[(unsigned char)(x)] & CAMEL_MIME_IS_DSPECIAL) == 0) -#define camel_mime_is_fieldname(x) ((camel_mime_special_table[(unsigned char)(x)] & (CAMEL_MIME_IS_CTRL|CAMEL_MIME_IS_SPACE)) == 0) -#define camel_mime_is_qpsafe(x) ((camel_mime_special_table[(unsigned char)(x)] & CAMEL_MIME_IS_QPSAFE) != 0) -#define camel_mime_is_especial(x) ((camel_mime_special_table[(unsigned char)(x)] & CAMEL_MIME_IS_ESPECIAL) != 0) -#define camel_mime_is_psafe(x) ((camel_mime_special_table[(unsigned char)(x)] & CAMEL_MIME_IS_PSAFE) != 0) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_MIME_UTILS_H */ diff --git a/camel/camel-movemail.c b/camel/camel-movemail.c deleted file mode 100644 index 70807195e5..0000000000 --- a/camel/camel-movemail.c +++ /dev/null @@ -1,542 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-movemail.c: mbox copying function */ - -/* - * Author: - * Dan Winship - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_ALLOCA_H -#include -#endif - -#include "camel-movemail.h" -#include "camel-exception.h" - -#include "camel-mime-parser.h" -#include "camel-mime-filter.h" -#include "camel-mime-filter-from.h" - -#include "camel-lock-client.h" - -#define d(x) - -#ifdef MOVEMAIL_PATH -#include - -static void movemail_external (const char *source, const char *dest, - CamelException *ex); -#endif - -#ifdef HAVE_BROKEN_SPOOL -static int camel_movemail_copy_filter(int fromfd, int tofd, off_t start, size_t bytes, CamelMimeFilter *filter); -static int camel_movemail_solaris (int oldsfd, int dfd, CamelException *ex); -#else -/* these could probably be exposed as a utility? (but only mbox needs it) */ -static int camel_movemail_copy_file(int sfd, int dfd, CamelException *ex); -#endif - -#if 0 -static int camel_movemail_copy(int fromfd, int tofd, off_t start, size_t bytes); -#endif - -/** - * camel_movemail: Copy an mbox file from a shared spool directory to a - * new folder in a Camel store - * @source: source file - * @dest: destination file - * @ex: a CamelException - * - * This copies an mbox file from a shared directory with multiple - * readers and writers into a private (presumably Camel-controlled) - * directory. Dot locking is used on the source file (but not the - * destination). - * - * Return Value: Returns -1 on error. - **/ -int -camel_movemail(const char *source, const char *dest, CamelException *ex) -{ - int lockid = -1; - int res = -1; - int sfd, dfd; - struct stat st; - - camel_exception_clear(ex); - - /* Stat and then open the spool file. If it doesn't exist or - * is empty, the user has no mail. (There's technically a race - * condition here in that an MDA might have just now locked it - * to deliver a message, but we don't care. In that case, - * assuming it's unlocked is equivalent to pretending we were - * called a fraction earlier.) - */ - if (stat (source, &st) == -1) { - if (errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not check mail file %s: %s"), - source, g_strerror (errno)); - } - return -1; - } - - if (st.st_size == 0) - return 0; - - /* open files */ - sfd = open (source, O_RDWR); - if (sfd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open mail file %s: %s"), - source, g_strerror (errno)); - return -1; - } - - dfd = open (dest, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR); - if (dfd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open temporary mail " - "file %s: %s"), dest, - g_strerror (errno)); - close (sfd); - return -1; - } - - /* lock our source mailbox */ - lockid = camel_lock_helper_lock(source, ex); - if (lockid == -1) { - close(sfd); - close(dfd); - return -1; - } - -#ifdef HAVE_BROKEN_SPOOL - res = camel_movemail_solaris(sfd, dfd, ex); -#else - res = camel_movemail_copy_file(sfd, dfd, ex); -#endif - - /* If no errors occurred copying the data, and we successfully - * close the destination file, then truncate the source file. - */ - if (res != -1) { - if (close (dfd) == 0) { - ftruncate (sfd, 0); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to store mail in temp file %s: %s"), - dest, g_strerror (errno)); - res = -1; - } - } else - close (dfd); - close (sfd); - - camel_lock_helper_unlock(lockid); - - return res; -} - -#ifdef MOVEMAIL_PATH -static void -movemail_external (const char *source, const char *dest, CamelException *ex) -{ - sigset_t mask, omask; - pid_t pid; - int fd[2], len = 0, nread, status; - char buf[BUFSIZ], *output = NULL; - - /* Block SIGCHLD so the app can't mess us up. */ - sigemptyset (&mask); - sigaddset (&mask, SIGCHLD); - sigprocmask (SIG_BLOCK, &mask, &omask); - - if (pipe (fd) == -1) { - sigprocmask (SIG_SETMASK, &omask, NULL); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create pipe: %s"), - g_strerror (errno)); - return; - } - - pid = fork (); - switch (pid) { - case -1: - close (fd[0]); - close (fd[1]); - sigprocmask (SIG_SETMASK, &omask, NULL); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not fork: %s"), - g_strerror (errno)); - return; - - case 0: - /* Child */ - close (fd[0]); - close (STDIN_FILENO); - dup2 (fd[1], STDOUT_FILENO); - dup2 (fd[1], STDERR_FILENO); - - execl (MOVEMAIL_PATH, MOVEMAIL_PATH, source, dest, NULL); - _exit (255); - break; - - default: - break; - } - - /* Parent */ - close (fd[1]); - - /* Read movemail's output. */ - while ((nread = read (fd[0], buf, sizeof (buf))) > 0) { - output = g_realloc (output, len + nread + 1); - memcpy (output + len, buf, nread); - len += nread; - output[len] = '\0'; - } - close (fd[0]); - - /* Now get the exit status. */ - while (waitpid (pid, &status, 0) == -1 && errno == EINTR) - ; - sigprocmask (SIG_SETMASK, &omask, NULL); - - if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Movemail program failed: %s"), - output ? output : _("(Unknown error)")); - } - g_free (output); -} -#endif - -#ifndef HAVE_BROKEN_SPOOL -static int -camel_movemail_copy_file(int sfd, int dfd, CamelException *ex) -{ - int nread, nwrote; - char buf[4096]; - - while (1) { - int written = 0; - - nread = read (sfd, buf, sizeof (buf)); - if (nread == 0) - break; - else if (nread == -1) { - if (errno == EINTR) - continue; - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Error reading mail file: %s"), - g_strerror (errno)); - return -1; - } - - while (nread) { - nwrote = write (dfd, buf + written, nread); - if (nwrote == -1) { - if (errno == EINTR) - continue; /* continues inner loop */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Error writing mail temp file: %s"), - g_strerror (errno)); - return -1; - } - written += nwrote; - nread -= nwrote; - } - } - - return 0; -} -#endif - -#if 0 -static int -camel_movemail_copy(int fromfd, int tofd, off_t start, size_t bytes) -{ - char buffer[4096]; - int written = 0; - - d(printf("writing %d bytes ... ", bytes)); - - if (lseek(fromfd, start, SEEK_SET) != start) - return -1; - - while (bytes>0) { - int toread, towrite; - - toread = bytes; - if (bytes>4096) - toread = 4096; - else - toread = bytes; - do { - towrite = read(fromfd, buffer, toread); - } while (towrite == -1 && errno == EINTR); - - if (towrite == -1) - return -1; - - /* check for 'end of file' */ - if (towrite == 0) { - d(printf("end of file?\n")); - break; - } - - do { - toread = write(tofd, buffer, towrite); - } while (toread == -1 && errno == EINTR); - - if (toread == -1) - return -1; - - written += toread; - bytes -= toread; - } - - d(printf("written %d bytes\n", written)); - - return written; -} -#endif - -#define PRE_SIZE (32) - -#ifdef HAVE_BROKEN_SPOOL -static int -camel_movemail_copy_filter(int fromfd, int tofd, off_t start, size_t bytes, CamelMimeFilter *filter) -{ - char buffer[4096+PRE_SIZE]; - int written = 0; - char *filterbuffer; - int filterlen, filterpre; - - d(printf("writing %d bytes ... ", bytes)); - - camel_mime_filter_reset(filter); - - if (lseek(fromfd, start, SEEK_SET) != start) - return -1; - - while (bytes>0) { - int toread, towrite; - - toread = bytes; - if (bytes>4096) - toread = 4096; - else - toread = bytes; - do { - towrite = read(fromfd, buffer+PRE_SIZE, toread); - } while (towrite == -1 && errno == EINTR); - - if (towrite == -1) - return -1; - - d(printf("read %d unfiltered bytes\n", towrite)); - - /* check for 'end of file' */ - if (towrite == 0) { - d(printf("end of file?\n")); - camel_mime_filter_complete(filter, buffer+PRE_SIZE, towrite, PRE_SIZE, - &filterbuffer, &filterlen, &filterpre); - towrite = filterlen; - if (towrite == 0) - break; - } else { - camel_mime_filter_filter(filter, buffer+PRE_SIZE, towrite, PRE_SIZE, - &filterbuffer, &filterlen, &filterpre); - towrite = filterlen; - } - - d(printf("writing %d filtered bytes\n", towrite)); - - do { - toread = write(tofd, filterbuffer, towrite); - } while (toread == -1 && errno == EINTR); - - if (toread == -1) - return -1; - - written += toread; - bytes -= toread; - } - - d(printf("written %d bytes\n", written)); - - return written; -} - -/* write the headers back out again, but not he Content-Length header, because we dont - want to maintain it! */ -static int -solaris_header_write(int fd, struct _camel_header_raw *header) -{ - struct iovec iv[4]; - int outlen = 0, len; - - iv[1].iov_base = ":"; - iv[1].iov_len = 1; - iv[3].iov_base = "\n"; - iv[3].iov_len = 1; - - while (header) { - if (strcasecmp(header->name, "Content-Length")) { - iv[0].iov_base = header->name; - iv[0].iov_len = strlen(header->name); - iv[2].iov_base = header->value; - iv[2].iov_len = strlen(header->value); - - do { - len = writev(fd, iv, 4); - } while (len == -1 && errno == EINTR); - - if (len == -1) - return -1; - outlen += len; - } - header = header->next; - } - - do { - len = write(fd, "\n", 1); - } while (len == -1 && errno == EINTR); - - if (len == -1) - return -1; - - outlen += 1; - - d(printf("Wrote %d bytes of headers\n", outlen)); - - return outlen; -} - -/* Well, since Solaris is a tad broken wrt its 'mbox' folder format, - we must convert it to a real mbox format. Thankfully this is - mostly pretty easy */ -static int -camel_movemail_solaris (int oldsfd, int dfd, CamelException *ex) -{ - CamelMimeParser *mp; - char *buffer; - int len; - int sfd; - CamelMimeFilterFrom *ffrom; - int ret = 1; - char *from = NULL; - - /* need to dup as the mime parser will close on finish */ - sfd = dup(oldsfd); - if (sfd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Error copying mail temp file: %s"), - g_strerror (errno)); - return -1; - } - - mp = camel_mime_parser_new(); - camel_mime_parser_scan_from(mp, TRUE); - camel_mime_parser_init_with_fd(mp, sfd); - - ffrom = camel_mime_filter_from_new(); - - while (camel_mime_parser_step(mp, &buffer, &len) == CAMEL_MIME_PARSER_STATE_FROM) { - g_assert(camel_mime_parser_from_line(mp)); - from = g_strdup(camel_mime_parser_from_line(mp)); - if (camel_mime_parser_step(mp, &buffer, &len) != CAMEL_MIME_PARSER_STATE_FROM_END) { - const char *cl; - int length; - int start, body; - off_t newpos; - - ret = 0; - - start = camel_mime_parser_tell_start_from(mp); - body = camel_mime_parser_tell(mp); - - if (write(dfd, from, strlen(from)) != strlen(from)) - goto fail; - - /* write out headers, but NOT content-length header */ - if (solaris_header_write(dfd, camel_mime_parser_headers_raw(mp)) == -1) - goto fail; - - cl = camel_mime_parser_header(mp, "content-length", NULL); - if (cl == NULL) { - g_warning("Required Content-Length header is missing from solaris mail box @ %d", (int)camel_mime_parser_tell(mp)); - camel_mime_parser_drop_step(mp); - camel_mime_parser_drop_step(mp); - camel_mime_parser_step(mp, &buffer, &len); - camel_mime_parser_unstep(mp); - length = camel_mime_parser_tell_start_from(mp) - body; - newpos = -1; - } else { - length = atoi(cl); - camel_mime_parser_drop_step(mp); - camel_mime_parser_drop_step(mp); - newpos = length+body; - } - /* copy body->length converting From lines */ - if (camel_movemail_copy_filter(sfd, dfd, body, length, (CamelMimeFilter *)ffrom) == -1) - goto fail; - if (newpos != -1) - camel_mime_parser_seek(mp, newpos, SEEK_SET); - } else { - g_error("Inalid parser state: %d", camel_mime_parser_state(mp)); - } - g_free(from); - } - - camel_object_unref((CamelObject *)mp); - camel_object_unref((CamelObject *)ffrom); - - return ret; - -fail: - g_free(from); - - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Error copying mail temp file: %s"), - g_strerror (errno)); - - - camel_object_unref((CamelObject *)mp); - camel_object_unref((CamelObject *)ffrom); - - return -1; -} -#endif /* HAVE_BROKEN_SPOOL */ - diff --git a/camel/camel-movemail.h b/camel/camel-movemail.h deleted file mode 100644 index 3e5206f672..0000000000 --- a/camel/camel-movemail.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-movemail.h: mbox copy function */ - -/* - * Author: - * Dan Winship - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_MOVEMAIL_H -#define CAMEL_MOVEMAIL_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include - -int camel_movemail (const char *source, const char *dest, CamelException *ex); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_MOVEMAIL_H */ diff --git a/camel/camel-multipart-encrypted.c b/camel/camel-multipart-encrypted.c deleted file mode 100644 index aa036bec23..0000000000 --- a/camel/camel-multipart-encrypted.c +++ /dev/null @@ -1,273 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "camel-multipart-encrypted.h" -#include "camel-mime-filter-crlf.h" -#include "camel-stream-filter.h" -#include "camel-stream-mem.h" -#include "camel-stream-fs.h" -#include "camel-mime-utils.h" -#include "camel-mime-part.h" - -static void camel_multipart_encrypted_class_init (CamelMultipartEncryptedClass *klass); -static void camel_multipart_encrypted_init (gpointer object, gpointer klass); -static void camel_multipart_encrypted_finalize (CamelObject *object); - -static void set_mime_type_field (CamelDataWrapper *data_wrapper, CamelContentType *mime_type); - - -static CamelMultipartClass *parent_class = NULL; - - -CamelType -camel_multipart_encrypted_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_multipart_get_type (), - "CamelMultipartEncrypted", - sizeof (CamelMultipartEncrypted), - sizeof (CamelMultipartEncryptedClass), - (CamelObjectClassInitFunc) camel_multipart_encrypted_class_init, - NULL, - (CamelObjectInitFunc) camel_multipart_encrypted_init, - (CamelObjectFinalizeFunc) camel_multipart_encrypted_finalize); - } - - return type; -} - - -static void -camel_multipart_encrypted_class_init (CamelMultipartEncryptedClass *klass) -{ - CamelDataWrapperClass *camel_data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (klass); - - parent_class = (CamelMultipartClass *) camel_multipart_get_type (); - - /* virtual method overload */ - camel_data_wrapper_class->set_mime_type_field = set_mime_type_field; -} - -static void -camel_multipart_encrypted_init (gpointer object, gpointer klass) -{ - CamelMultipartEncrypted *multipart = (CamelMultipartEncrypted *) object; - - camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart), "multipart/encrypted"); - - multipart->decrypted = NULL; -} - -static void -camel_multipart_encrypted_finalize (CamelObject *object) -{ - CamelMultipartEncrypted *mpe = (CamelMultipartEncrypted *) object; - - g_free (mpe->protocol); - - if (mpe->decrypted) - camel_object_unref (mpe->decrypted); -} - -/* we snoop the mime type to get the protocol */ -static void -set_mime_type_field (CamelDataWrapper *data_wrapper, CamelContentType *mime_type) -{ - CamelMultipartEncrypted *mpe = (CamelMultipartEncrypted *) data_wrapper; - - if (mime_type) { - const char *protocol; - - protocol = camel_content_type_param (mime_type, "protocol"); - g_free (mpe->protocol); - mpe->protocol = g_strdup (protocol); - } - - ((CamelDataWrapperClass *) parent_class)->set_mime_type_field (data_wrapper, mime_type); -} - - -/** - * camel_multipart_encrypted_new: - * - * Create a new CamelMultipartEncrypted object. - * - * A MultipartEncrypted should be used to store and create parts of - * type "multipart/encrypted". - * - * Returns a new CamelMultipartEncrypted - **/ -CamelMultipartEncrypted * -camel_multipart_encrypted_new (void) -{ - CamelMultipartEncrypted *multipart; - - multipart = (CamelMultipartEncrypted *) camel_object_new (CAMEL_MULTIPART_ENCRYPTED_TYPE); - - return multipart; -} - - -int -camel_multipart_encrypted_encrypt (CamelMultipartEncrypted *mpe, CamelMimePart *content, - CamelCipherContext *cipher, const char *userid, - GPtrArray *recipients, CamelException *ex) -{ - abort(); - -#if 0 - CamelMimePart *version_part, *encrypted_part; - CamelContentType *mime_type; - CamelDataWrapper *wrapper; - CamelStream *stream; - - g_return_val_if_fail (CAMEL_IS_MULTIPART_ENCRYPTED (mpe), -1); - g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (cipher), -1); - g_return_val_if_fail (cipher->encrypt_protocol != NULL, -1); - g_return_val_if_fail (CAMEL_IS_MIME_PART (content), -1); - - /* encrypt the content stream */ - encrypted_part = camel_mime_part_new(); - if (camel_cipher_encrypt (cipher, userid, recipients, content, encrypted_part, ex) == -1) { - camel_object_unref(encrypted_part); - return -1; - } - - /* construct the version part */ - stream = camel_stream_mem_new (); - camel_stream_write_string (stream, "Version: 1\n"); - camel_stream_reset (stream); - - version_part = camel_mime_part_new (); - wrapper = camel_data_wrapper_new (); - camel_data_wrapper_set_mime_type (wrapper, cipher->encrypt_protocol); - camel_data_wrapper_construct_from_stream (wrapper, stream); - camel_object_unref (stream); - camel_medium_set_content_object ((CamelMedium *) version_part, wrapper); - camel_object_unref (wrapper); - - /* save the version and encrypted parts */ - /* FIXME: make sure there aren't any other parts?? */ - camel_multipart_add_part (CAMEL_MULTIPART (mpe), version_part); - camel_object_unref (version_part); - camel_multipart_add_part (CAMEL_MULTIPART (mpe), encrypted_part); - camel_object_unref (encrypted_part); - - /* cache the decrypted content */ - camel_object_ref (content); - mpe->decrypted = content; - - /* set the content-type params for this multipart/encrypted part */ - mime_type = camel_content_type_new ("multipart", "encrypted"); - camel_content_type_set_param (mime_type, "protocol", cipher->encrypt_protocol); - camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (mpe), mime_type); - camel_content_type_unref (mime_type); - camel_multipart_set_boundary ((CamelMultipart *) mpe, NULL); -#endif - - return 0; -} - - -CamelMimePart * -camel_multipart_encrypted_decrypt (CamelMultipartEncrypted *mpe, - CamelCipherContext *cipher, - CamelException *ex) -{ - CamelMimePart *version_part, *encrypted_part, *decrypted_part; - CamelContentType *mime_type; - CamelCipherValidity *valid; - CamelDataWrapper *wrapper; - const char *protocol; - char *content_type; - - g_return_val_if_fail (CAMEL_IS_MULTIPART_ENCRYPTED (mpe), NULL); - g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (cipher), NULL); - g_return_val_if_fail (cipher->encrypt_protocol != NULL, NULL); - - if (mpe->decrypted) { - /* we seem to have already decrypted the part */ - camel_object_ref (mpe->decrypted); - return mpe->decrypted; - } - - protocol = mpe->protocol; - - if (protocol) { - /* make sure the protocol matches the cipher encrypt protocol */ - if (g_ascii_strcasecmp (cipher->encrypt_protocol, protocol) != 0) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to decrypt MIME part: protocol error")); - - return NULL; - } - } else { - /* *shrug* - I guess just go on as if they match? */ - protocol = cipher->encrypt_protocol; - } - - /* make sure the protocol matches the version part's content-type */ - version_part = camel_multipart_get_part (CAMEL_MULTIPART (mpe), CAMEL_MULTIPART_ENCRYPTED_VERSION); - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (version_part)); - content_type = camel_data_wrapper_get_mime_type (wrapper); - if (g_ascii_strcasecmp (content_type, protocol) != 0) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to decrypt MIME part: protocol error")); - - g_free (content_type); - - return NULL; - } - g_free (content_type); - - /* get the encrypted part (second part) */ - encrypted_part = camel_multipart_get_part (CAMEL_MULTIPART (mpe), CAMEL_MULTIPART_ENCRYPTED_CONTENT); - mime_type = camel_mime_part_get_content_type (encrypted_part); - if (!camel_content_type_is (mime_type, "application", "octet-stream")) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to decrypt MIME part: invalid structure")); - return NULL; - } - - decrypted_part = camel_mime_part_new(); - valid = camel_cipher_decrypt(cipher, encrypted_part, decrypted_part, ex); - if (valid) { - camel_object_ref(decrypted_part); - mpe->decrypted = decrypted_part; - camel_cipher_validity_free(valid); - } else { - camel_object_ref(decrypted_part); - decrypted_part = NULL; - } - - return decrypted_part; -} diff --git a/camel/camel-multipart-encrypted.h b/camel/camel-multipart-encrypted.h deleted file mode 100644 index 94bcb792cf..0000000000 --- a/camel/camel-multipart-encrypted.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __CAMEL_MULTIPART_ENCRYPTED_H__ -#define __CAMEL_MULTIPART_ENCRYPTED_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include - -#define CAMEL_MULTIPART_ENCRYPTED_TYPE (camel_multipart_encrypted_get_type ()) -#define CAMEL_MULTIPART_ENCRYPTED(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MULTIPART_ENCRYPTED_TYPE, CamelMultipartEncrypted)) -#define CAMEL_MULTIPART_ENCRYPTED_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MULTIPART_ENCRYPTED_TYPE, CamelMultipartEncryptedClass)) -#define CAMEL_IS_MULTIPART_ENCRYPTED(o) (CAMEL_CHECK_TYPE((o), CAMEL_MULTIPART_ENCRYPTED_TYPE)) - -typedef struct _CamelMultipartEncrypted CamelMultipartEncrypted; -typedef struct _CamelMultipartEncryptedClass CamelMultipartEncryptedClass; - -/* 'handy' enums for getting the internal parts of the multipart */ -enum { - CAMEL_MULTIPART_ENCRYPTED_VERSION, - CAMEL_MULTIPART_ENCRYPTED_CONTENT, -}; - -struct _CamelMultipartEncrypted { - CamelMultipart parent_object; - - CamelMimePart *version; - CamelMimePart *content; - CamelMimePart *decrypted; - - char *protocol; -}; - - -struct _CamelMultipartEncryptedClass { - CamelMultipartClass parent_class; - -}; - - -CamelType camel_multipart_encrypted_get_type (void); - - -CamelMultipartEncrypted *camel_multipart_encrypted_new (void); - -int camel_multipart_encrypted_encrypt (CamelMultipartEncrypted *mpe, CamelMimePart *content, - CamelCipherContext *cipher, const char *userid, - GPtrArray *recipients, CamelException *ex); - -CamelMimePart *camel_multipart_encrypted_decrypt (CamelMultipartEncrypted *mpe, - CamelCipherContext *cipher, - CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_MULTIPART_ENCRYPTED_H__ */ diff --git a/camel/camel-multipart-signed.c b/camel/camel-multipart-signed.c deleted file mode 100644 index 5dca448a7f..0000000000 --- a/camel/camel-multipart-signed.c +++ /dev/null @@ -1,763 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * camel-multipart.c : Abstract class for a multipart - * - * Authors: Michael Zucchi - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_ALLOCA_H -#include -#endif - -#include - -#include -#include -#include - -#include - -#include "camel-mime-part.h" -#include "camel-mime-message.h" -#include "camel-mime-parser.h" -#include "camel-stream-mem.h" -#include "camel-multipart-signed.h" -#include "camel-mime-part.h" -#include "camel-exception.h" -#include "md5-utils.h" - -#include "camel-stream-filter.h" -#include "camel-seekable-substream.h" -#include "camel-mime-filter-crlf.h" -#include "camel-mime-filter-canon.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x)) - #include ;*/ - -static void signed_add_part (CamelMultipart *multipart, CamelMimePart *part); -static void signed_add_part_at (CamelMultipart *multipart, CamelMimePart *part, guint index); -static void signed_remove_part (CamelMultipart *multipart, CamelMimePart *part); -static CamelMimePart *signed_remove_part_at (CamelMultipart *multipart, guint index); -static CamelMimePart *signed_get_part (CamelMultipart *multipart, guint index); -static guint signed_get_number (CamelMultipart *multipart); - -static ssize_t write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream); -static void set_mime_type_field (CamelDataWrapper *data_wrapper, CamelContentType *mime_type); -static int construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream); -static int signed_construct_from_parser (CamelMultipart *multipart, struct _CamelMimeParser *mp); - -static CamelMultipartClass *parent_class = NULL; - -/* Returns the class for a CamelMultipartSigned */ -#define CMP_CLASS(so) CAMEL_MULTIPART_SIGNED_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -/* Returns the class for a CamelDataWrapper */ -#define CDW_CLASS(so) CAMEL_DATA_WRAPPER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static void -camel_multipart_signed_class_init (CamelMultipartSignedClass *camel_multipart_signed_class) -{ - CamelDataWrapperClass *camel_data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS(camel_multipart_signed_class); - CamelMultipartClass *mpclass = (CamelMultipartClass *)camel_multipart_signed_class; - - parent_class = (CamelMultipartClass *)camel_multipart_get_type(); - - /* virtual method overload */ - camel_data_wrapper_class->construct_from_stream = construct_from_stream; - camel_data_wrapper_class->write_to_stream = write_to_stream; - camel_data_wrapper_class->decode_to_stream = write_to_stream; - camel_data_wrapper_class->set_mime_type_field = set_mime_type_field; - - mpclass->add_part = signed_add_part; - mpclass->add_part_at = signed_add_part_at; - mpclass->remove_part = signed_remove_part; - mpclass->remove_part_at = signed_remove_part_at; - mpclass->get_part = signed_get_part; - mpclass->get_number = signed_get_number; - mpclass->construct_from_parser = signed_construct_from_parser; - -/* - mpclass->get_boundary = signed_get_boundary; - mpclass->set_boundary = signed_set_boundary; -*/ -} - -static void -camel_multipart_signed_init (gpointer object, gpointer klass) -{ - CamelMultipartSigned *multipart = (CamelMultipartSigned *)object; - - camel_data_wrapper_set_mime_type(CAMEL_DATA_WRAPPER(multipart), "multipart/signed"); - multipart->start1 = -1; -} - -static void -camel_multipart_signed_finalize (CamelObject *object) -{ - CamelMultipartSigned *mps = (CamelMultipartSigned *)object; - - g_free(mps->protocol); - g_free(mps->micalg); - if (mps->signature) - camel_object_unref((CamelObject *)mps->signature); - if (mps->content) - camel_object_unref((CamelObject *)mps->content); - if (mps->contentraw) - camel_object_unref((CamelObject *)mps->contentraw); -} - -CamelType -camel_multipart_signed_get_type (void) -{ - static CamelType camel_multipart_signed_type = CAMEL_INVALID_TYPE; - - if (camel_multipart_signed_type == CAMEL_INVALID_TYPE) { - camel_multipart_signed_type = camel_type_register (camel_multipart_get_type (), "CamelMultipartSigned", - sizeof (CamelMultipartSigned), - sizeof (CamelMultipartSignedClass), - (CamelObjectClassInitFunc) camel_multipart_signed_class_init, - NULL, - (CamelObjectInitFunc) camel_multipart_signed_init, - (CamelObjectFinalizeFunc) camel_multipart_signed_finalize); - } - - return camel_multipart_signed_type; -} - -/** - * camel_multipart_signed_new: - * - * Create a new CamelMultipartSigned object. - * - * A MultipartSigned should be used to store and create parts of - * type "multipart/signed". This is because multipart/signed is - * entirely broken-by-design (tm) and uses completely - * different semantics to other mutlipart types. It must be treated - * as opaque data by any transport. See rfc 3156 for details. - * - * There are 3 ways to create the part: - * Use construct_from_stream. If this is used, then you must - * set the mime_type appropriately to match the data uses, so - * that the multiple parts my be extracted. - * - * Use construct_from_parser. The parser MUST be in the CAMEL_MIME_PARSER_STATE_HEADER - * state, and the current content_type MUST be "multipart/signed" with - * the appropriate boundary and it SHOULD include the appropriate protocol - * and hash specifiers. - * - * Use sign_part. A signature part will automatically be created - * and the whole part may be written using write_to_stream to - * create a 'transport-safe' version (as safe as can be expected with - * such a broken specification). - * - * Return value: a new CamelMultipartSigned - **/ -CamelMultipartSigned * -camel_multipart_signed_new (void) -{ - CamelMultipartSigned *multipart; - - multipart = (CamelMultipartSigned *)camel_object_new(CAMEL_MULTIPART_SIGNED_TYPE); - - return multipart; -} - -/* find the next boundary @bound from @start, return the start of the actual data - @end points to the end of the data BEFORE the boundary */ -static char *parse_boundary(char *start, const char *bound, char **end) -{ - char *data, *begin; - - begin = strstr(start, bound); - if (begin == NULL) - return NULL; - - data = begin+strlen(bound); - if (begin > start && begin[-1] == '\n') - begin--; - if (begin > start && begin[-1] == '\r') - begin--; - if (data[0] == '\r') - data++; - if (data[0] == '\n') - data++; - - *end = begin; - return data; -} - -/* yeah yuck. - Well, we could probably use the normal mime parser, but then it would change our - headers. - This is good enough ... till its not! */ -static int -parse_content(CamelMultipartSigned *mps) -{ - CamelMultipart *mp = (CamelMultipart *)mps; - char *start, *end, *start2, *end2, *last, *post; - CamelStreamMem *mem; - char *bound; - const char *boundary; - - boundary = camel_multipart_get_boundary(mp); - if (boundary == NULL) { - g_warning("Trying to get multipart/signed content without setting boundary first"); - return -1; - } - - /* turn it into a string, and 'fix' it up */ - /* this is extremely dodgey but should work! */ - mem = (CamelStreamMem *)((CamelDataWrapper *)mps)->stream; - if (mem == NULL) { - g_warning("Trying to parse multipart/signed without constructing first"); - return -1; - } - - camel_stream_write((CamelStream *)mem, "", 1); - g_byte_array_set_size(mem->buffer, mem->buffer->len-1); - last = mem->buffer->data + mem->buffer->len; - - bound = alloca(strlen(boundary)+5); - sprintf(bound, "--%s", boundary); - - start = parse_boundary(mem->buffer->data, bound, &end); - if (start == NULL || start[0] == 0) - return -1; - - if (end > (char *)mem->buffer->data) { - char *tmp = g_strndup(mem->buffer->data, start-(char *)mem->buffer->data-1); - camel_multipart_set_preface(mp, tmp); - g_free(tmp); - } - - start2 = parse_boundary(start, bound, &end); - if (start2 == NULL || start2[0] == 0) - return -1; - - sprintf(bound, "--%s--", boundary); - post = parse_boundary(start2, bound, &end2); - if (post == NULL) - return -1; - - if (post[0]) - camel_multipart_set_postface(mp, post); - - mps->start1 = start-(char *)mem->buffer->data; - mps->end1 = end-(char *)mem->buffer->data; - mps->start2 = start2-(char *)mem->buffer->data; - mps->end2 = end2-(char *)mem->buffer->data; - - return 0; -} - -/* we snoop the mime type to get boundary and hash info */ -static void -set_mime_type_field(CamelDataWrapper *data_wrapper, CamelContentType *mime_type) -{ - CamelMultipartSigned *mps = (CamelMultipartSigned *)data_wrapper; - - ((CamelDataWrapperClass *)parent_class)->set_mime_type_field(data_wrapper, mime_type); - if (mime_type) { - const char *micalg, *protocol; - - protocol = camel_content_type_param(mime_type, "protocol"); - g_free(mps->protocol); - mps->protocol = g_strdup(protocol); - - micalg = camel_content_type_param(mime_type, "micalg"); - g_free(mps->micalg); - mps->micalg = g_strdup(micalg); - } -} - -static void -signed_add_part(CamelMultipart *multipart, CamelMimePart *part) -{ - g_warning("Cannot add parts to a signed part using add_part"); -} - -static void -signed_add_part_at(CamelMultipart *multipart, CamelMimePart *part, guint index) -{ - g_warning("Cannot add parts to a signed part using add_part_at"); -} - -static void -signed_remove_part(CamelMultipart *multipart, CamelMimePart *part) -{ - g_warning("Cannot remove parts from a signed part using remove_part"); -} - -static CamelMimePart * -signed_remove_part_at (CamelMultipart *multipart, guint index) -{ - g_warning("Cannot remove parts from a signed part using remove_part"); - return NULL; -} - -static CamelMimePart * -signed_get_part(CamelMultipart *multipart, guint index) -{ - CamelMultipartSigned *mps = (CamelMultipartSigned *)multipart; - CamelDataWrapper *dw = (CamelDataWrapper *)multipart; - CamelStream *stream; - - switch (index) { - case CAMEL_MULTIPART_SIGNED_CONTENT: - if (mps->content) - return mps->content; - if (mps->contentraw) { - stream = mps->contentraw; - camel_object_ref((CamelObject *)stream); - } else if (mps->start1 == -1 - && parse_content(mps) == -1 - && (stream = ((CamelDataWrapper *)mps)->stream) == NULL) { - g_warning("Trying to get content on an invalid multipart/signed"); - return NULL; - } else if (dw->stream == NULL) { - return NULL; - } else if (mps->start1 == -1) { - stream = dw->stream; - camel_object_ref(stream); - } else { - stream = camel_seekable_substream_new((CamelSeekableStream *)dw->stream, mps->start1, mps->end1); - } - camel_stream_reset(stream); - mps->content = camel_mime_part_new(); - camel_data_wrapper_construct_from_stream((CamelDataWrapper *)mps->content, stream); - camel_object_unref(stream); - return mps->content; - case CAMEL_MULTIPART_SIGNED_SIGNATURE: - if (mps->signature) - return mps->signature; - if (mps->start1 == -1 - && parse_content(mps) == -1) { - g_warning("Trying to get signature on invalid multipart/signed"); - return NULL; - } else if (dw->stream == NULL) { - return NULL; - } - stream = camel_seekable_substream_new((CamelSeekableStream *)dw->stream, mps->start2, mps->end2); - camel_stream_reset(stream); - mps->signature = camel_mime_part_new(); - camel_data_wrapper_construct_from_stream((CamelDataWrapper *)mps->signature, stream); - camel_object_unref((CamelObject *)stream); - return mps->signature; - default: - g_warning("trying to get object out of bounds for multipart"); - } - - return NULL; -} - -static guint -signed_get_number(CamelMultipart *multipart) -{ - CamelDataWrapper *dw = (CamelDataWrapper *)multipart; - CamelMultipartSigned *mps = (CamelMultipartSigned *)multipart; - - /* check what we have, so we return something reasonable */ - - if ((mps->content || mps->contentraw) && mps->signature) - return 2; - - if (mps->start1 == -1 && parse_content(mps) == -1) { - if (dw->stream == NULL) - return 0; - else - return 1; - } else { - return 2; - } -} - -static void -set_stream(CamelMultipartSigned *mps, CamelStream *mem) -{ - CamelDataWrapper *dw = (CamelDataWrapper *)mps; - - if (dw->stream) - camel_object_unref((CamelObject *)dw->stream); - dw->stream = (CamelStream *)mem; - - mps->start1 = -1; - if (mps->content) { - camel_object_unref((CamelObject *)mps->content); - mps->content = NULL; - } - if (mps->contentraw) { - camel_object_unref((CamelObject *)mps->contentraw); - mps->contentraw = NULL; - } - if (mps->signature) { - camel_object_unref((CamelObject *)mps->signature); - mps->signature = NULL; - } -} - -static int -construct_from_stream(CamelDataWrapper *data_wrapper, CamelStream *stream) -{ - CamelMultipartSigned *mps = (CamelMultipartSigned *)data_wrapper; - CamelStream *mem = camel_stream_mem_new(); - - if (camel_stream_write_to_stream(stream, mem) == -1) - return -1; - - set_stream(mps, mem); - - return 0; -} - -static int -signed_construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser *mp) -{ - int err; - CamelContentType *content_type; - CamelMultipartSigned *mps = (CamelMultipartSigned *)multipart; - char *buf; - size_t len; - CamelStream *mem; - - /* we *must not* be in multipart state, otherwise the mime parser will - parse the headers which is a no no @#$@# stupid multipart/signed spec */ - g_assert(camel_mime_parser_state(mp) == CAMEL_MIME_PARSER_STATE_HEADER); - - /* All we do is copy it to a memstream */ - content_type = camel_mime_parser_content_type(mp); - camel_multipart_set_boundary(multipart, camel_content_type_param(content_type, "boundary")); - - mem = camel_stream_mem_new(); - while (camel_mime_parser_step(mp, &buf, &len) != CAMEL_MIME_PARSER_STATE_BODY_END) - camel_stream_write(mem, buf, len); - - set_stream(mps, mem); - - err = camel_mime_parser_errno(mp); - if (err != 0) { - errno = err; - return -1; - } else - return 0; -} - -static ssize_t -write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) -{ - CamelMultipartSigned *mps = (CamelMultipartSigned *)data_wrapper; - CamelMultipart *mp = (CamelMultipart *)mps; - const char *boundary; - ssize_t total = 0; - ssize_t count; - - /* we have 3 basic cases: - 1. constructed, we write out the data wrapper stream we got - 2. signed content, we create and write out a new stream - 3. invalid - */ - - /* 1 */ - /* FIXME: locking? */ - if (data_wrapper->stream) { - camel_stream_reset(data_wrapper->stream); - return camel_stream_write_to_stream(data_wrapper->stream, stream); - } - - /* 3 */ - if (mps->signature == NULL || mps->contentraw == NULL) - return -1; - - /* 2 */ - boundary = camel_multipart_get_boundary(mp); - if (mp->preface) { - count = camel_stream_write_string(stream, mp->preface); - if (count == -1) - return -1; - total += count; - } - - /* first boundary */ - count = camel_stream_printf(stream, "\n--%s\n", boundary); - if (count == -1) - return -1; - total += count; - - /* output content part */ - camel_stream_reset(mps->contentraw); - count = camel_stream_write_to_stream(mps->contentraw, stream); - if (count == -1) - return -1; - total += count; - - /* boundary */ - count = camel_stream_printf(stream, "\n--%s\n", boundary); - if (count == -1) - return -1; - total += count; - - /* signature */ - count = camel_data_wrapper_write_to_stream((CamelDataWrapper *)mps->signature, stream); - if (count == -1) - return -1; - total += count; - - /* write the terminating boudary delimiter */ - count = camel_stream_printf(stream, "\n--%s--\n", boundary); - if (count == -1) - return -1; - total += count; - - /* and finally the postface */ - if (mp->postface) { - count = camel_stream_write_string(stream, mp->postface); - if (count == -1) - return -1; - total += count; - } - - return total; -} - -/* See rfc3156, section 2 and others */ -/* We do this simply: Anything not base64 must be qp - This is so that we can safely translate any occurance of "From " - into the quoted-printable escaped version safely. */ -static void -prepare_sign(CamelMimePart *mime_part) -{ - CamelDataWrapper *wrapper; - CamelTransferEncoding encoding; - int parts, i; - - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); - if (!wrapper) - return; - - if (CAMEL_IS_MULTIPART (wrapper)) { - parts = camel_multipart_get_number((CamelMultipart *)wrapper); - for (i = 0; i < parts; i++) - prepare_sign(camel_multipart_get_part((CamelMultipart *)wrapper, i)); - } else if (CAMEL_IS_MIME_MESSAGE (wrapper)) { - prepare_sign((CamelMimePart *)wrapper); - } else { - encoding = camel_mime_part_get_encoding(mime_part); - - if (encoding != CAMEL_TRANSFER_ENCODING_BASE64 - && encoding != CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE) { - camel_mime_part_set_encoding(mime_part, CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE); - } - } -} - -/** - * camel_multipart_signed_sign: - * @mps: - * @context: The CipherContext to use for signing. - * @content: CamelMimePart content you wish to sign/transport. - * @userid: The id of the signing key to use. - * @hash: The algorithm to use. - * @ex: - * - * Sign the part @content, and attach it as the first part - * (CAMEL_MULTIPART_SIGNED_CONTENT) of the multipart @mps. A - * signature object will be created and setup as the second part - * (CAMEL_MULTIPART_SIGNED_SIGNATURE) of the object. Once a part has - * been successfully signed the mutlipart is ready for transmission. - * - * This method should be used to create multipart/signed objects - * which are properly canoncalised before signing, etc. - * - * Return value: -1 on error, setting @ex appropriately. On error - * neither the content or signature parts will be setup. - **/ -int -camel_multipart_signed_sign(CamelMultipartSigned *mps, CamelCipherContext *context, CamelMimePart *content, const char *userid, CamelCipherHash hash, CamelException *ex) -{ - abort(); -#if 0 - CamelMimeFilter *canon_filter; - CamelStream *mem; - CamelStreamFilter *filter; - CamelContentType *mime_type; - CamelMimePart *sigpart; - - /* this needs to be set */ - g_return_val_if_fail(context->sign_protocol != NULL, -1); - - prepare_sign(content); - - mem = camel_stream_mem_new(); - filter = camel_stream_filter_new_with_stream(mem); - - /* Note: see rfc2015 or rfc3156, section 5 */ - canon_filter = camel_mime_filter_canon_new(CAMEL_MIME_FILTER_CANON_STRIP|CAMEL_MIME_FILTER_CANON_CRLF|CAMEL_MIME_FILTER_CANON_FROM); - camel_stream_filter_add(filter, (CamelMimeFilter *)canon_filter); - camel_object_unref((CamelObject *)canon_filter); - - camel_data_wrapper_write_to_stream((CamelDataWrapper *)content, (CamelStream *)filter); - camel_stream_flush((CamelStream *)filter); - camel_object_unref((CamelObject *)filter); - camel_stream_reset(mem); - -#if 0 - printf("-- Signing:\n"); - fwrite(((CamelStreamMem *)mem)->buffer->data, ((CamelStreamMem *)mem)->buffer->len, 1, stdout); - printf("-- end\n"); -#endif - - sigpart = camel_mime_part_new(); - - if (camel_cipher_sign(context, userid, hash, mem, sigpart, ex) == -1) { - camel_object_unref(mem); - camel_object_unref(sigpart); - return -1; - } - - /* setup our mime type and boundary */ - mime_type = camel_content_type_new("multipart", "signed"); - camel_content_type_set_param(mime_type, "micalg", camel_cipher_hash_to_id(context, hash)); - camel_content_type_set_param(mime_type, "protocol", context->sign_protocol); - camel_data_wrapper_set_mime_type_field(CAMEL_DATA_WRAPPER (mps), mime_type); - camel_content_type_unref(mime_type); - camel_multipart_set_boundary((CamelMultipart *)mps, NULL); - - /* just keep the whole raw content. We dont *really* need to do this because - we know how we just proccessed it, but, well, better to be safe than sorry */ - mps->signature = sigpart; - mps->contentraw = mem; - camel_stream_reset(mem); - - /* clear the data-wrapper stream - tells write_to_stream to use the right object */ - if (((CamelDataWrapper *)mps)->stream) { - camel_object_unref((CamelObject *) ((CamelDataWrapper *)mps)->stream); - ((CamelDataWrapper *)mps)->stream = NULL; - } -#endif - return 0; -} - -CamelStream * -camel_multipart_signed_get_content_stream(CamelMultipartSigned *mps, CamelException *ex) -{ - CamelStream *constream; - - /* we need to be able to verify stuff we just signed as well as stuff we loaded from a stream/parser */ - - if (mps->contentraw) { - constream = mps->contentraw; - camel_object_ref((CamelObject *)constream); - } else { - CamelStream *sub; - CamelMimeFilter *canon_filter; - - if (mps->start1 == -1 && parse_content(mps) == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("parse error")); - return NULL; - } - - /* first, prepare our parts */ - sub = camel_seekable_substream_new((CamelSeekableStream *)((CamelDataWrapper *)mps)->stream, mps->start1, mps->end1); - constream = (CamelStream *)camel_stream_filter_new_with_stream(sub); - camel_object_unref((CamelObject *)sub); - - /* Note: see rfc2015 or rfc3156, section 5 */ - canon_filter = camel_mime_filter_canon_new (CAMEL_MIME_FILTER_CANON_CRLF); - camel_stream_filter_add((CamelStreamFilter *)constream, (CamelMimeFilter *)canon_filter); - camel_object_unref((CamelObject *)canon_filter); - } - - return constream; -} - -/** - * camel_multipart_signed_verify: - * @mps: - * @context: - * @ex: - * - * Verify a signed object. This may be used to verify newly signed - * objects as well as those created from external streams or parsers. - * - * Return value: A validity value, or NULL on error, setting @ex - * appropriately. - **/ -CamelCipherValidity * -camel_multipart_signed_verify(CamelMultipartSigned *mps, CamelCipherContext *context, CamelException *ex) -{ - abort(); - - return NULL; -#if 0 - CamelCipherValidity *valid; - CamelMimePart *sigpart; - CamelStream *constream; - - /* we need to be able to verify stuff we just signed as well as stuff we loaded from a stream/parser */ - - if (mps->contentraw) { - constream = mps->contentraw; - camel_object_ref((CamelObject *)constream); - } else { - CamelStream *sub; - CamelMimeFilter *canon_filter; - - if (mps->start1 == -1 && parse_content(mps) == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("parse error")); - return NULL; - } - - /* first, prepare our parts */ - sub = camel_seekable_substream_new((CamelSeekableStream *)((CamelDataWrapper *)mps)->stream, mps->start1, mps->end1); - constream = (CamelStream *)camel_stream_filter_new_with_stream(sub); - camel_object_unref((CamelObject *)sub); - - /* Note: see rfc2015 or rfc3156, section 5 */ - canon_filter = camel_mime_filter_canon_new (CAMEL_MIME_FILTER_CANON_CRLF); - camel_stream_filter_add((CamelStreamFilter *)constream, (CamelMimeFilter *)canon_filter); - camel_object_unref((CamelObject *)canon_filter); - } - - /* we do this as a normal mime part so we can have it handle transfer encoding etc */ - sigpart = camel_multipart_get_part((CamelMultipart *)mps, CAMEL_MULTIPART_SIGNED_SIGNATURE); - - /* do the magic, the caller must supply the right context for this kind of object */ - valid = camel_cipher_verify(context, camel_cipher_id_to_hash(context, mps->micalg), constream, sigpart, ex); - -#if 0 - { - CamelStream *sout = camel_stream_fs_new_with_fd(dup(0)); - - camel_stream_printf(sout, "-- Verifying:\n"); - camel_stream_reset(constream); - camel_stream_write_to_stream(constream, sout); - camel_stream_printf(sout, "-- end\n"); - camel_object_unref((CamelObject *)sout); - } -#endif - - camel_object_unref(constream); - - return valid; -#endif -} - - diff --git a/camel/camel-multipart-signed.h b/camel/camel-multipart-signed.h deleted file mode 100644 index 2b0df64189..0000000000 --- a/camel/camel-multipart-signed.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * camel-signed--multipart.h : class for a signed-multipart - * - * Authors: Michael Zucchi - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -/* Should this be a subclass of multipart? - No, because we dont have different parts? - I'm not really sure yet ... ? */ - -#ifndef CAMEL_MULTIPART_SIGNED_H -#define CAMEL_MULTIPART_SIGNED_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include - -#define CAMEL_MULTIPART_SIGNED_TYPE (camel_multipart_signed_get_type ()) -#define CAMEL_MULTIPART_SIGNED(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MULTIPART_SIGNED_TYPE, CamelMultipartSigned)) -#define CAMEL_MULTIPART_SIGNED_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MULTIPART_SIGNED_TYPE, CamelMultipartSignedClass)) -#define CAMEL_IS_MULTIPART_SIGNED(o) (CAMEL_CHECK_TYPE((o), CAMEL_MULTIPART_SIGNED_TYPE)) - -/* -enum { - CAMEL_MULTIPART_EMPTY, - CAMEL_MULTIPART_CONST, - CAMEL_MULTIPART_SIGN, - CAMEL_MULTIPART_ENCR, -}; -*/ - -/* 'handy' enums for getting the internal parts of the multipart */ -enum { - CAMEL_MULTIPART_SIGNED_CONTENT, - CAMEL_MULTIPART_SIGNED_SIGNATURE, -}; - -typedef struct _CamelMultipartSigned CamelMultipartSigned; - -struct _CamelMultipartSigned -{ - CamelMultipart parent_object; - - /* these are the client visible parts, decoded forms of our data wrapper content */ - CamelMimePart *content; - CamelMimePart *signature; - - /* the raw content which must go over the wire, if we have generated it */ - /* perhaps this should jsut set data_wrapper->stream and update start1/end1 accordingly, as it is done - for other parts, or visa versa? */ - CamelStream *contentraw; - - /*int state;*/ - - /* just cache some info we use */ - char *protocol; - char *micalg; - - /* offset pointers of start of boundary in content object */ - off_t start1, end1; - off_t start2, end2; -}; - -typedef struct { - CamelMultipartClass parent_class; -} CamelMultipartSignedClass; - -/* Standard Camel function */ -CamelType camel_multipart_signed_get_type (void); - -/* public methods */ -CamelMultipartSigned *camel_multipart_signed_new (void); - -CamelStream *camel_multipart_signed_get_content_stream(CamelMultipartSigned *mps, CamelException *ex); - -int camel_multipart_signed_sign (CamelMultipartSigned *mps, CamelCipherContext *context, - CamelMimePart *content, const char *uiserid, - CamelCipherHash hash, CamelException *ex); -CamelCipherValidity *camel_multipart_signed_verify (CamelMultipartSigned *mps, CamelCipherContext *context, - CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_MULTIPART_SIGNED_H */ - - diff --git a/camel/camel-multipart.c b/camel/camel-multipart.c deleted file mode 100644 index 3ec60147d5..0000000000 --- a/camel/camel-multipart.c +++ /dev/null @@ -1,589 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-multipart.c : Abstract class for a multipart */ - - -/* - * - * Author : - * Bertrand Guiheneuf - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include /* strlen() */ -#include /* for getpid */ -#include /* for time */ -#include - -#include "camel-stream-mem.h" -#include "camel-multipart.h" -#include "camel-mime-part.h" -#include "camel-exception.h" -#include "md5-utils.h" - -#define d(x) - -static gboolean is_offline (CamelDataWrapper *data_wrapper); -static void add_part (CamelMultipart *multipart, - CamelMimePart *part); -static void add_part_at (CamelMultipart *multipart, - CamelMimePart *part, - guint index); -static void remove_part (CamelMultipart *multipart, - CamelMimePart *part); -static CamelMimePart * remove_part_at (CamelMultipart *multipart, - guint index); -static CamelMimePart * get_part (CamelMultipart *multipart, - guint index); -static guint get_number (CamelMultipart *multipart); -static void set_boundary (CamelMultipart *multipart, - const char *boundary); -static const gchar * get_boundary (CamelMultipart *multipart); -static ssize_t write_to_stream (CamelDataWrapper *data_wrapper, - CamelStream *stream); -static void unref_part (gpointer data, gpointer user_data); - -static int construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser *mp); - -static CamelDataWrapperClass *parent_class = NULL; - - - -/* Returns the class for a CamelMultipart */ -#define CMP_CLASS(so) CAMEL_MULTIPART_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -/* Returns the class for a CamelDataWrapper */ -#define CDW_CLASS(so) CAMEL_DATA_WRAPPER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - - -static void -camel_multipart_class_init (CamelMultipartClass *camel_multipart_class) -{ - CamelDataWrapperClass *camel_data_wrapper_class = - CAMEL_DATA_WRAPPER_CLASS (camel_multipart_class); - - parent_class = (CamelDataWrapperClass *) camel_data_wrapper_get_type (); - - /* virtual method definition */ - camel_multipart_class->add_part = add_part; - camel_multipart_class->add_part_at = add_part_at; - camel_multipart_class->remove_part = remove_part; - camel_multipart_class->remove_part_at = remove_part_at; - camel_multipart_class->get_part = get_part; - camel_multipart_class->get_number = get_number; - camel_multipart_class->set_boundary = set_boundary; - camel_multipart_class->get_boundary = get_boundary; - camel_multipart_class->construct_from_parser = construct_from_parser; - - /* virtual method overload */ - camel_data_wrapper_class->write_to_stream = write_to_stream; - camel_data_wrapper_class->decode_to_stream = write_to_stream; - camel_data_wrapper_class->is_offline = is_offline; -} - -static void -camel_multipart_init (gpointer object, gpointer klass) -{ - CamelMultipart *multipart = CAMEL_MULTIPART (object); - - camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart), - "multipart/mixed"); - multipart->preface = NULL; - multipart->postface = NULL; -} - -static void -camel_multipart_finalize (CamelObject *object) -{ - CamelMultipart *multipart = CAMEL_MULTIPART (object); - - g_list_foreach (multipart->parts, unref_part, NULL); - - /*if (multipart->boundary) - g_free (multipart->boundary);*/ - if (multipart->preface) - g_free (multipart->preface); - if (multipart->postface) - g_free (multipart->postface); -} - - -CamelType -camel_multipart_get_type (void) -{ - static CamelType camel_multipart_type = CAMEL_INVALID_TYPE; - - if (camel_multipart_type == CAMEL_INVALID_TYPE) { - camel_multipart_type = camel_type_register (camel_data_wrapper_get_type (), "CamelMultipart", - sizeof (CamelMultipart), - sizeof (CamelMultipartClass), - (CamelObjectClassInitFunc) camel_multipart_class_init, - NULL, - (CamelObjectInitFunc) camel_multipart_init, - (CamelObjectFinalizeFunc) camel_multipart_finalize); - } - - return camel_multipart_type; -} - -static void -unref_part (gpointer data, gpointer user_data) -{ - CamelObject *part = data; - - camel_object_unref (part); -} - -/** - * camel_multipart_new: - * - * Create a new CamelMultipart object. - * - * Return value: a new CamelMultipart - **/ -CamelMultipart * -camel_multipart_new (void) -{ - CamelMultipart *multipart; - - multipart = (CamelMultipart *)camel_object_new (CAMEL_MULTIPART_TYPE); - multipart->preface = NULL; - multipart->postface = NULL; - - return multipart; -} - - -static void -add_part (CamelMultipart *multipart, CamelMimePart *part) -{ - multipart->parts = g_list_append (multipart->parts, part); - camel_object_ref (part); -} - -/** - * camel_multipart_add_part: - * @multipart: a CamelMultipart - * @part: the part to add - * - * Appends the part to the multipart object. - **/ -void -camel_multipart_add_part (CamelMultipart *multipart, CamelMimePart *part) -{ - g_return_if_fail (CAMEL_IS_MULTIPART (multipart)); - g_return_if_fail (CAMEL_IS_MIME_PART (part)); - - CMP_CLASS (multipart)->add_part (multipart, part); -} - - -static void -add_part_at (CamelMultipart *multipart, CamelMimePart *part, guint index) -{ - multipart->parts = g_list_insert (multipart->parts, part, index); - camel_object_ref (part); -} - -/** - * camel_multipart_add_part_at: - * @multipart: a CamelMultipart - * @part: the part to add - * @index: index to add the multipart at - * - * Adds the part to the multipart object after the @index'th - * element. If @index is greater than the number of parts, it is - * equivalent to camel_multipart_add_part(). - **/ -void -camel_multipart_add_part_at (CamelMultipart *multipart, - CamelMimePart *part, guint index) -{ - g_return_if_fail (CAMEL_IS_MULTIPART (multipart)); - g_return_if_fail (CAMEL_IS_MIME_PART (part)); - - CMP_CLASS (multipart)->add_part_at (multipart, part, index); -} - - -static void -remove_part (CamelMultipart *multipart, CamelMimePart *part) -{ - if (!multipart->parts) - return; - multipart->parts = g_list_remove (multipart->parts, part); - camel_object_unref (part); -} - -/** - * camel_multipart_remove_part: - * @multipart: a CamelMultipart - * @part: the part to remove - * - * Removes @part from @multipart. - **/ -void -camel_multipart_remove_part (CamelMultipart *multipart, - CamelMimePart *part) -{ - g_return_if_fail (CAMEL_IS_MULTIPART (multipart)); - g_return_if_fail (CAMEL_IS_MIME_PART (part)); - - CMP_CLASS (multipart)->remove_part (multipart, part); -} - - -static CamelMimePart * -remove_part_at (CamelMultipart *multipart, guint index) -{ - GList *parts_list; - GList *part_to_remove; - CamelMimePart *removed_part; - - if (!(multipart->parts)) - return NULL; - - parts_list = multipart->parts; - part_to_remove = g_list_nth (parts_list, index); - if (!part_to_remove) { - g_warning ("CamelMultipart::remove_part_at: " - "part to remove is NULL\n"); - return NULL; - } - removed_part = CAMEL_MIME_PART (part_to_remove->data); - - multipart->parts = g_list_remove_link (parts_list, part_to_remove); - if (part_to_remove->data) - camel_object_unref (part_to_remove->data); - g_list_free_1 (part_to_remove); - - return removed_part; -} - -/** - * camel_multipart_remove_part_at: - * @multipart: a CamelMultipart - * @index: a zero-based index indicating the part to remove - * - * Remove the indicated part from the multipart object. - * - * Return value: the removed part. Note that it is camel_object_unref()ed - * before being returned, which may cause it to be destroyed. - **/ -CamelMimePart * -camel_multipart_remove_part_at (CamelMultipart *multipart, guint index) -{ - g_return_val_if_fail (CAMEL_IS_MULTIPART (multipart), NULL); - - return CMP_CLASS (multipart)->remove_part_at (multipart, index); -} - - -static CamelMimePart * -get_part (CamelMultipart *multipart, guint index) -{ - GList *part; - - if (!(multipart->parts)) - return NULL; - - part = g_list_nth (multipart->parts, index); - if (part) - return CAMEL_MIME_PART (part->data); - else - return NULL; -} - -/** - * camel_multipart_get_part: - * @multipart: a CamelMultipart - * @index: a zero-based index indicating the part to get - * - * Return value: the indicated subpart, or %NULL - **/ -CamelMimePart * -camel_multipart_get_part (CamelMultipart *multipart, guint index) -{ - g_return_val_if_fail (CAMEL_IS_MULTIPART (multipart), NULL); - - return CMP_CLASS (multipart)->get_part (multipart, index); -} - - -static guint -get_number (CamelMultipart *multipart) -{ - return g_list_length (multipart->parts); -} - -/** - * camel_multipart_get_number: - * @multipart: a CamelMultipart - * - * Return value: the number of subparts in @multipart - **/ -guint -camel_multipart_get_number (CamelMultipart *multipart) -{ - g_return_val_if_fail (CAMEL_IS_MULTIPART (multipart), 0); - - return CMP_CLASS (multipart)->get_number (multipart); -} - - -static void -set_boundary (CamelMultipart *multipart, const char *boundary) -{ - CamelDataWrapper *cdw = CAMEL_DATA_WRAPPER (multipart); - char *bgen, digest[16], bbuf[27], *p; - int state, save; - - g_return_if_fail (cdw->mime_type != NULL); - - if (!boundary) { - /* Generate a fairly random boundary string. */ - bgen = g_strdup_printf ("%p:%lu:%lu", multipart, - (unsigned long) getpid(), - (unsigned long) time(0)); - md5_get_digest (bgen, strlen (bgen), digest); - g_free (bgen); - strcpy (bbuf, "=-"); - p = bbuf + 2; - state = save = 0; - p += camel_base64_encode_step (digest, 16, FALSE, p, &state, &save); - *p = '\0'; - - boundary = bbuf; - } - - camel_content_type_set_param (cdw->mime_type, "boundary", boundary); -} - -/** - * camel_multipart_set_boundary: - * @multipart: a CamelMultipart - * @boundary: the message boundary, or %NULL - * - * Sets the message boundary for @multipart to @boundary. This should - * be a string which does not occur anywhere in any of @multipart's - * subparts. If @boundary is %NULL, a randomly-generated boundary will - * be used. - **/ -void -camel_multipart_set_boundary (CamelMultipart *multipart, const char *boundary) -{ - g_return_if_fail (CAMEL_IS_MULTIPART (multipart)); - - CMP_CLASS (multipart)->set_boundary (multipart, boundary); -} - - -static const gchar * -get_boundary (CamelMultipart *multipart) -{ - CamelDataWrapper *cdw = CAMEL_DATA_WRAPPER (multipart); - - g_return_val_if_fail (cdw->mime_type != NULL, NULL); - return camel_content_type_param (cdw->mime_type, "boundary"); -} - -/** - * camel_multipart_get_boundary: - * @multipart: a CamelMultipart - * - * Return value: @multipart's message boundary - **/ -const gchar * -camel_multipart_get_boundary (CamelMultipart *multipart) -{ - return CMP_CLASS (multipart)->get_boundary (multipart); -} - -static gboolean -is_offline (CamelDataWrapper *data_wrapper) -{ - CamelMultipart *multipart = CAMEL_MULTIPART (data_wrapper); - GList *node; - CamelDataWrapper *part; - - if (parent_class->is_offline (data_wrapper)) - return TRUE; - for (node = multipart->parts; node; node = node->next) { - part = node->data; - if (camel_data_wrapper_is_offline (part)) - return TRUE; - } - - return FALSE; -} - -/* this is MIME specific, doesn't belong here really */ -static ssize_t -write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) -{ - CamelMultipart *multipart = CAMEL_MULTIPART (data_wrapper); - const gchar *boundary; - ssize_t total = 0; - ssize_t count; - GList *node; - - /* get the bundary text */ - boundary = camel_multipart_get_boundary (multipart); - - /* we cannot write a multipart without a boundary string */ - g_return_val_if_fail (boundary, -1); - - /* - * write the preface text (usually something like - * "This is a mime message, if you see this, then - * your mail client probably doesn't support ...." - */ - if (multipart->preface) { - count = camel_stream_write_string (stream, multipart->preface); - if (count == -1) - return -1; - total += count; - } - - /* - * Now, write all the parts, separated by the boundary - * delimiter - */ - node = multipart->parts; - while (node) { - count = camel_stream_printf (stream, "\n--%s\n", boundary); - if (count == -1) - return -1; - total += count; - - count = camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (node->data), stream); - if (count == -1) - return -1; - total += count; - node = node->next; - } - - /* write the terminating boudary delimiter */ - count = camel_stream_printf (stream, "\n--%s--\n", boundary); - if (count == -1) - return -1; - total += count; - - /* and finally the postface */ - if (multipart->postface) { - count = camel_stream_write_string (stream, multipart->postface); - if (count == -1) - return -1; - total += count; - } - - return total; -} - -/** - * camel_multipart_set_preface: - * @multipart: - * @preface: - * - * Set the preface text for this multipart. Will be written out infront - * of the multipart. This text should only include US-ASCII strings, and - * be relatively short, and will be ignored by any MIME mail client. - **/ -void -camel_multipart_set_preface(CamelMultipart *multipart, const char *preface) -{ - if (multipart->preface != preface) { - g_free(multipart->preface); - if (preface) - multipart->preface = g_strdup(preface); - else - multipart->preface = NULL; - } -} - -/** - * camel_multipart_set_postface: - * @multipart: - * @postface: - * - * Set the postfix text for this multipart. Will be written out after - * the last boundary of the multipart, and ignored by any MIME mail - * client. - * - * Generally postface texts should not be sent with multipart messages. - **/ -void -camel_multipart_set_postface(CamelMultipart *multipart, const char *postface) -{ - if (multipart->postface != postface) { - g_free(multipart->postface); - if (postface) - multipart->postface = g_strdup(postface); - else - multipart->postface = NULL; - } -} - -static int -construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser *mp) -{ - int err; - CamelContentType *content_type; - CamelMimePart *bodypart; - char *buf; - size_t len; - - g_assert(camel_mime_parser_state(mp) == CAMEL_MIME_PARSER_STATE_MULTIPART); - - /* FIXME: we should use a came-mime-mutlipart, not jsut a camel-multipart, but who cares */ - d(printf("Creating multi-part\n")); - - content_type = camel_mime_parser_content_type(mp); - camel_multipart_set_boundary(multipart, - camel_content_type_param(content_type, "boundary")); - - while (camel_mime_parser_step(mp, &buf, &len) != CAMEL_MIME_PARSER_STATE_MULTIPART_END) { - camel_mime_parser_unstep(mp); - bodypart = camel_mime_part_new(); - camel_mime_part_construct_from_parser(bodypart, mp); - camel_multipart_add_part(multipart, bodypart); - camel_object_unref((CamelObject *)bodypart); - } - - /* these are only return valid data in the MULTIPART_END state */ - camel_multipart_set_preface(multipart, camel_mime_parser_preface (mp)); - camel_multipart_set_postface(multipart, camel_mime_parser_postface (mp)); - - err = camel_mime_parser_errno(mp); - if (err != 0) { - errno = err; - return -1; - } else - return 0; -} - -int -camel_multipart_construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser *mp) -{ - g_return_val_if_fail(CAMEL_IS_MULTIPART(multipart), -1); - - return CMP_CLASS(multipart)->construct_from_parser(multipart, mp); -} diff --git a/camel/camel-multipart.h b/camel/camel-multipart.h deleted file mode 100644 index ac2e37f540..0000000000 --- a/camel/camel-multipart.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-multipart.h : class for a multipart */ - -/* - * - * Author : - * Bertrand Guiheneuf - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_MULTIPART_H -#define CAMEL_MULTIPART_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include - -#define CAMEL_MULTIPART_TYPE (camel_multipart_get_type ()) -#define CAMEL_MULTIPART(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MULTIPART_TYPE, CamelMultipart)) -#define CAMEL_MULTIPART_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MULTIPART_TYPE, CamelMultipartClass)) -#define CAMEL_IS_MULTIPART(o) (CAMEL_CHECK_TYPE((o), CAMEL_MULTIPART_TYPE)) - -struct _CamelMimeParser; - -struct _CamelMultipart -{ - CamelDataWrapper parent_object; - - GList *parts; - gchar *preface; - gchar *postface; -}; - -typedef struct { - CamelDataWrapperClass parent_class; - - /* Virtual methods */ - void (*add_part) (CamelMultipart *multipart, CamelMimePart *part); - void (*add_part_at) (CamelMultipart *multipart, CamelMimePart *part, guint index); - void (*remove_part) (CamelMultipart *multipart, CamelMimePart *part); - CamelMimePart * (*remove_part_at) (CamelMultipart *multipart, guint index); - CamelMimePart * (*get_part) (CamelMultipart *multipart, guint index); - guint (*get_number) (CamelMultipart *multipart); - void (*set_boundary) (CamelMultipart *multipart, const char *boundary); - const gchar * (*get_boundary) (CamelMultipart *multipart); - - int (*construct_from_parser)(CamelMultipart *, struct _CamelMimeParser *); - /*int (*construct_from_stream)(CamelMultipart *, CamelStream *);*/ - -} CamelMultipartClass; - -/* Standard Camel function */ -CamelType camel_multipart_get_type (void); - - -/* public methods */ -CamelMultipart * camel_multipart_new (void); -void camel_multipart_add_part (CamelMultipart *multipart, - CamelMimePart *part); -void camel_multipart_add_part_at (CamelMultipart *multipart, - CamelMimePart *part, - guint index); -void camel_multipart_remove_part (CamelMultipart *multipart, - CamelMimePart *part); -CamelMimePart * camel_multipart_remove_part_at (CamelMultipart *multipart, - guint index); -CamelMimePart * camel_multipart_get_part (CamelMultipart *multipart, - guint index); -guint camel_multipart_get_number (CamelMultipart *multipart); -void camel_multipart_set_boundary (CamelMultipart *multipart, - const char *boundary); -const gchar * camel_multipart_get_boundary (CamelMultipart *multipart); - -void camel_multipart_set_preface (CamelMultipart *multipart, const char *preface); -void camel_multipart_set_postface (CamelMultipart *multipart, const char *postface); - -int camel_multipart_construct_from_parser(CamelMultipart *multipart, struct _CamelMimeParser *mp); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_MULTIPART_H */ - diff --git a/camel/camel-news-address.c b/camel/camel-news-address.c deleted file mode 100644 index c8a170781a..0000000000 --- a/camel/camel-news-address.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "camel-news-address.h" - - -static void camel_news_address_class_init (CamelNewsAddressClass *klass); - -static CamelAddressClass *camel_news_address_parent; - -static void -camel_news_address_class_init (CamelNewsAddressClass *klass) -{ - camel_news_address_parent = CAMEL_ADDRESS_CLASS (camel_type_get_global_classfuncs (camel_address_get_type ())); -} - - -CamelType -camel_news_address_get_type (void) -{ - static guint type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_address_get_type (), "CamelNewsAddress", - sizeof (CamelNewsAddress), - sizeof (CamelNewsAddressClass), - (CamelObjectClassInitFunc) camel_news_address_class_init, - NULL, - NULL, - NULL); - } - - return type; -} - -/** - * camel_news_address_new: - * - * Create a new CamelNewsAddress object. - * - * Return value: A new CamelNewsAddress widget. - **/ -CamelNewsAddress * -camel_news_address_new (void) -{ - CamelNewsAddress *new = CAMEL_NEWS_ADDRESS ( camel_object_new (camel_news_address_get_type ())); - return new; -} diff --git a/camel/camel-news-address.h b/camel/camel-news-address.h deleted file mode 100644 index ca1505e9a6..0000000000 --- a/camel/camel-news-address.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_NEWS_ADDRESS_H -#define _CAMEL_NEWS_ADDRESS_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#define CAMEL_NEWS_ADDRESS(obj) CAMEL_CHECK_CAST (obj, camel_news_address_get_type (), CamelNewsAddress) -#define CAMEL_NEWS_ADDRESS_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_news_address_get_type (), CamelNewsAddressClass) -#define CAMEL_IS_NEWS_ADDRESS(obj) CAMEL_CHECK_TYPE (obj, camel_news_address_get_type ()) - -typedef struct _CamelNewsAddressClass CamelNewsAddressClass; - -struct _CamelNewsAddress { - CamelAddress parent; - - struct _CamelNewsAddressPrivate *priv; -}; - -struct _CamelNewsAddressClass { - CamelAddressClass parent_class; -}; - -CamelType camel_news_address_get_type (void); -CamelNewsAddress *camel_news_address_new (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_NEWS_ADDRESS_H */ diff --git a/camel/camel-object.c b/camel/camel-object.c deleted file mode 100644 index 744e9f7566..0000000000 --- a/camel/camel-object.c +++ /dev/null @@ -1,1834 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * - * Author: - * Michael Zucchi - * - * Copyright 2000-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "camel-object.h" -#include "camel-file-utils.h" - -#include -#include - -#define d(x) - -/* I just mashed the keyboard for these... */ -#define CAMEL_OBJECT_MAGIC 0x77A344ED -#define CAMEL_OBJECT_CLASS_MAGIC 0xEE26A997 -#define CAMEL_OBJECT_FINALISED_MAGIC 0x84AC365F -#define CAMEL_OBJECT_CLASS_FINALISED_MAGIC 0x7621ABCD - -/* ** Quickie type system ************************************************* */ - -/* A 'locked' hooklist, that is only allocated on demand */ -typedef struct _CamelHookList { - EMutex *lock; - - unsigned int depth:30; /* recursive event depth */ - unsigned int flags:2; /* flags, see below */ - - unsigned int list_length; - struct _CamelHookPair *list; -} CamelHookList; - -#define CAMEL_HOOK_PAIR_REMOVED (1<<0) - -/* a 'hook pair', actually a hook tuple, we just store all hooked events in the same list, - and just comapre as we go, rather than storing separate lists for each hook type - - the name field just points directly to the key field in the class's preplist hashtable. - This way we can just use a direct pointer compare when scanning it, and also saves - copying the string */ -typedef struct _CamelHookPair -{ - struct _CamelHookPair *next; /* next MUST be the first member */ - - unsigned int id:30; - unsigned int flags:2; /* removed, etc */ - - const char *name; /* points to the key field in the classes preplist, static memory */ - union { - CamelObjectEventHookFunc event; - CamelObjectEventPrepFunc prep; - char *filename; - } func; - void *data; -} CamelHookPair; - -struct _CamelObjectBag { - GHashTable *object_table; /* object by key */ - GHashTable *key_table; /* key by object */ - CamelCopyFunc copy_key; - GFreeFunc free_key; - pthread_t owner; /* the thread that has reserved the bag for a new entry */ - sem_t reserve_sem; /* used to track ownership */ -}; - -/* used to tag a bag hookpair */ -static const char *bag_name = "object:bag"; - -/* meta-data stuff */ -static void co_metadata_free(CamelObject *obj, CamelObjectMeta *meta); -static CamelObjectMeta *co_metadata_get(CamelObject *obj); -static CamelHookPair *co_metadata_pair(CamelObject *obj, int create); - -static const char *meta_name = "object:meta"; -#define CAMEL_OBJECT_STATE_FILE_MAGIC "CLMD" - -/* ********************************************************************** */ - -static CamelHookList *camel_object_get_hooks(CamelObject *o); -static void camel_object_free_hooks(CamelObject *o); -static void camel_object_bag_remove_unlocked(CamelObjectBag *inbag, CamelObject *o, CamelHookList *hooks); - -#define camel_object_unget_hooks(o) (e_mutex_unlock((CAMEL_OBJECT(o)->hooks->lock))) - - -/* ********************************************************************** */ - -static pthread_mutex_t chunks_lock = PTHREAD_MUTEX_INITIALIZER; - -static EMemChunk *pair_chunks; -static EMemChunk *hook_chunks; -static unsigned int pair_id = 1; - -static EMutex *type_lock; - -static GHashTable *type_table; -static EMemChunk *type_chunks; - -CamelType camel_object_type; - -#define P_LOCK(l) (pthread_mutex_lock(&l)) -#define P_UNLOCK(l) (pthread_mutex_unlock(&l)) -#define E_LOCK(l) (e_mutex_lock(l)) -#define E_UNLOCK(l) (e_mutex_unlock(l)) -#define CLASS_LOCK(k) (g_mutex_lock((((CamelObjectClass *)k)->lock))) -#define CLASS_UNLOCK(k) (g_mutex_unlock((((CamelObjectClass *)k)->lock))) - - -static struct _CamelHookPair * -pair_alloc(void) -{ - CamelHookPair *pair; - - P_LOCK(chunks_lock); - pair = e_memchunk_alloc(pair_chunks); - pair->id = pair_id++; - if (pair_id == 0) - pair_id = 1; - P_UNLOCK(chunks_lock); - - return pair; -} - -static void -pair_free(CamelHookPair *pair) -{ - g_assert(pair_chunks != NULL); - - P_LOCK(chunks_lock); - e_memchunk_free(pair_chunks, pair); - P_UNLOCK(chunks_lock); -} - -static struct _CamelHookList * -hooks_alloc(void) -{ - CamelHookList *hooks; - - P_LOCK(chunks_lock); - hooks = e_memchunk_alloc(hook_chunks); - P_UNLOCK(chunks_lock); - - return hooks; -} - -static void -hooks_free(CamelHookList *hooks) -{ - g_assert(hook_chunks != NULL); - - P_LOCK(chunks_lock); - e_memchunk_free(hook_chunks, hooks); - P_UNLOCK(chunks_lock); -} - -/* not checked locked, who cares, only required for people that want to redefine root objects */ -void -camel_type_init(void) -{ - static int init = FALSE; - - if (init) - return; - - init = TRUE; - pair_chunks = e_memchunk_new(16, sizeof(CamelHookPair)); - hook_chunks = e_memchunk_new(16, sizeof(CamelHookList)); - type_lock = e_mutex_new(E_MUTEX_REC); - type_chunks = e_memchunk_new(32, sizeof(CamelType)); - type_table = g_hash_table_new(NULL, NULL); -} - -/* ************************************************************************ */ - -/* Should this return the object to the caller? */ -static void -cobject_init (CamelObject *o, CamelObjectClass *klass) -{ - o->klass = klass; - o->magic = CAMEL_OBJECT_MAGIC; - o->ref_count = 1; - o->flags = 0; -} - -static void -cobject_finalise(CamelObject *o) -{ - /*printf("%p: finalise %s\n", o, o->klass->name);*/ - - g_assert(o->ref_count == 0); - - camel_object_free_hooks(o); - - o->magic = CAMEL_OBJECT_FINALISED_MAGIC; - o->klass = NULL; -} - -static int -cobject_getv(CamelObject *o, CamelException *ex, CamelArgGetV *args) -{ - int i; - guint32 tag; - - for (i=0;iargc;i++) { - CamelArgGet *arg = &args->argv[i]; - - tag = arg->tag; - - switch (tag & CAMEL_ARG_TAG) { - case CAMEL_OBJECT_ARG_DESCRIPTION: - *arg->ca_str = (char *)o->klass->name; - break; - case CAMEL_OBJECT_ARG_METADATA: - *arg->ca_ptr = co_metadata_get(o); - break; - case CAMEL_OBJECT_ARG_STATE_FILE: { - CamelHookPair *pair = co_metadata_pair(o, FALSE); - - if (pair) { - *arg->ca_str = g_strdup(pair->func.filename); - camel_object_unget_hooks(o); - } - break; } - } - } - - /* could have flags or stuff here? */ - return 0; -} - -static int -cobject_setv(CamelObject *o, CamelException *ex, CamelArgV *args) -{ - int i; - guint32 tag; - - for (i=0;iargc;i++) { - CamelArg *arg = &args->argv[i]; - - tag = arg->tag; - - switch (tag & CAMEL_ARG_TAG) { - case CAMEL_OBJECT_ARG_STATE_FILE: { - CamelHookPair *pair; - - /* We store the filename on the meta-data hook-pair */ - pair = co_metadata_pair(o, TRUE); - g_free(pair->func.filename); - pair->func.filename = g_strdup(arg->ca_str); - camel_object_unget_hooks(o); - break; } - } - } - - /* could have flags or stuff here? */ - return 0; -} - -static void -cobject_free(CamelObject *o, guint32 tag, void *value) -{ - switch(tag & CAMEL_ARG_TAG) { - case CAMEL_OBJECT_ARG_METADATA: - co_metadata_free(o, value); - break; - case CAMEL_OBJECT_ARG_STATE_FILE: - g_free(value); - break; - case CAMEL_OBJECT_ARG_PERSISTENT_PROPERTIES: - g_slist_free((GSList *)value); - break; - } -} - -static char * -cobject_meta_get(CamelObject *obj, const char * name) -{ - CamelHookPair *pair; - CamelObjectMeta *meta; - char *res = NULL; - - g_return_val_if_fail(CAMEL_IS_OBJECT (obj), 0); - g_return_val_if_fail(name != NULL, 0); - - pair = co_metadata_pair(obj, FALSE); - if (pair) { - meta = pair->data; - while (meta) { - if (!strcmp(meta->name, name)) { - res = g_strdup(meta->value); - break; - } - meta = meta->next; - } - camel_object_unget_hooks(obj); - } - - return res; -} - -static gboolean -cobject_meta_set(CamelObject *obj, const char * name, const char *value) -{ - CamelHookPair *pair; - int changed = FALSE; - CamelObjectMeta *meta, *metap; - - g_return_val_if_fail(CAMEL_IS_OBJECT (obj), FALSE); - g_return_val_if_fail(name != NULL, FALSE); - - if (obj->hooks == NULL && value == NULL) - return FALSE; - - pair = co_metadata_pair(obj, TRUE); - meta = pair->data; - metap = (CamelObjectMeta *)&pair->data; - while (meta) { - if (!strcmp(meta->name, name)) - break; - metap = meta; - meta = meta->next; - } - - /* TODO: The camelobjectmeta structure is identical to - CamelTag, they could be merged or share common code */ - if (meta == NULL) { - if (value == NULL) - goto done; - meta = g_malloc(sizeof(*meta) + strlen(name)); - meta->next = pair->data; - pair->data = meta; - strcpy(meta->name, name); - meta->value = g_strdup(value); - changed = TRUE; - } else if (value == NULL) { - metap->next = meta->next; - g_free(meta->value); - g_free(meta); - changed = TRUE; - } else if (strcmp(meta->value, value) != 0) { - g_free(meta->value); - meta->value = g_strdup(value); - changed = TRUE; - } - -done: - camel_object_unget_hooks(obj); - - return changed; -} - -/* State file for CamelObject data. Any later versions should only append data. - - version:uint32 - - Version 0 of the file: - - version:uint32 = 0 - count:uint32 -- count of meta-data items - ( name:string value:string ) *count -- meta-data items - - Version 1 of the file adds: - count:uint32 -- count of persistent properties - ( tag:uing32 value:tagtype ) *count -- persistent properties - -*/ - -static int -cobject_state_read(CamelObject *obj, FILE *fp) -{ - guint32 i, count, version; - - /* NB: for later versions, just check the version is 1 .. known version */ - if (camel_file_util_decode_uint32(fp, &version) == -1 - || version > 1 - || camel_file_util_decode_uint32(fp, &count) == -1) - return -1; - - for (i=0;i 0) { - CamelArgV *argv; - - if (camel_file_util_decode_uint32(fp, &count) == -1 - || count == 0) { - /* maybe it was just version 0 afterall */ - return 0; - } - - /* we batch up the properties and set them in one go */ - argv = g_malloc(sizeof(*argv) + (count - CAMEL_ARGV_MAX) * sizeof(argv->argv[0])); - argv->argc = 0; - for (i=0;iargv[argv->argc].tag) == -1) - goto cleanup; - - /* so far,only do strings and ints, doubles could be added, - object's would require a serialisation interface */ - - switch(argv->argv[argv->argc].tag & CAMEL_ARG_TYPE) { - case CAMEL_ARG_INT: - case CAMEL_ARG_BOO: - if (camel_file_util_decode_uint32(fp, &argv->argv[argv->argc].ca_int) == -1) - goto cleanup; - break; - case CAMEL_ARG_STR: - if (camel_file_util_decode_string(fp, &argv->argv[argv->argc].ca_str) == -1) - goto cleanup; - break; - default: - goto cleanup; - } - - argv->argc++; - } - - camel_object_setv(obj, NULL, argv); - cleanup: - for (i=0;iargc;i++) { - if ((argv->argv[i].tag & CAMEL_ARG_TYPE) == CAMEL_ARG_STR) - g_free(argv->argv[i].ca_str); - } - g_free(argv); - } - - return 0; -} - -/* TODO: should pass exception around */ -static int -cobject_state_write(CamelObject *obj, FILE *fp) -{ - gint32 count, i; - CamelObjectMeta *meta = NULL, *scan; - int res = -1; - GSList *props = NULL, *l; - CamelArgGetV *arggetv = NULL; - CamelArgV *argv = NULL; - - camel_object_get(obj, NULL, CAMEL_OBJECT_METADATA, &meta, NULL); - - count = 0; - scan = meta; - while (scan) { - count++; - scan = scan->next; - } - - /* current version is 1 */ - if (camel_file_util_encode_uint32(fp, 1) == -1 - || camel_file_util_encode_uint32(fp, count) == -1) - goto abort; - - scan = meta; - while (scan) { - if (camel_file_util_encode_string(fp, meta->name) == -1 - || camel_file_util_encode_string(fp, meta->value) == -1) - goto abort; - scan = scan->next; - } - - camel_object_get(obj, NULL, CAMEL_OBJECT_PERSISTENT_PROPERTIES, &props, NULL); - - /* we build an arggetv to query the object atomically, - we also need an argv to store the results - bit messy */ - - count = g_slist_length(props); - - arggetv = g_malloc0(sizeof(*arggetv) + (count - CAMEL_ARGV_MAX) * sizeof(arggetv->argv[0])); - argv = g_malloc0(sizeof(*argv) + (count - CAMEL_ARGV_MAX) * sizeof(argv->argv[0])); - l = props; - i = 0; - while (l) { - CamelProperty *prop = l->data; - - argv->argv[i].tag = prop->tag; - arggetv->argv[i].tag = prop->tag; - arggetv->argv[i].ca_ptr = &argv->argv[i].ca_ptr; - - i++; - l = l->next; - } - arggetv->argc = i; - argv->argc = i; - - camel_object_getv(obj, NULL, arggetv); - - if (camel_file_util_encode_uint32(fp, count) == -1) - goto abort; - - for (i=0;iargc;i++) { - CamelArg *arg = &argv->argv[i]; - - if (camel_file_util_encode_uint32(fp, arg->tag) == -1) - goto abort; - - switch (arg->tag & CAMEL_ARG_TYPE) { - case CAMEL_ARG_INT: - case CAMEL_ARG_BOO: - if (camel_file_util_encode_uint32(fp, arg->ca_int) == -1) - goto abort; - break; - case CAMEL_ARG_STR: - if (camel_file_util_encode_string(fp, arg->ca_str) == -1) - goto abort; - break; - } - } - - res = 0; -abort: - for (i=0;iargc;i++) { - CamelArg *arg = &argv->argv[i]; - - if ((argv->argv[i].tag & CAMEL_ARG_TYPE) == CAMEL_ARG_STR) - camel_object_free(obj, arg->tag, arg->ca_str); - } - - g_free(argv); - g_free(arggetv); - - if (props) - camel_object_free(obj, CAMEL_OBJECT_PERSISTENT_PROPERTIES, props); - - if (meta) - camel_object_free(obj, CAMEL_OBJECT_METADATA, meta); - - return res; -} - - -static void -cobject_class_init(CamelObjectClass *klass) -{ - klass->magic = CAMEL_OBJECT_CLASS_MAGIC; - - klass->getv = cobject_getv; - klass->setv = cobject_setv; - klass->free = cobject_free; - - klass->meta_get = cobject_meta_get; - klass->meta_set = cobject_meta_set; - klass->state_read = cobject_state_read; - klass->state_write = cobject_state_write; - - camel_object_class_add_event(klass, "finalize", NULL); - camel_object_class_add_event(klass, "meta_changed", NULL); -} - -static void -cobject_class_finalise(CamelObjectClass * klass) -{ - klass->magic = CAMEL_OBJECT_CLASS_FINALISED_MAGIC; - - g_free(klass); -} - -CamelType -camel_object_get_type (void) -{ - if (camel_object_type == CAMEL_INVALID_TYPE) { - camel_type_init(); - - camel_object_type = camel_type_register(NULL, "CamelObject", /*, 0, 0*/ - sizeof(CamelObject), sizeof(CamelObjectClass), - cobject_class_init, cobject_class_finalise, - cobject_init, cobject_finalise); - } - - return camel_object_type; -} - -static void -camel_type_class_init(CamelObjectClass *klass, CamelObjectClass *type) -{ - if (type->parent) - camel_type_class_init(klass, type->parent); - - if (type->klass_init) - type->klass_init(klass); -} - -CamelType -camel_type_register (CamelType parent, const char * name, - /*unsigned int ver, unsigned int rev,*/ - size_t object_size, size_t klass_size, - CamelObjectClassInitFunc class_init, - CamelObjectClassFinalizeFunc class_finalise, - CamelObjectInitFunc object_init, - CamelObjectFinalizeFunc object_finalise) -{ - CamelObjectClass *klass; - /*int offset; - size_t size;*/ - - if (parent != NULL && parent->magic != CAMEL_OBJECT_CLASS_MAGIC) { - g_warning("camel_type_register: invalid junk parent class for '%s'", name); - return NULL; - } - - E_LOCK(type_lock); - - /* Have to check creation, it might've happened in another thread before we got here */ - klass = g_hash_table_lookup(type_table, name); - if (klass != NULL) { - if (klass->klass_size != klass_size || klass->object_size != object_size - || klass->klass_init != class_init || klass->klass_finalise != class_finalise - || klass->init != object_init || klass->finalise != object_finalise) { - g_warning("camel_type_register: Trying to re-register class '%s'", name); - klass = NULL; - } - E_UNLOCK(type_lock); - return klass; - } - - /* this is for objects with no parent as part of their struct ('interfaces'?) */ - /*offset = parent?parent->klass_size:0; - offset = (offset + 3) & (~3); - - size = offset + klass_size; - - klass = g_malloc0(size); - - klass->klass_size = size; - klass->klass_data = offset; - - offset = parent?parent->object_size:0; - offset = (offset + 3) & (~3); - - klass->object_size = offset + object_size; - klass->object_data = offset;*/ - - if (parent - && klass_size < parent->klass_size) { - g_warning("camel_type_register: '%s' has smaller class size than parent '%s'", name, parent->name); - E_UNLOCK(type_lock); - return NULL; - } - - klass = g_malloc0(klass_size); - klass->klass_size = klass_size; - klass->object_size = object_size; - klass->lock = g_mutex_new(); - klass->instance_chunks = e_memchunk_new(8, object_size); - - klass->parent = parent; - if (parent) { - klass->next = parent->child; - parent->child = klass; - } - klass->name = name; - - /*klass->version = ver; - klass->revision = rev;*/ - - klass->klass_init = class_init; - klass->klass_finalise = class_finalise; - - klass->init = object_init; - klass->finalise = object_finalise; - - /* setup before class init, incase class init func uses the type or looks it up ? */ - g_hash_table_insert(type_table, (void *)name, klass); - - camel_type_class_init(klass, klass); - - E_UNLOCK(type_lock); - - return klass; -} - -static void -camel_object_init(CamelObject *o, CamelObjectClass *klass, CamelType type) -{ - if (type->parent) - camel_object_init(o, klass, type->parent); - - if (type->init) - type->init(o, klass); -} - -CamelObject * -camel_object_new(CamelType type) -{ - CamelObject *o; - - if (type == NULL) - return NULL; - - if (type->magic != CAMEL_OBJECT_CLASS_MAGIC) - return NULL; - - CLASS_LOCK(type); - - o = e_memchunk_alloc0(type->instance_chunks); - -#ifdef CAMEL_OBJECT_TRACK_INSTANCES - if (type->instances) - type->instances->prev = o; - o->next = type->instances; - o->prev = NULL; - type->instances = o; -#endif - - CLASS_UNLOCK(type); - - camel_object_init(o, type, type); - - d(printf("%p: new %s()\n", o, o->klass->name)); - - return o; -} - -void -camel_object_ref(void *vo) -{ - register CamelObject *o = vo; - - g_return_if_fail(CAMEL_IS_OBJECT(o)); - - E_LOCK(type_lock); - - o->ref_count++; - d(printf("%p: ref %s(%d)\n", o, o->klass->name, o->ref_count)); - - E_UNLOCK(type_lock); -} - -void -camel_object_unref(void *vo) -{ - register CamelObject *o = vo; - register CamelObjectClass *klass, *k; - CamelHookList *hooks = NULL; - - g_return_if_fail(CAMEL_IS_OBJECT(o)); - - klass = o->klass; - - if (o->hooks) - hooks = camel_object_get_hooks(o); - - E_LOCK(type_lock); - - o->ref_count--; - - d(printf("%p: unref %s(%d)\n", o, o->klass->name, o->ref_count)); - - if (o->ref_count > 0 - || (o->flags & CAMEL_OBJECT_DESTROY)) { - E_UNLOCK(type_lock); - if (hooks) - camel_object_unget_hooks(o); - return; - } - - o->flags |= CAMEL_OBJECT_DESTROY; - - if (hooks) - camel_object_bag_remove_unlocked(NULL, o, hooks); - - E_UNLOCK(type_lock); - - if (hooks) - camel_object_unget_hooks(o); - - camel_object_trigger_event(o, "finalize", NULL); - - k = klass; - while (k) { - if (k->finalise) - k->finalise(o); - k = k->parent; - } - - o->magic = CAMEL_OBJECT_FINALISED_MAGIC; - - CLASS_LOCK(klass); -#ifdef CAMEL_OBJECT_TRACK_INSTANCES - if (o->prev) - o->prev->next = o->next; - else - klass->instances = o->next; - if (o->next) - o->next->prev = o->prev; -#endif - e_memchunk_free(klass->instance_chunks, o); - CLASS_UNLOCK(klass); -} - -const char * -camel_type_to_name (CamelType type) -{ - if (type == NULL) - return "(NULL class)"; - - if (type->magic == CAMEL_OBJECT_CLASS_MAGIC) - return type->name; - - return "(Junk class)"; -} - -CamelType camel_name_to_type(const char *name) -{ - /* TODO: Load a class off disk (!) */ - - return g_hash_table_lookup(type_table, name); -} - -static char * -desc_data(CamelObject *o, int ok) -{ - char *what; - - if (o == NULL) - what = g_strdup("NULL OBJECT"); - else if (o->magic == ok) - what = NULL; - else if (o->magic == CAMEL_OBJECT_MAGIC) - what = g_strdup_printf("CLASS '%s'", ((CamelObjectClass *)o)->name); - else if (o->magic == CAMEL_OBJECT_CLASS_MAGIC) - what = g_strdup_printf("CLASS '%s'", ((CamelObjectClass *)o)->name); - else if (o->magic == CAMEL_OBJECT_FINALISED_MAGIC) - what = g_strdup_printf("finalised OBJECT"); - else if (o->magic == CAMEL_OBJECT_CLASS_FINALISED_MAGIC) - what = g_strdup_printf("finalised CLASS"); - else - what = g_strdup_printf("junk data"); - - return what; -} - -static gboolean -check_magic(void *o, CamelType ctype, int isob) -{ - char *what, *to; - - what = desc_data(o, isob?CAMEL_OBJECT_MAGIC:CAMEL_OBJECT_CLASS_MAGIC); - to = desc_data((CamelObject *)ctype, CAMEL_OBJECT_CLASS_MAGIC); - - if (what || to) { - if (what == NULL) { - if (isob) - what = g_strdup_printf("OBJECT '%s'", ((CamelObject *)o)->klass->name); - else - what = g_strdup_printf("OBJECT '%s'", ((CamelObjectClass *)o)->name); - } - if (to == NULL) - to = g_strdup_printf("OBJECT '%s'", ctype->name); - g_warning("Trying to check %s is %s", what, to); - g_free(what); - g_free(to); - - return FALSE; - } - - return TRUE; -} - -gboolean -camel_object_is (CamelObject *o, CamelType ctype) -{ - CamelObjectClass *k; - - g_return_val_if_fail(check_magic(o, ctype, TRUE), FALSE); - - k = o->klass; - while (k) { - if (k == ctype) - return TRUE; - k = k->parent; - } - - return FALSE; -} - -gboolean -camel_object_class_is (CamelObjectClass *k, CamelType ctype) -{ - g_return_val_if_fail(check_magic(k, ctype, FALSE), FALSE); - - while (k) { - if (k == ctype) - return TRUE; - k = k->parent; - } - - return FALSE; -} - -CamelObject * -camel_object_cast(CamelObject *o, CamelType ctype) -{ - CamelObjectClass *k; - - g_return_val_if_fail(check_magic(o, ctype, TRUE), NULL); - - k = o->klass; - while (k) { - if (k == ctype) - return o; - k = k->parent; - } - - g_warning("Object %p (class '%s') doesn't have '%s' in its hierarchy", o, o->klass->name, ctype->name); - - return NULL; -} - -CamelObjectClass * -camel_object_class_cast(CamelObjectClass *k, CamelType ctype) -{ - CamelObjectClass *r = k; - - g_return_val_if_fail(check_magic(k, ctype, FALSE), NULL); - - while (k) { - if (k == ctype) - return r; - k = k->parent; - } - - g_warning("Class '%s' doesn't have '%s' in its hierarchy", r->name, ctype->name); - - return NULL; -} - -void -camel_object_class_add_event(CamelObjectClass *klass, const char *name, CamelObjectEventPrepFunc prep) -{ - CamelHookPair *pair; - - g_return_if_fail (name); - - pair = klass->hooks; - while (pair) { - if (strcmp(pair->name, name) == 0) { - g_warning("camel_object_class_add_event: `%s' is already declared for '%s'\n", - name, klass->name); - return; - } - pair = pair->next; - } - - pair = pair_alloc(); - pair->name = name; - pair->func.prep = prep; - pair->flags = 0; - - pair->next = klass->hooks; - klass->hooks = pair; -} - -/* free hook data */ -static void -camel_object_free_hooks (CamelObject *o) -{ - CamelHookPair *pair, *next; - - if (o->hooks) { - g_assert(o->hooks->depth == 0); - g_assert((o->hooks->flags & CAMEL_HOOK_PAIR_REMOVED) == 0); - - pair = o->hooks->list; - while (pair) { - next = pair->next; - - if (pair->name == meta_name) { - co_metadata_free(o, pair->data); - g_free(pair->func.filename); - } - - pair_free(pair); - pair = next; - } - e_mutex_destroy(o->hooks->lock); - hooks_free(o->hooks); - o->hooks = NULL; - } -} - -/* return (allocate if required) the object's hook list, locking at the same time */ -static CamelHookList * -camel_object_get_hooks (CamelObject *o) -{ - static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - CamelHookList *hooks; - - /* if we have it, we dont have to do any other locking, - otherwise use a global lock to setup the object's hook data */ - if (o->hooks == NULL) { - pthread_mutex_lock(&lock); - if (o->hooks == NULL) { - hooks = hooks_alloc(); - hooks->lock = e_mutex_new(E_MUTEX_REC); - hooks->flags = 0; - hooks->depth = 0; - hooks->list_length = 0; - hooks->list = NULL; - o->hooks = hooks; - } - pthread_mutex_unlock(&lock); - } - - e_mutex_lock(o->hooks->lock); - - return o->hooks; -} - -unsigned int -camel_object_hook_event(void *vo, const char * name, CamelObjectEventHookFunc func, void *data) -{ - CamelObject *obj = vo; - CamelHookPair *pair, *hook; - CamelHookList *hooks; - int id; - - g_return_val_if_fail(CAMEL_IS_OBJECT (obj), 0); - g_return_val_if_fail(name != NULL, 0); - g_return_val_if_fail(func != NULL, 0); - - hook = obj->klass->hooks; - while (hook) { - if (strcmp(hook->name, name) == 0) - goto setup; - hook = hook->next; - } - - g_warning("camel_object_hook_event: trying to hook event `%s' in class `%s' with no defined events.", - name, obj->klass->name); - - return 0; - -setup: - /* setup hook pair */ - pair = pair_alloc(); - pair->name = hook->name; /* effectively static! */ - pair->func.event = func; - pair->data = data; - pair->flags = 0; - id = pair->id; - - /* get the hook list object, locked, link in new event hook, unlock */ - hooks = camel_object_get_hooks(obj); - pair->next = hooks->list; - hooks->list = pair; - hooks->list_length++; - camel_object_unget_hooks(obj); - - return id; -} - -void -camel_object_remove_event(void *vo, unsigned int id) -{ - CamelObject *obj = vo; - CamelHookList *hooks; - CamelHookPair *pair, *parent; - - g_return_if_fail (CAMEL_IS_OBJECT (obj)); - g_return_if_fail (id != 0); - - if (obj->hooks == NULL) { - g_warning("camel_object_unhook_event: trying to unhook `%d` from an instance of `%s' with no hooks", - id, obj->klass->name); - return; - } - - /* scan hooks for this event, remove it, or flag it if we're busy */ - hooks = camel_object_get_hooks(obj); - parent = (CamelHookPair *)&hooks->list; - pair = parent->next; - while (pair) { - if (pair->id == id - && (pair->flags & CAMEL_HOOK_PAIR_REMOVED) == 0) { - if (hooks->depth > 0) { - pair->flags |= CAMEL_HOOK_PAIR_REMOVED; - hooks->flags |= CAMEL_HOOK_PAIR_REMOVED; - } else { - parent->next = pair->next; - pair_free(pair); - hooks->list_length--; - } - camel_object_unget_hooks(obj); - return; - } - parent = pair; - pair = pair->next; - } - camel_object_unget_hooks(obj); - - g_warning("camel_object_unhook_event: cannot find hook id %d in instance of `%s'", - id, obj->klass->name); -} - -void -camel_object_unhook_event(void *vo, const char * name, CamelObjectEventHookFunc func, void *data) -{ - CamelObject *obj = vo; - CamelHookList *hooks; - CamelHookPair *pair, *parent; - - g_return_if_fail (CAMEL_IS_OBJECT (obj)); - g_return_if_fail (name != NULL); - g_return_if_fail (func != NULL); - - if (obj->hooks == NULL) { - g_warning("camel_object_unhook_event: trying to unhook `%s` from an instance of `%s' with no hooks", - name, obj->klass->name); - return; - } - - /* scan hooks for this event, remove it, or flag it if we're busy */ - hooks = camel_object_get_hooks(obj); - parent = (CamelHookPair *)&hooks->list; - pair = parent->next; - while (pair) { - if (pair->func.event == func - && pair->data == data - && strcmp(pair->name, name) == 0 - && (pair->flags & CAMEL_HOOK_PAIR_REMOVED) == 0) { - if (hooks->depth > 0) { - pair->flags |= CAMEL_HOOK_PAIR_REMOVED; - hooks->flags |= CAMEL_HOOK_PAIR_REMOVED; - } else { - parent->next = pair->next; - pair_free(pair); - hooks->list_length--; - } - camel_object_unget_hooks(obj); - return; - } - parent = pair; - pair = pair->next; - } - camel_object_unget_hooks(obj); - - g_warning("camel_object_unhook_event: cannot find hook/data pair %p/%p in an instance of `%s' attached to `%s'", - func, data, obj->klass->name, name); -} - -void -camel_object_trigger_event(void *vo, const char * name, void *event_data) -{ - CamelObject *obj = vo; - CamelHookList *hooks; - CamelHookPair *pair, **pairs, *parent, *hook; - int i, size; - const char *prepname; - - g_return_if_fail (CAMEL_IS_OBJECT (obj)); - g_return_if_fail (name); - - hook = obj->klass->hooks; - while (hook) { - if (strcmp(hook->name, name) == 0) - goto trigger; - hook = hook->next; - } - - g_warning("camel_object_trigger_event: trying to trigger unknown event `%s' in class `%s'", - name, obj->klass->name); - - return; - -trigger: - /* try prep function, if false, then quit */ - if (hook->func.prep != NULL && !hook->func.prep(obj, event_data)) - return; - - /* also, no hooks, dont bother going further */ - if (obj->hooks == NULL) - return; - - /* lock the object for hook emission */ - camel_object_ref(obj); - hooks = camel_object_get_hooks(obj); - - if (hooks->list) { - /* first, copy the items in the list, and say we're in an event */ - hooks->depth++; - pair = hooks->list; - size = 0; - pairs = alloca(sizeof(pairs[0]) * hooks->list_length); - prepname = hook->name; - while (pair) { - if (pair->name == prepname) - pairs[size++] = pair; - pair = pair->next; - } - - /* now execute the events we have, if they haven't been removed during our calls */ - for (i=size-1;i>=0;i--) { - pair = pairs[i]; - if ((pair->flags & CAMEL_HOOK_PAIR_REMOVED) == 0) - (pair->func.event) (obj, event_data, pair->data); - } - hooks->depth--; - - /* and if we're out of any events, then clean up any pending removes */ - if (hooks->depth == 0 && (hooks->flags & CAMEL_HOOK_PAIR_REMOVED)) { - parent = (CamelHookPair *)&hooks->list; - pair = parent->next; - while (pair) { - if (pair->flags & CAMEL_HOOK_PAIR_REMOVED) { - parent->next = pair->next; - pair_free(pair); - hooks->list_length--; - } else { - parent = pair; - } - pair = parent->next; - } - hooks->flags &= ~CAMEL_HOOK_PAIR_REMOVED; - } - } - - camel_object_unget_hooks(obj); - camel_object_unref(obj); -} - -/* get/set arg methods */ -int camel_object_set(void *vo, CamelException *ex, ...) -{ - CamelArgV args; - CamelObject *o = vo; - CamelObjectClass *klass = o->klass; - int ret = 0; - - g_return_val_if_fail(CAMEL_IS_OBJECT(o), -1); - - camel_argv_start(&args, ex); - - while (camel_argv_build(&args) && ret == 0) - ret = klass->setv(o, ex, &args); - if (ret == 0) - ret = klass->setv(o, ex, &args); - - camel_argv_end(&args); - - return ret; -} - -int camel_object_setv(void *vo, CamelException *ex, CamelArgV *args) -{ - g_return_val_if_fail(CAMEL_IS_OBJECT(vo), -1); - - return ((CamelObject *)vo)->klass->setv(vo, ex, args); -} - -int camel_object_get(void *vo, CamelException *ex, ...) -{ - CamelObject *o = vo; - CamelArgGetV args; - CamelObjectClass *klass = o->klass; - int ret = 0; - - g_return_val_if_fail(CAMEL_IS_OBJECT(o), -1); - - camel_argv_start(&args, ex); - - while (camel_arggetv_build(&args) && ret == 0) - ret = klass->getv(o, ex, &args); - if (ret == 0) - ret = klass->getv(o, ex, &args); - - camel_argv_end(&args); - - return ret; -} - -int camel_object_getv(void *vo, CamelException *ex, CamelArgGetV *args) -{ - g_return_val_if_fail(CAMEL_IS_OBJECT(vo), -1); - - return ((CamelObject *)vo)->klass->getv(vo, ex, args); -} - -/* NB: If this doesn't return NULL, then you must unget_hooks when done */ -static CamelHookPair * -co_metadata_pair(CamelObject *obj, int create) -{ - CamelHookPair *pair; - CamelHookList *hooks; - - if (obj->hooks == NULL && !create) - return NULL; - - hooks = camel_object_get_hooks(obj); - pair = hooks->list; - while (pair) { - if (pair->name == meta_name) - return pair; - - pair = pair->next; - } - - if (create) { - pair = pair_alloc(); - pair->name = meta_name; - pair->data = NULL; - pair->flags = 0; - pair->func.filename = NULL; - pair->next = hooks->list; - hooks->list = pair; - hooks->list_length++; - } else { - camel_object_unget_hooks(obj); - } - - return pair; -} - -static CamelObjectMeta * -co_metadata_get(CamelObject *obj) -{ - CamelHookPair *pair; - CamelObjectMeta *meta = NULL, *metaout = NULL, *metalast; - - pair = co_metadata_pair(obj, FALSE); - if (pair) { - meta = pair->data; - - while (meta) { - CamelObjectMeta *m; - - m = g_malloc(sizeof(*metalast) + strlen(meta->name)); - m->next = NULL; - strcpy(m->name, meta->name); - m->value = g_strdup(meta->value); - if (metaout == NULL) - metalast = metaout = m; - else { - metalast->next = m; - metalast = m; - } - meta = meta->next; - } - - camel_object_unget_hooks(obj); - } - - return metaout; -} - -static void -co_metadata_free(CamelObject *obj, CamelObjectMeta *meta) -{ - while (meta) { - CamelObjectMeta *metan = meta->next; - - g_free(meta->value); - g_free(meta); - meta = metan; - } -} - -/** - * camel_object_meta_get: - * @vo: - * @name: - * - * Get a meta-data on an object. - * - * Return value: NULL if the meta-data is not set. - **/ -char * -camel_object_meta_get(void *vo, const char * name) -{ - CamelObject *obj = vo; - - g_return_val_if_fail(CAMEL_IS_OBJECT (obj), 0); - g_return_val_if_fail(name != NULL, 0); - - return obj->klass->meta_get(obj, name); -} - -/** - * camel_object_meta_set: - * @vo: - * @name: Name of meta-data. Should be prefixed with class of setter. - * @value: Value to set. If NULL, then the meta-data is removed. - * - * Set a meta-data item on an object. If the object supports persistent - * data, then the meta-data will be persistent across sessions. - * - * If the meta-data changes, is added, or removed, then a - * "meta_changed" event will be triggered with the name of the changed - * data. - * - * Return Value: TRUE if the setting caused a change to the object's - * metadata. - **/ -gboolean -camel_object_meta_set(void *vo, const char * name, const char *value) -{ - CamelObject *obj = vo; - - g_return_val_if_fail(CAMEL_IS_OBJECT (obj), FALSE); - g_return_val_if_fail(name != NULL, FALSE); - - if (obj->klass->meta_set(obj, name, value)) { - camel_object_trigger_event(obj, "meta_changed", (void *)name); - return TRUE; - } - - return FALSE; -} - -/** - * camel_object_state_read: - * @vo: - * - * Read persistent object state from object_set(CAMEL_OBJECT_STATE_FILE). - * - * Return value: -1 on error. - **/ -int camel_object_state_read(void *vo) -{ - CamelObject *obj = vo; - int res = -1; - char *file; - FILE *fp; - char magic[4]; - - camel_object_get(vo, NULL, CAMEL_OBJECT_STATE_FILE, &file, NULL); - if (file == NULL) - return 0; - - fp = fopen(file, "r"); - if (fp != NULL) { - if (fread(magic, 4, 1, fp) == 1 - && memcmp(magic, CAMEL_OBJECT_STATE_FILE_MAGIC, 4) == 0) - res = obj->klass->state_read(obj, fp); - else - res = -1; - fclose(fp); - } - - camel_object_free(vo, CAMEL_OBJECT_STATE_FILE, file); - - return res; -} - -/** - * camel_object_state_write: - * @vo: - * - * Write persistent state to the file as set by object_set(CAMEL_OBJECT_STATE_FILE). - * - * Return value: -1 on error. - **/ -int camel_object_state_write(void *vo) -{ - CamelObject *obj = vo; - int res = -1; - char *file, *savename; - FILE *fp; - - camel_object_get(vo, NULL, CAMEL_OBJECT_STATE_FILE, &file, NULL); - if (file == NULL) - return 0; - - savename = camel_file_util_savename(file); - fp = fopen(savename, "w"); - if (fp != NULL) { - if (fwrite(CAMEL_OBJECT_STATE_FILE_MAGIC, 4, 1, fp) == 1 - && obj->klass->state_write(obj, fp) == 0) { - if (fclose(fp) == 0) { - res = 0; - rename(savename, file); - } - } else { - fclose(fp); - } - } - - g_free(savename); - camel_object_free(vo, CAMEL_OBJECT_STATE_FILE, file); - - return res; -} - -/* free an arg object, you can only free objects 1 at a time */ -void camel_object_free(void *vo, guint32 tag, void *value) -{ - g_return_if_fail(CAMEL_IS_OBJECT(vo)); - - /* We could also handle freeing of args differently - - Add a 'const' bit to the arg type field, - specifying that the object should not be freed. - - And, add free handlers for any pointer objects which are - not const. The free handlers would be hookpairs off of the - class. - - Then we handle the basic types OBJ,STR here, and pass PTR - types to their appropriate handler, without having to pass - through the invocation heirarchy of the free method. - - This would also let us copy and do other things with args - we can't do, but i can't see a use for that yet ... */ - - ((CamelObject *)vo)->klass->free(vo, tag, value); -} - -static void -object_class_dump_tree_rec(CamelType root, int depth) -{ - char *p; -#ifdef CAMEL_OBJECT_TRACK_INSTANCES - struct _CamelObject *o; -#endif - - p = alloca(depth*2+1); - memset(p, ' ', depth*2); - p[depth*2] = 0; - - while (root) { - CLASS_LOCK(root); - printf("%sClass: %s\n", p, root->name); - /*printf("%sVersion: %u.%u\n", p, root->version, root->revision);*/ - if (root->hooks) { - CamelHookPair *pair = root->hooks; - - while (pair) { - printf("%s event '%s' prep %p\n", p, pair->name, pair->func.prep); - pair = pair->next; - } - } -#ifdef CAMEL_OBJECT_TRACK_INSTANCES - o = root->instances; - while (o) { - printf("%s instance %p [%d]\n", p, o, o->ref_count); - /* todo: should lock hooks while it scans them */ - if (o->hooks) { - CamelHookPair *pair = o->hooks->list; - - while (pair) { - printf("%s hook '%s' func %p data %p\n", p, pair->name, pair->func.event, pair->data); - pair = pair->next; - } - } - o = o->next; - } -#endif - CLASS_UNLOCK(root); - - if (root->child) - object_class_dump_tree_rec(root->child, depth+1); - - root = root->next; - } -} - -void -camel_object_class_dump_tree(CamelType root) -{ - object_class_dump_tree_rec(root, 0); -} - -CamelObjectBag * -camel_object_bag_new (GHashFunc hash, GEqualFunc equal, CamelCopyFunc keycopy, GFreeFunc keyfree) -{ - CamelObjectBag *bag; - - bag = g_malloc(sizeof(*bag)); - bag->object_table = g_hash_table_new(hash, equal); - bag->copy_key = keycopy; - bag->free_key = keyfree; - bag->key_table = g_hash_table_new(NULL, NULL); - bag->owner = 0; - - /* init the semaphore to 1 owner, this is who has reserved the bag for adding */ - sem_init(&bag->reserve_sem, 0, 1); - - return bag; -} - -static void -save_object(void *key, CamelObject *o, GPtrArray *objects) -{ - g_ptr_array_add(objects, o); -} - -void -camel_object_bag_destroy (CamelObjectBag *bag) -{ - GPtrArray *objects = g_ptr_array_new(); - int i; - - sem_getvalue(&bag->reserve_sem, &i); - g_assert(i == 1); - - g_hash_table_foreach(bag->object_table, (GHFunc)save_object, objects); - for (i=0;ilen;i++) - camel_object_bag_remove(bag, objects->pdata[i]); - - g_ptr_array_free(objects, TRUE); - g_hash_table_destroy(bag->object_table); - g_hash_table_destroy(bag->key_table); - sem_destroy(&bag->reserve_sem); - g_free(bag); -} - -void -camel_object_bag_add (CamelObjectBag *bag, const void *key, void *vo) -{ - CamelObject *o = vo; - CamelHookList *hooks; - CamelHookPair *pair; - void *k; - - hooks = camel_object_get_hooks(o); - E_LOCK(type_lock); - - pair = hooks->list; - while (pair) { - if (pair->name == bag_name && pair->data == bag) { - E_UNLOCK(type_lock); - camel_object_unget_hooks(o); - return; - } - pair = pair->next; - } - - pair = pair_alloc(); - pair->name = bag_name; - pair->data = bag; - pair->flags = 0; - - pair->next = hooks->list; - hooks->list = pair; - hooks->list_length++; - - k = bag->copy_key(key); - g_hash_table_insert(bag->object_table, k, vo); - g_hash_table_insert(bag->key_table, vo, k); - - if (bag->owner == pthread_self()) { - bag->owner = 0; - sem_post(&bag->reserve_sem); - } - - E_UNLOCK(type_lock); - camel_object_unget_hooks(o); -} - -void * -camel_object_bag_get (CamelObjectBag *bag, const void *key) -{ - CamelObject *o; - - E_LOCK(type_lock); - - o = g_hash_table_lookup(bag->object_table, key); - if (o) { - /* we use the same lock as the refcount */ - o->ref_count++; - } else if (bag->owner != pthread_self()) { - E_UNLOCK(type_lock); - sem_wait(&bag->reserve_sem); - E_LOCK(type_lock); - /* re-check if it slipped in */ - o = g_hash_table_lookup(bag->object_table, key); - if (o) - o->ref_count++; - /* we dont want to reserve the bag */ - sem_post(&bag->reserve_sem); - } - - E_UNLOCK(type_lock); - - return o; -} - -/* like get, but also reserve a spot for key if it isn't there */ -/* After calling reserve, you MUST call bag_abort or bag_add */ -/* Also note that currently you can only reserve a single key - at any one time in a given thread */ -void * -camel_object_bag_reserve (CamelObjectBag *bag, const void *key) -{ - CamelObject *o; - - E_LOCK(type_lock); - - o = g_hash_table_lookup(bag->object_table, key); - if (o) { - o->ref_count++; - } else { - g_assert(bag->owner != pthread_self()); - E_UNLOCK(type_lock); - sem_wait(&bag->reserve_sem); - E_LOCK(type_lock); - /* incase its slipped in while we were waiting */ - o = g_hash_table_lookup(bag->object_table, key); - if (o) { - o->ref_count++; - /* in which case we dont need to reserve the bag either */ - sem_post(&bag->reserve_sem); - } else { - bag->owner = pthread_self(); - } - } - - E_UNLOCK(type_lock); - - return o; -} - -/* abort a reserved key */ -void -camel_object_bag_abort (CamelObjectBag *bag, const void *key) -{ - g_assert(bag->owner == pthread_self()); - - bag->owner = 0; - sem_post(&bag->reserve_sem); -} - -static void -save_bag(void *key, CamelObject *o, GPtrArray *list) -{ - /* we have the refcount lock already */ - o->ref_count++; - g_ptr_array_add(list, o); -} - -/* get a list of all objects in the bag, ref'd - ignores any reserved keys */ -GPtrArray * -camel_object_bag_list (CamelObjectBag *bag) -{ - GPtrArray *list; - - list = g_ptr_array_new(); - - E_LOCK(type_lock); - g_hash_table_foreach(bag->object_table, (GHFunc)save_bag, list); - E_UNLOCK(type_lock); - - return list; -} - -/* if bag is NULL, remove all bags from object */ -static void -camel_object_bag_remove_unlocked (CamelObjectBag *inbag, CamelObject *o, CamelHookList *hooks) -{ - CamelHookPair *pair, *parent; - void *oldkey; - CamelObjectBag *bag; - - parent = (CamelHookPair *)&hooks->list; - pair = parent->next; - while (pair) { - if (pair->name == bag_name - && (inbag == NULL || inbag == pair->data)) { - bag = pair->data; - /* lookup object in table? */ - oldkey = g_hash_table_lookup(bag->key_table, o); - if (oldkey) { - g_hash_table_remove(bag->key_table, o); - g_hash_table_remove(bag->object_table, oldkey); - bag->free_key(oldkey); - } - parent->next = pair->next; - pair_free(pair); - hooks->list_length--; - } else { - parent = pair; - } - pair = parent->next; - } -} - -void -camel_object_bag_remove (CamelObjectBag *inbag, void *vo) -{ - CamelObject *o = vo; - CamelHookList *hooks; - - if (o->hooks == NULL) - return; - - hooks = camel_object_get_hooks(o); - E_LOCK(type_lock); - - camel_object_bag_remove_unlocked(inbag, o, hooks); - - E_UNLOCK(type_lock); - camel_object_unget_hooks(o); -} diff --git a/camel/camel-object.h b/camel/camel-object.h deleted file mode 100644 index 33ecefbb0a..0000000000 --- a/camel/camel-object.h +++ /dev/null @@ -1,290 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-object.h: Base class for Camel */ - -/* - * Author: - * Dan Winship - * Michael Zucchi - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_OBJECT_H -#define CAMEL_OBJECT_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include /* FILE */ -#include /* size_t */ -#include -#include - -#include -#include /* this is a @##$@#SF stupid header */ - -/* this crap shouldn't be here */ -#include - -/* turn on so that camel_object_class_dump_tree() dumps object instances as well */ -#define CAMEL_OBJECT_TRACK_INSTANCES - -typedef struct _CamelObjectClass *CamelType; - -#ifdef G_DISABLE_CHECKS -#define CAMEL_CHECK_CAST(obj, ctype, ptype) ((ptype *) obj) -#define CAMEL_CHECK_CLASS_CAST(klass, ctype, ptype) ((ptype *) klass) -#else -#define CAMEL_CHECK_CAST(obj, ctype, ptype) ((ptype *) camel_object_cast ((CamelObject *)(obj), (CamelType)(ctype))) -#define CAMEL_CHECK_CLASS_CAST(klass, ctype, ptype) ((ptype *) camel_object_class_cast ((CamelObjectClass *)(klass), (CamelType)(ctype) )) -#endif -#define CAMEL_CHECK_TYPE(obj, ctype) (camel_object_is ((CamelObject *)(obj), (CamelType)(ctype) )) -#define CAMEL_CHECK_CLASS_TYPE(klass, ctype) (camel_object_class_is ((CamelObjectClass *)(klass), (CamelType)(ctype))) - -extern CamelType camel_object_type; - -#define CAMEL_OBJECT_TYPE (camel_object_type) - -/* we can't check casts till we've got the type, use the global type variable because its cheaper */ -#define CAMEL_OBJECT(obj) (CAMEL_CHECK_CAST((obj), camel_object_type, CamelObject)) -#define CAMEL_OBJECT_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), camel_object_type, CamelObjectClass)) -#define CAMEL_IS_OBJECT(o) (CAMEL_CHECK_TYPE((o), camel_object_type)) -#define CAMEL_IS_OBJECT_CLASS(k) (CAMEL_CHECK_CLASS_TYPE((k), camel_object_type)) - -#define CAMEL_OBJECT_GET_CLASS(o) ((CamelObjectClass *)(CAMEL_OBJECT(o))->klass) -#define CAMEL_OBJECT_GET_TYPE(o) ((CamelType)(CAMEL_OBJECT(o))->klass) - -typedef struct _CamelObjectClass CamelObjectClass; -typedef struct _CamelObject CamelObject; -typedef unsigned int CamelObjectHookID; -typedef struct _CamelObjectMeta CamelObjectMeta; - -typedef void (*CamelObjectClassInitFunc) (CamelObjectClass *); -typedef void (*CamelObjectClassFinalizeFunc) (CamelObjectClass *); -typedef void (*CamelObjectInitFunc) (CamelObject *, CamelObjectClass *); -typedef void (*CamelObjectFinalizeFunc) (CamelObject *); - -typedef gboolean (*CamelObjectEventPrepFunc) (CamelObject *, gpointer); -typedef void (*CamelObjectEventHookFunc) (CamelObject *, gpointer, gpointer); - -#define CAMEL_INVALID_TYPE (NULL) - -/* camel object args. */ -enum { - /* Get a description of the object. */ - CAMEL_OBJECT_ARG_DESCRIPTION = CAMEL_ARG_FIRST, /* Get a copy of the meta-data list (should be freed) */ - CAMEL_OBJECT_ARG_METADATA, - CAMEL_OBJECT_ARG_STATE_FILE, - CAMEL_OBJECT_ARG_PERSISTENT_PROPERTIES, -}; - -enum { - CAMEL_OBJECT_DESCRIPTION = CAMEL_OBJECT_ARG_DESCRIPTION | CAMEL_ARG_STR, - /* Returns a CamelObjectMeta list */ - CAMEL_OBJECT_METADATA = CAMEL_OBJECT_ARG_METADATA | CAMEL_ARG_PTR, - /* sets where the persistent data should reside, otherwise it isn't persistent */ - CAMEL_OBJECT_STATE_FILE = CAMEL_OBJECT_ARG_STATE_FILE | CAMEL_ARG_STR, - /* returns a GSList CamelProperties of persistent properties */ - CAMEL_OBJECT_PERSISTENT_PROPERTIES = CAMEL_OBJECT_ARG_PERSISTENT_PROPERTIES | CAMEL_ARG_PTR, -}; - -enum _CamelObjectFlags { - CAMEL_OBJECT_DESTROY = (1<<0), -}; - -/* returned by get::CAMEL_OBJECT_METADATA */ -struct _CamelObjectMeta { - struct _CamelObjectMeta *next; - - char *value; - char name[1]; /* allocated as part of structure */ -}; - -/* TODO: create a simpleobject which has no events on it, or an interface for events */ -struct _CamelObject { - struct _CamelObjectClass *klass; - - guint32 magic; /* only really needed for debugging ... */ - - /* current hooks on this object */ - struct _CamelHookList *hooks; - - guint32 ref_count:24; - guint32 flags:8; - -#ifdef CAMEL_OBJECT_TRACK_INSTANCES - struct _CamelObject *next, *prev; -#endif -}; - -struct _CamelObjectClass -{ - struct _CamelObjectClass *parent; - - guint32 magic; /* in same spot for validation */ - - struct _CamelObjectClass *next, *child; /* maintain heirarchy, just for kicks */ - - const char *name; - - void *lock; /* lock when used in threading, else just pads struct */ - - /*unsigned short version, revision;*/ - - /* if the object's bigger than 64K, it could use redesigning */ - unsigned short object_size/*, object_data*/; - unsigned short klass_size/*, klass_data*/; - - /* available hooks for this class */ - struct _CamelHookPair *hooks; - - /* memchunks for this type */ - struct _EMemChunk *instance_chunks; -#ifdef CAMEL_OBJECT_TRACK_INSTANCES - struct _CamelObject *instances; -#endif - - /* init class */ - void (*klass_init)(struct _CamelObjectClass *); - void (*klass_finalise)(struct _CamelObjectClass *); - - /* init/finalise object */ - void (*init)(struct _CamelObject *, struct _CamelObjectClass *); - void (*finalise)(struct _CamelObject *); - - /* get/set interface */ - int (*setv)(struct _CamelObject *, struct _CamelException *ex, CamelArgV *args); - int (*getv)(struct _CamelObject *, struct _CamelException *ex, CamelArgGetV *args); - /* we only free 1 at a time, and only pointer types, obviously */ - void (*free)(struct _CamelObject *, guint32 tag, void *ptr); - - /* get/set meta-data interface */ - char *(*meta_get)(struct _CamelObject *, const char * name); - gboolean (*meta_set)(struct _CamelObject *, const char * name, const char *value); - - /* persistence stuff */ - int (*state_read)(struct _CamelObject *, FILE *fp); - int (*state_write)(struct _CamelObject *, FILE *fp); -}; - -/* The type system .... it's pretty simple..... */ -void camel_type_init (void); -CamelType camel_type_register(CamelType parent, const char * name, /*unsigned int ver, unsigned int rev,*/ - size_t instance_size, - size_t classfuncs_size, - CamelObjectClassInitFunc class_init, - CamelObjectClassFinalizeFunc class_finalize, - CamelObjectInitFunc instance_init, - CamelObjectFinalizeFunc instance_finalize); - -/* deprecated interface */ -#define camel_type_get_global_classfuncs(x) ((CamelObjectClass *)(x)) - -/* object class methods (types == classes now) */ -const char *camel_type_to_name (CamelType type); -CamelType camel_name_to_type (const char *name); -void camel_object_class_add_event (CamelObjectClass *klass, const char *name, CamelObjectEventPrepFunc prep); - -void camel_object_class_dump_tree (CamelType root); - -/* casting */ -CamelObject *camel_object_cast(CamelObject *obj, CamelType ctype); -gboolean camel_object_is(CamelObject *obj, CamelType ctype); - -CamelObjectClass *camel_object_class_cast (CamelObjectClass *klass, CamelType ctype); -gboolean camel_object_class_is (CamelObjectClass *klass, CamelType ctype); - -CamelType camel_object_get_type (void); - -CamelObject *camel_object_new (CamelType type); -CamelObject *camel_object_new_name (const char *name); - -void camel_object_ref(void *); -void camel_object_unref(void *); - -#ifdef CAMEL_DEBUG -#define camel_object_ref(o) (printf("%s (%s:%d):ref (%p)\n", __FUNCTION__, __FILE__, __LINE__, o), camel_object_ref(o)) -#define camel_object_unref(o) (printf("%s (%s:%d):unref (%p)\n", __FUNCTION__, __FILE__, __LINE__, o), camel_object_unref (o)) -#endif - -/* hooks */ -CamelObjectHookID camel_object_hook_event(void *obj, const char *name, CamelObjectEventHookFunc hook, void *data); -void camel_object_remove_event(void *obj, CamelObjectHookID id); -void camel_object_unhook_event(void *obj, const char *name, CamelObjectEventHookFunc hook, void *data); -void camel_object_trigger_event(void *obj, const char *name, void *event_data); - -/* get/set methods */ -int camel_object_set(void *obj, struct _CamelException *ex, ...); -int camel_object_setv(void *obj, struct _CamelException *ex, CamelArgV *); -int camel_object_get(void *obj, struct _CamelException *ex, ...); -int camel_object_getv(void *obj, struct _CamelException *ex, CamelArgGetV *); - -/* meta-data for user-specific data */ -char *camel_object_meta_get(void *vo, const char * name); -gboolean camel_object_meta_set(void *vo, const char * name, const char *value); - -/* reads/writes the state from/to the CAMEL_OBJECT_STATE_FILE */ -int camel_object_state_read(void *vo); -int camel_object_state_write(void *vo); - -/* free a bunch of objects, list must be 0 terminated */ -void camel_object_free(void *vo, guint32 tag, void *value); - -/* for managing bags of weakly-ref'd 'child' objects */ -typedef struct _CamelObjectBag CamelObjectBag; -typedef void *(*CamelCopyFunc)(const void *vo); - -CamelObjectBag *camel_object_bag_new(GHashFunc hash, GEqualFunc equal, CamelCopyFunc keycopy, GFreeFunc keyfree); -void *camel_object_bag_get(CamelObjectBag *bag, const void *key); -void *camel_object_bag_reserve(CamelObjectBag *bag, const void *key); -void camel_object_bag_add(CamelObjectBag *bag, const void *key, void *o); -void camel_object_bag_abort(CamelObjectBag *bag, const void *key); -GPtrArray *camel_object_bag_list(CamelObjectBag *bag); -void camel_object_bag_remove(CamelObjectBag *bag, void *o); -void camel_object_bag_destroy(CamelObjectBag *bag); - -#define CAMEL_MAKE_CLASS(type, tname, parent, pname) \ -static CamelType type##_type; \ -static pname##Class * type##_parent_class; \ - \ -CamelType \ -type##_get_type(void) \ -{ \ - if (type##_type == 0) { \ - type##_parent_class = (pname##Class *)parent##_get_type(); \ - type##_type = camel_type_register( \ - type##_parent_class, #tname "Class", \ - sizeof(tname), \ - sizeof(tname ## Class), \ - (CamelObjectClassInitFunc) type##_class_init, \ - NULL, \ - (CamelObjectInitFunc) type##_init, \ - (CamelObjectFinalizeFunc) type##_finalise); \ - } \ - \ - return type##_type; \ -} - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_OBJECT_H */ diff --git a/camel/camel-operation.c b/camel/camel-operation.c deleted file mode 100644 index 03c0c77617..0000000000 --- a/camel/camel-operation.c +++ /dev/null @@ -1,687 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Michael Zucchi - * - * Copyright 2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include -#include -#include -#include -#ifdef HAVE_NSS -#include -#endif - -#include "camel-operation.h" -#include "e-util/e-msgport.h" - -#define d(x) - -/* ********************************************************************** */ - -struct _status_stack { - guint32 flags; - char *msg; - int pc; /* last pc reported */ - unsigned int stamp; /* last stamp reported */ -}; - -struct _CamelOperation { - struct _CamelOperation *next; - struct _CamelOperation *prev; - - pthread_t id; /* id of running thread */ - guint32 flags; /* cancelled ? */ - int blocked; /* cancellation blocked depth */ - int refcount; - - CamelOperationStatusFunc status; - void *status_data; - unsigned int status_update; - - /* stack of status messages (struct _status_stack *) */ - GSList *status_stack; - struct _status_stack *lastreport; - - EMsgPort *cancel_port; - int cancel_fd; -#ifdef HAVE_NSS - PRFileDesc *cancel_prfd; -#endif -}; - -#define CAMEL_OPERATION_CANCELLED (1<<0) -#define CAMEL_OPERATION_TRANSIENT (1<<1) - -/* Delay before a transient operation has any effect on the status */ -#define CAMEL_OPERATION_TRANSIENT_DELAY (5) - -static pthread_mutex_t operation_lock = PTHREAD_MUTEX_INITIALIZER; -#define LOCK() pthread_mutex_lock(&operation_lock) -#define UNLOCK() pthread_mutex_unlock(&operation_lock) - - -static unsigned int stamp (void); -static EDList operation_list = E_DLIST_INITIALISER(operation_list); -static pthread_key_t operation_key; - -typedef struct _CamelOperationMsg { - EMsg msg; -} CamelOperationMsg ; - -/** - * camel_operation_init: - * @void: - * - * Init internal variables. Only call this once. - **/ -void -camel_operation_init(void) -{ - pthread_key_create(&operation_key, NULL); -} - -/** - * camel_operation_new: - * @status: Callback for receiving status messages. This will always - * be called with an internal lock held. - * @status_data: User data. - * - * Create a new camel operation handle. Camel operation handles can - * be used in a multithreaded application (or a single operation - * handle can be used in a non threaded appliation) to cancel running - * operations and to obtain notification messages of the internal - * status of messages. - * - * Return value: A new operation handle. - **/ -CamelOperation * -camel_operation_new (CamelOperationStatusFunc status, void *status_data) -{ - CamelOperation *cc; - - cc = g_malloc0(sizeof(*cc)); - - cc->flags = 0; - cc->blocked = 0; - cc->refcount = 1; - cc->status = status; - cc->status_data = status_data; - cc->cancel_port = e_msgport_new(); - cc->cancel_fd = -1; - - LOCK(); - e_dlist_addtail(&operation_list, (EDListNode *)cc); - UNLOCK(); - - return cc; -} - -/** - * camel_operation_mute: - * @cc: - * - * mutes a camel operation permanently. from this point on you will never - * receive operation updates, even if more are sent. - **/ -void -camel_operation_mute(CamelOperation *cc) -{ - LOCK(); - cc->status = NULL; - cc->status_data = NULL; - UNLOCK(); -} - -/** - * camel_operation_registered: - * - * Returns the registered operation, or %NULL if none registered. - **/ -CamelOperation * -camel_operation_registered (void) -{ - CamelOperation *cc = (CamelOperation *)pthread_getspecific(operation_key); - - if (cc) - camel_operation_ref(cc); - - return cc; -} - -/** - * camel_operation_ref: - * @cc: operation context - * - * Add a reference to the CamelOperation @cc. - **/ -void -camel_operation_ref (CamelOperation *cc) -{ - g_assert(cc->refcount > 0); - - LOCK(); - cc->refcount++; - UNLOCK(); -} - -/** - * camel_operation_unref: - * @cc: operation context - * - * Unref and potentially free @cc. - **/ -void -camel_operation_unref (CamelOperation *cc) -{ - GSList *n; - - g_assert(cc->refcount > 0); - - LOCK(); - if (cc->refcount == 1) { - CamelOperationMsg *msg; - - e_dlist_remove((EDListNode *)cc); - - while ((msg = (CamelOperationMsg *)e_msgport_get(cc->cancel_port))) - g_free(msg); - - e_msgport_destroy(cc->cancel_port); - - n = cc->status_stack; - while (n) { - g_warning("Camel operation status stack non empty: %s", (char *)n->data); - g_free(n->data); - n = n->next; - } - g_slist_free(cc->status_stack); - - g_free(cc); - } else { - cc->refcount--; - } - UNLOCK(); -} - -/** - * camel_operation_cancel_block: - * @cc: operation context - * - * Block cancellation for this operation. If @cc is NULL, then the - * current thread is blocked. - **/ -void -camel_operation_cancel_block (CamelOperation *cc) -{ - if (cc == NULL) - cc = (CamelOperation *)pthread_getspecific(operation_key); - - if (cc) { - LOCK(); - cc->blocked++; - UNLOCK(); - } -} - -/** - * camel_operation_cancel_unblock: - * @cc: operation context - * - * Unblock cancellation, when the unblock count reaches the block - * count, then this operation can be cancelled. If @cc is NULL, then - * the current thread is unblocked. - **/ -void -camel_operation_cancel_unblock (CamelOperation *cc) -{ - if (cc == NULL) - cc = (CamelOperation *)pthread_getspecific(operation_key); - - if (cc) { - LOCK(); - cc->blocked--; - UNLOCK(); - } -} - -/** - * camel_operation_cancel: - * @cc: operation context - * - * Cancel a given operation. If @cc is NULL then all outstanding - * operations are cancelled. - **/ -void -camel_operation_cancel (CamelOperation *cc) -{ - CamelOperationMsg *msg; - - LOCK(); - - if (cc == NULL) { - CamelOperation *cn; - - cc = (CamelOperation *)operation_list.head; - cn = cc->next; - while (cn) { - cc->flags |= CAMEL_OPERATION_CANCELLED; - msg = g_malloc0(sizeof(*msg)); - e_msgport_put(cc->cancel_port, (EMsg *)msg); - cc = cn; - cn = cn->next; - } - } else if ((cc->flags & CAMEL_OPERATION_CANCELLED) == 0) { - d(printf("cancelling thread %d\n", cc->id)); - - cc->flags |= CAMEL_OPERATION_CANCELLED; - msg = g_malloc0(sizeof(*msg)); - e_msgport_put(cc->cancel_port, (EMsg *)msg); - } - - UNLOCK(); -} - -/** - * camel_operation_register: - * @cc: operation context - * - * Register a thread or the main thread for cancellation through @cc. - * If @cc is NULL, then a new cancellation is created for this thread. - * - * All calls to operation_register() should be matched with calls to - * operation_unregister(), or resources will be lost. - * - * Return Value: Returns @cc, or if NULL, the new operation. - * - **/ -CamelOperation * -camel_operation_register (CamelOperation *cc) -{ - CamelOperation *oldcc = pthread_getspecific(operation_key); - - pthread_setspecific(operation_key, cc); - - return oldcc; -} - -/** - * camel_operation_unregister: - * @cc: operation context - * - * Unregister the current thread. - **/ -void -camel_operation_unregister (CamelOperation *cc) -{ - pthread_setspecific(operation_key, NULL); -} - -/** - * camel_operation_cancel_check: - * @cc: operation context - * - * Check if cancellation has been applied to @cc. If @cc is NULL, - * then the CamelOperation registered for the current thread is used. - * - * Return value: TRUE if the operation has been cancelled. - **/ -gboolean -camel_operation_cancel_check (CamelOperation *cc) -{ - CamelOperationMsg *msg; - int cancelled; - - d(printf("checking for cancel in thread %d\n", pthread_self())); - - if (cc == NULL) - cc = (CamelOperation *)pthread_getspecific(operation_key); - - LOCK(); - - if (cc == NULL || cc->blocked > 0) { - d(printf("ahah! cancellation is blocked\n")); - cancelled = FALSE; - } else if (cc->flags & CAMEL_OPERATION_CANCELLED) { - d(printf("previously cancelled\n")); - cancelled = TRUE; - } else if ((msg = (CamelOperationMsg *)e_msgport_get(cc->cancel_port))) { - d(printf("Got cancellation message\n")); - g_free(msg); - cc->flags |= CAMEL_OPERATION_CANCELLED; - cancelled = TRUE; - } else - cancelled = FALSE; - - UNLOCK(); - - return cancelled; -} - -/** - * camel_operation_cancel_fd: - * @cc: operation context - * - * Retrieve a file descriptor that can be waited on (select, or poll) - * for read, to asynchronously detect cancellation. - * - * Return value: The fd, or -1 if cancellation is not available - * (blocked, or has not been registered for this thread). - **/ -int -camel_operation_cancel_fd (CamelOperation *cc) -{ - if (cc == NULL) - cc = (CamelOperation *)pthread_getspecific(operation_key); - - if (cc == NULL || cc->blocked) - return -1; - - LOCK(); - - if (cc->cancel_fd == -1) - cc->cancel_fd = e_msgport_fd(cc->cancel_port); - - UNLOCK(); - - return cc->cancel_fd; -} - -#ifdef HAVE_NSS -/** - * camel_operation_cancel_prfd: - * @cc: operation context - * - * Retrieve a file descriptor that can be waited on (select, or poll) - * for read, to asynchronously detect cancellation. - * - * Return value: The fd, or NULL if cancellation is not available - * (blocked, or has not been registered for this thread). - **/ -PRFileDesc * -camel_operation_cancel_prfd (CamelOperation *cc) -{ - if (cc == NULL) - cc = (CamelOperation *)pthread_getspecific(operation_key); - - if (cc == NULL || cc->blocked) - return NULL; - - LOCK(); - - if (cc->cancel_prfd == NULL) - cc->cancel_prfd = e_msgport_prfd(cc->cancel_port); - - UNLOCK(); - - return cc->cancel_prfd; -} -#endif /* HAVE_NSS */ - -/** - * camel_operation_start: - * @cc: operation context - * @what: action being performed (printf-style format string) - * @Varargs: varargs - * - * Report the start of an operation. All start operations should have - * similar end operations. - **/ -void -camel_operation_start (CamelOperation *cc, char *what, ...) -{ - va_list ap; - char *msg; - struct _status_stack *s; - - if (cc == NULL) - cc = (CamelOperation *)pthread_getspecific(operation_key); - - if (cc == NULL) - return; - - LOCK(); - - if (cc->status == NULL) { - UNLOCK(); - return; - } - - va_start(ap, what); - msg = g_strdup_vprintf(what, ap); - va_end(ap); - cc->status_update = 0; - s = g_malloc0(sizeof(*s)); - s->msg = msg; - s->flags = 0; - cc->lastreport = s; - cc->status_stack = g_slist_prepend(cc->status_stack, s); - - UNLOCK(); - - cc->status(cc, msg, CAMEL_OPERATION_START, cc->status_data); - - d(printf("start '%s'\n", msg, pc)); -} - -/** - * camel_operation_start_transient: - * @cc: operation context - * @what: printf-style format string describing the action being performed - * @Varargs: varargs - * - * Start a transient event. We only update this to the display if it - * takes very long to process, and if we do, we then go back to the - * previous state when finished. - **/ -void -camel_operation_start_transient (CamelOperation *cc, char *what, ...) -{ - va_list ap; - char *msg; - struct _status_stack *s; - - if (cc == NULL) - cc = (CamelOperation *)pthread_getspecific(operation_key); - - if (cc == NULL || cc->status == NULL) - return; - - LOCK(); - - va_start(ap, what); - msg = g_strdup_vprintf(what, ap); - va_end(ap); - cc->status_update = 0; - s = g_malloc0(sizeof(*s)); - s->msg = msg; - s->flags = CAMEL_OPERATION_TRANSIENT; - s->stamp = stamp(); - cc->status_stack = g_slist_prepend(cc->status_stack, s); - d(printf("start '%s'\n", msg, pc)); - - UNLOCK(); - - /* we dont report it yet */ - /*cc->status(cc, msg, CAMEL_OPERATION_START, cc->status_data);*/ -} - -static unsigned int stamp(void) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - /* update 4 times/second */ - return (tv.tv_sec * 4) + tv.tv_usec / (1000000/4); -} - -/** - * camel_operation_progress: - * @cc: Operation to report to. - * @pc: Percent complete, 0 to 100. - * - * Report progress on the current operation. If @cc is NULL, then the - * currently registered operation is used. @pc reports the current - * percentage of completion, which should be in the range of 0 to 100. - * - * If the total percentage is not know, then use - * camel_operation_progress_count(). - **/ -void -camel_operation_progress (CamelOperation *cc, int pc) -{ - unsigned int now; - struct _status_stack *s; - char *msg = NULL; - - if (cc == NULL) - cc = (CamelOperation *)pthread_getspecific(operation_key); - - if (cc == NULL) - return; - - LOCK(); - - if (cc->status == NULL || cc->status_stack == NULL) { - UNLOCK(); - return; - } - - s = cc->status_stack->data; - s->pc = pc; - - /* Transient messages dont start updating till 4 seconds after - they started, then they update every second */ - now = stamp(); - if (cc->status_update == now) { - cc = NULL; - } else if (s->flags & CAMEL_OPERATION_TRANSIENT) { - if (s->stamp + CAMEL_OPERATION_TRANSIENT_DELAY > now) { - cc = NULL; - } else { - cc->status_update = now; - cc->lastreport = s; - msg = g_strdup(s->msg); - } - } else { - s->stamp = cc->status_update = now; - cc->lastreport = s; - msg = g_strdup(s->msg); - } - - UNLOCK(); - - if (cc) { - cc->status(cc, msg, pc, cc->status_data); - g_free(msg); - } -} - -/** - * camel_operation_progress_count: - * @cc: operation context - * @sofar: - * - **/ -void -camel_operation_progress_count (CamelOperation *cc, int sofar) -{ - camel_operation_progress(cc, sofar); -} - -/** - * camel_operation_end: - * @cc: operation context - * @what: Format string. - * @Varargs: varargs - * - * Report the end of an operation. If @cc is NULL, then the currently - * registered operation is notified. - **/ -void -camel_operation_end (CamelOperation *cc) -{ - struct _status_stack *s, *p; - unsigned int now; - char *msg = NULL; - int pc = 0; - - if (cc == NULL) - cc = (CamelOperation *)pthread_getspecific(operation_key); - - if (cc == NULL) - return; - - LOCK(); - - if (cc->status == NULL || cc->status_stack == NULL) { - UNLOCK(); - return; - } - - /* so what we do here is this. If the operation that just - * ended was transient, see if we have any other transient - * messages that haven't been updated yet above us, otherwise, - * re-update as a non-transient at the last reported pc */ - now = stamp(); - s = cc->status_stack->data; - if (s->flags & CAMEL_OPERATION_TRANSIENT) { - if (cc->lastreport == s) { - GSList *l = cc->status_stack->next; - while (l) { - p = l->data; - if (p->flags & CAMEL_OPERATION_TRANSIENT) { - if (p->stamp + CAMEL_OPERATION_TRANSIENT_DELAY < now) { - msg = g_strdup(p->msg); - pc = p->pc; - cc->lastreport = p; - break; - } - } else { - msg = g_strdup(p->msg); - pc = p->pc; - cc->lastreport = p; - break; - } - l = l->next; - } - } - g_free(s->msg); - } else { - msg = s->msg; - pc = CAMEL_OPERATION_END; - cc->lastreport = s; - } - g_free(s); - cc->status_stack = g_slist_remove_link(cc->status_stack, cc->status_stack); - - UNLOCK(); - - if (msg) { - cc->status(cc, msg, pc, cc->status_data); - g_free(msg); - } -} diff --git a/camel/camel-operation.h b/camel/camel-operation.h deleted file mode 100644 index 62e29dc2ac..0000000000 --- a/camel/camel-operation.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi - * - * Copyright 2001 Ximian, Inc. (www.ximian.com/) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_OPERATION_H -#define CAMEL_OPERATION_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -/* cancellation helper stuff, not yet finalised */ - -typedef struct _CamelOperation CamelOperation; - -typedef void (*CamelOperationStatusFunc)(struct _CamelOperation *op, const char *what, int pc, void *data); - -enum _camel_operation_status_t { - CAMEL_OPERATION_START = -1, - CAMEL_OPERATION_END = -2, -}; - -/* main thread functions */ -void camel_operation_init(void); - -CamelOperation *camel_operation_new(CamelOperationStatusFunc status, void *status_data); -void camel_operation_mute(CamelOperation *cc); -void camel_operation_ref(CamelOperation *cc); -void camel_operation_unref(CamelOperation *cc); -void camel_operation_cancel(CamelOperation *cc); -/* subthread functions */ -CamelOperation *camel_operation_register(CamelOperation *cc); -void camel_operation_unregister (CamelOperation *cc); - -/* called internally by camel, for the current thread */ -void camel_operation_cancel_block(CamelOperation *cc); -void camel_operation_cancel_unblock(CamelOperation *cc); -int camel_operation_cancel_check(CamelOperation *cc); -int camel_operation_cancel_fd(CamelOperation *cc); -#ifdef HAVE_NSS -struct PRFileDesc *camel_operation_cancel_prfd(CamelOperation *cc); -#endif -/* return the registered operation for this thread, if there is one */ -CamelOperation *camel_operation_registered(void); - -void camel_operation_start(CamelOperation *cc, char *what, ...); -void camel_operation_start_transient(CamelOperation *cc, char *what, ...); -void camel_operation_progress(CamelOperation *cc, int pc); -void camel_operation_progress_count(CamelOperation *cc, int sofar); -void camel_operation_end(CamelOperation *cc); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_OPERATION_H */ diff --git a/camel/camel-partition-table.c b/camel/camel-partition-table.c deleted file mode 100644 index e5b2639a4a..0000000000 --- a/camel/camel-partition-table.c +++ /dev/null @@ -1,998 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2001-2003 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "e-util/e-msgport.h" - -#include "camel-block-file.h" -#include "camel-partition-table.h" - -/* Do we synchronously write table updates - makes the - tables consistent after program crash without sync */ -/*#define SYNC_UPDATES*/ - -#define d(x) /*(printf("%s(%d):%s: ", __FILE__, __LINE__, __PRETTY_FUNCTION__),(x))*/ -/* key index debug */ -#define k(x) /*(printf("%s(%d):%s: ", __FILE__, __LINE__, __PRETTY_FUNCTION__),(x))*/ - - -struct _CamelPartitionTablePrivate { - pthread_mutex_t lock; /* for locking partition */ -}; - -#define CAMEL_PARTITION_TABLE_LOCK(kf, lock) (pthread_mutex_lock(&(kf)->priv->lock)) -#define CAMEL_PARTITION_TABLE_UNLOCK(kf, lock) (pthread_mutex_unlock(&(kf)->priv->lock)) - - -static void -camel_partition_table_class_init(CamelPartitionTableClass *klass) -{ -} - -static void -camel_partition_table_init(CamelPartitionTable *cpi) -{ - struct _CamelPartitionTablePrivate *p; - - e_dlist_init(&cpi->partition); - - p = cpi->priv = g_malloc0(sizeof(*cpi->priv)); - pthread_mutex_init(&p->lock, NULL); -} - -static void -camel_partition_table_finalise(CamelPartitionTable *cpi) -{ - CamelBlock *bl; - struct _CamelPartitionTablePrivate *p; - - p = cpi->priv; - - if (cpi->blocks) { - while ((bl = (CamelBlock *)e_dlist_remhead(&cpi->partition))) { - camel_block_file_sync_block(cpi->blocks, bl); - camel_block_file_unref_block(cpi->blocks, bl); - } - camel_block_file_sync(cpi->blocks); - - camel_object_unref((CamelObject *)cpi->blocks); - } - - pthread_mutex_destroy(&p->lock); - - g_free(p); - -} - -CamelType -camel_partition_table_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_object_get_type(), "CamelPartitionTable", - sizeof (CamelPartitionTable), - sizeof (CamelPartitionTableClass), - (CamelObjectClassInitFunc) camel_partition_table_class_init, - NULL, - (CamelObjectInitFunc) camel_partition_table_init, - (CamelObjectFinalizeFunc) camel_partition_table_finalise); - } - - return type; -} - -/* ********************************************************************** */ - -/* - Have 2 hashes: - Name -> nameid - Word -> wordid - -nameid is pointer to name file, includes a bit to say if name is deleted -wordid is a pointer to word file, includes pointer to start of word entries - -delete a name -> set it as deleted, do nothing else though - -lookup word, if nameid is deleted, mark it in wordlist as unused and mark for write (?) -*/ - -/* ********************************************************************** */ - -/* This simple hash seems to work quite well */ -static camel_hash_t hash_key(const char *key) -{ - camel_hash_t hash = 0xABADF00D; - - while (*key) { - hash = hash * (*key) ^ (*key); - key++; - } - - return hash; -} - -/* Call with lock held */ -static CamelBlock *find_partition(CamelPartitionTable *cpi, camel_hash_t id, int *indexp) -{ - int index, jump; - CamelBlock *bl; - CamelPartitionMapBlock *ptb; - CamelPartitionMap *part; - - /* first, find the block this key might be in, then binary search the block */ - bl = (CamelBlock *)cpi->partition.head; - while (bl->next) { - ptb = (CamelPartitionMapBlock *)&bl->data; - part = ptb->partition; - if (ptb->used > 0 && id <= part[ptb->used-1].hashid) { - index = ptb->used/2; - jump = ptb->used/4; - - if (jump == 0) - jump = 1; - - while (1) { - if (id <= part[index].hashid) { - if (index == 0 || id > part[index-1].hashid) - break; - index -= jump; - } else { - if (index >= ptb->used-1) - break; - index += jump; - } - jump = jump/2; - if (jump == 0) - jump = 1; - } - *indexp = index; - - return bl; - } - bl = bl->next; - } - - g_warning("could not find a partition that could fit ! partition table corrupt!"); - - /* This should never be reached */ - - return NULL; -} - -CamelPartitionTable *camel_partition_table_new(struct _CamelBlockFile *bs, camel_block_t root) -{ - CamelPartitionTable *cpi; - CamelPartitionMapBlock *ptb; - CamelPartitionKeyBlock *kb; - CamelBlock *block, *pblock; - - cpi = (CamelPartitionTable *)camel_object_new(camel_partition_table_get_type()); - cpi->rootid = root; - cpi->blocks = bs; - camel_object_ref((CamelObject *)bs); - - /* read the partition table into memory */ - do { - block = camel_block_file_get_block(bs, root); - if (block == NULL) - goto fail; - - ptb = (CamelPartitionMapBlock *)&block->data; - - d(printf("Adding partition block, used = %d, hashid = %08x\n", ptb->used, ptb->partition[0].hashid)); - - /* if we have no data, prime initial block */ - if (ptb->used == 0 && e_dlist_empty(&cpi->partition) && ptb->next == 0) { - pblock = camel_block_file_new_block(bs); - if (pblock == NULL) { - camel_block_file_unref_block(bs, block); - goto fail; - } - kb = (CamelPartitionKeyBlock *)&pblock->data; - kb->used = 0; - ptb->used = 1; - ptb->partition[0].hashid = 0xffffffff; - ptb->partition[0].blockid = pblock->id; - camel_block_file_touch_block(bs, pblock); - camel_block_file_unref_block(bs, pblock); - camel_block_file_touch_block(bs, block); -#ifdef SYNC_UPDATES - camel_block_file_sync_block(bs, block); -#endif - } - - root = ptb->next; - camel_block_file_detach_block(bs, block); - e_dlist_addtail(&cpi->partition, (EDListNode *)block); - } while (root); - - return cpi; - -fail: - camel_object_unref((CamelObject *)cpi); - return NULL; -} - -/* sync our blocks, the caller must still sync the blockfile itself */ -int -camel_partition_table_sync(CamelPartitionTable *cpi) -{ - CamelBlock *bl, *bn; - struct _CamelPartitionTablePrivate *p; - int ret = 0; - - CAMEL_PARTITION_TABLE_LOCK(cpi, lock); - - p = cpi->priv; - - if (cpi->blocks) { - bl = (CamelBlock *)cpi->partition.head; - bn = bl->next; - while (bn) { - ret = camel_block_file_sync_block(cpi->blocks, bl); - if (ret == -1) - goto fail; - bl = bn; - bn = bn->next; - } - } -fail: - CAMEL_PARTITION_TABLE_UNLOCK(cpi, lock); - - return ret; -} - -camel_key_t camel_partition_table_lookup(CamelPartitionTable *cpi, const char *key) -{ - CamelPartitionKeyBlock *pkb; - CamelPartitionMapBlock *ptb; - CamelBlock *block, *ptblock; - camel_hash_t hashid; - camel_key_t keyid = 0; - int index, i; - - hashid = hash_key(key); - - CAMEL_PARTITION_TABLE_LOCK(cpi, lock); - - ptblock = find_partition(cpi, hashid, &index); - if (ptblock == NULL) { - CAMEL_PARTITION_TABLE_UNLOCK(cpi, lock); - return 0; - } - ptb = (CamelPartitionMapBlock *)&ptblock->data; - block = camel_block_file_get_block(cpi->blocks, ptb->partition[index].blockid); - if (block == NULL) { - CAMEL_PARTITION_TABLE_UNLOCK(cpi, lock); - return 0; - } - - pkb = (CamelPartitionKeyBlock *)&block->data; - - /* What to do about duplicate hash's? */ - for (i=0;iused;i++) { - if (pkb->keys[i].hashid == hashid) { - /* !! need to: lookup and compare string value */ - /* get_key() if key == key ... */ - keyid = pkb->keys[i].keyid; - break; - } - } - - CAMEL_PARTITION_TABLE_UNLOCK(cpi, lock); - - camel_block_file_unref_block(cpi->blocks, block); - - return keyid; -} - -void camel_partition_table_remove(CamelPartitionTable *cpi, const char *key) -{ - CamelPartitionKeyBlock *pkb; - CamelPartitionMapBlock *ptb; - CamelBlock *block, *ptblock; - camel_hash_t hashid; - camel_key_t keyid = 0; - int index, i; - - hashid = hash_key(key); - - CAMEL_PARTITION_TABLE_LOCK(cpi, lock); - - ptblock = find_partition(cpi, hashid, &index); - if (ptblock == NULL) { - CAMEL_PARTITION_TABLE_UNLOCK(cpi, lock); - return; - } - ptb = (CamelPartitionMapBlock *)&ptblock->data; - block = camel_block_file_get_block(cpi->blocks, ptb->partition[index].blockid); - if (block == NULL) { - CAMEL_PARTITION_TABLE_UNLOCK(cpi, lock); - return; - } - pkb = (CamelPartitionKeyBlock *)&block->data; - - /* What to do about duplicate hash's? */ - for (i=0;iused;i++) { - if (pkb->keys[i].hashid == hashid) { - /* !! need to: lookup and compare string value */ - /* get_key() if key == key ... */ - keyid = pkb->keys[i].keyid; - - /* remove this key */ - pkb->used--; - for (;iused;i++) { - pkb->keys[i].keyid = pkb->keys[i+1].keyid; - pkb->keys[i].hashid = pkb->keys[i+1].hashid; - } - camel_block_file_touch_block(cpi->blocks, block); - break; - } - } - - CAMEL_PARTITION_TABLE_UNLOCK(cpi, lock); - - camel_block_file_unref_block(cpi->blocks, block); -} - -static int -keys_cmp(const void *ap, const void *bp) -{ - const CamelPartitionKey *a = ap; - const CamelPartitionKey *b = bp; - - if (a->hashid < b->hashid) - return -1; - else if (a->hashid > b->hashid) - return 1; - - return 0; -} - -int -camel_partition_table_add(CamelPartitionTable *cpi, const char *key, camel_key_t keyid) -{ - camel_hash_t hashid, partid; - int index, newindex = 0; /* initialisation of this and pkb/nkb is just to silence compiler */ - CamelPartitionMapBlock *ptb, *ptn; - CamelPartitionKeyBlock *kb, *newkb, *nkb = NULL, *pkb = NULL; - CamelBlock *block, *ptblock, *ptnblock; - int i, half, len; - struct _CamelPartitionKey keys[CAMEL_BLOCK_SIZE/4]; - int ret = -1; - -#define KEY_SIZE (sizeof(kb->keys)/sizeof(kb->keys[0])) - - hashid = hash_key(key); - - CAMEL_PARTITION_TABLE_LOCK(cpi, lock); - ptblock = find_partition(cpi, hashid, &index); - if (ptblock == NULL) { - CAMEL_PARTITION_TABLE_UNLOCK(cpi, lock); - return -1; - } - ptb = (CamelPartitionMapBlock *)&ptblock->data; - block = camel_block_file_get_block(cpi->blocks, ptb->partition[index].blockid); - if (block == NULL) { - CAMEL_PARTITION_TABLE_UNLOCK(cpi, lock); - return -1; - } - kb = (CamelPartitionKeyBlock *)&block->data; - - /* TODO: Keep the key array in sorted order, cheaper lookups and split operation */ - - if (kb->used < sizeof(kb->keys)/sizeof(kb->keys[0])) { - /* Have room, just put it in */ - kb->keys[kb->used].hashid = hashid; - kb->keys[kb->used].keyid = keyid; - kb->used++; - } else { - CamelBlock *newblock = NULL, *nblock = NULL, *pblock = NULL; - - /* Need to split? See if previous or next has room, then split across that instead */ - - /* TODO: Should look at next/previous partition table block as well ... */ - - if (index > 0) { - pblock = camel_block_file_get_block(cpi->blocks, ptb->partition[index-1].blockid); - if (pblock == NULL) - goto fail; - pkb = (CamelPartitionKeyBlock *)&pblock->data; - } - if (index < (ptb->used-1)) { - nblock = camel_block_file_get_block(cpi->blocks, ptb->partition[index+1].blockid); - if (nblock == NULL) { - if (pblock) - camel_block_file_unref_block(cpi->blocks, pblock); - goto fail; - } - nkb = (CamelPartitionKeyBlock *)&nblock->data; - } - - if (pblock && pkb->used < KEY_SIZE) { - if (nblock && nkb->used < KEY_SIZE) { - if (pkb->used < nkb->used) { - newindex = index+1; - newblock = nblock; - } else { - newindex = index-1; - newblock = pblock; - } - } else { - newindex = index-1; - newblock = pblock; - } - } else { - if (nblock && nkb->used < KEY_SIZE) { - newindex = index+1; - newblock = nblock; - } - } - - /* We had no room, need to split across another block */ - if (newblock == NULL) { - /* See if we have room in the partition table for this block or need to split that too */ - if (ptb->used >= sizeof(ptb->partition)/sizeof(ptb->partition[0])) { - /* TODO: Could check next block to see if it'll fit there first */ - ptnblock = camel_block_file_new_block(cpi->blocks); - if (ptnblock == NULL) { - if (nblock) - camel_block_file_unref_block(cpi->blocks, nblock); - if (pblock) - camel_block_file_unref_block(cpi->blocks, pblock); - goto fail; - } - camel_block_file_detach_block(cpi->blocks, ptnblock); - - /* split block and link on-disk, always sorted */ - ptn = (CamelPartitionMapBlock *)&ptnblock->data; - ptn->next = ptb->next; - ptb->next = ptnblock->id; - len = ptb->used / 2; - ptn->used = ptb->used - len; - ptb->used = len; - memcpy(ptn->partition, &ptb->partition[len], ptn->used * sizeof(ptb->partition[0])); - - /* link in-memory */ - ptnblock->next = ptblock->next; - ptblock->next->prev = ptnblock; - ptblock->next = ptnblock; - ptnblock->prev = ptblock; - - /* write in right order to ensure structure */ - camel_block_file_touch_block(cpi->blocks, ptnblock); -#ifdef SYNC_UPDATES - camel_block_file_sync_block(cpi->blocks, ptnblock); -#endif - if (index > len) { - camel_block_file_touch_block(cpi->blocks, ptblock); -#ifdef SYNC_UPDATES - camel_block_file_sync_block(cpi->blocks, ptblock); -#endif - index -= len; - ptb = ptn; - ptblock = ptnblock; - } - } - - /* try get newblock before modifying existing */ - newblock = camel_block_file_new_block(cpi->blocks); - if (newblock == NULL) { - if (nblock) - camel_block_file_unref_block(cpi->blocks, nblock); - if (pblock) - camel_block_file_unref_block(cpi->blocks, pblock); - goto fail; - } - - for (i=ptb->used-1;i>index;i--) { - ptb->partition[i+1].hashid = ptb->partition[i].hashid; - ptb->partition[i+1].blockid = ptb->partition[i].blockid; - } - ptb->used++; - - newkb = (CamelPartitionKeyBlock *)&newblock->data; - newkb->used = 0; - newindex = index+1; - - ptb->partition[newindex].hashid = ptb->partition[index].hashid; - ptb->partition[newindex].blockid = newblock->id; - - if (nblock) - camel_block_file_unref_block(cpi->blocks, nblock); - if (pblock) - camel_block_file_unref_block(cpi->blocks, pblock); - } else { - newkb = (CamelPartitionKeyBlock *)&newblock->data; - - if (newblock == pblock) { - if (nblock) - camel_block_file_unref_block(cpi->blocks, nblock); - } else { - if (pblock) - camel_block_file_unref_block(cpi->blocks, pblock); - } - } - - /* sort keys to find midpoint */ - len = kb->used; - memcpy(keys, kb->keys, sizeof(kb->keys[0])*len); - memcpy(keys+len, newkb->keys, sizeof(newkb->keys[0])*newkb->used); - len += newkb->used; - keys[len].hashid = hashid; - keys[len].keyid = keyid; - len++; - qsort(keys, len, sizeof(keys[0]), keys_cmp); - - /* Split keys, fix partition table */ - half = len/2; - partid = keys[half-1].hashid; - - if (index < newindex) { - memcpy(kb->keys, keys, sizeof(keys[0])*half); - kb->used = half; - memcpy(newkb->keys, keys+half, sizeof(keys[0])*(len-half)); - newkb->used = len-half; - ptb->partition[index].hashid = partid; - } else { - memcpy(newkb->keys, keys, sizeof(keys[0])*half); - newkb->used = half; - memcpy(kb->keys, keys+half, sizeof(keys[0])*(len-half)); - kb->used = len-half; - ptb->partition[newindex].hashid = partid; - } - - camel_block_file_touch_block(cpi->blocks, ptblock); -#ifdef SYNC_UPDATES - camel_block_file_sync_block(cpi->blocks, ptblock); -#endif - camel_block_file_touch_block(cpi->blocks, newblock); - camel_block_file_unref_block(cpi->blocks, newblock); - } - - camel_block_file_touch_block(cpi->blocks, block); - camel_block_file_unref_block(cpi->blocks, block); - - ret = 0; -fail: - CAMEL_PARTITION_TABLE_UNLOCK(cpi, lock); - - return ret; -} - -/* ********************************************************************** */ - - -struct _CamelKeyTablePrivate { - pthread_mutex_t lock; /* for locking key */ -}; - -#define CAMEL_KEY_TABLE_LOCK(kf, lock) (pthread_mutex_lock(&(kf)->priv->lock)) -#define CAMEL_KEY_TABLE_UNLOCK(kf, lock) (pthread_mutex_unlock(&(kf)->priv->lock)) - - -static void -camel_key_table_class_init(CamelKeyTableClass *klass) -{ -} - -static void -camel_key_table_init(CamelKeyTable *ki) -{ - struct _CamelKeyTablePrivate *p; - - p = ki->priv = g_malloc0(sizeof(*ki->priv)); - pthread_mutex_init(&p->lock, NULL); -} - -static void -camel_key_table_finalise(CamelKeyTable *ki) -{ - struct _CamelKeyTablePrivate *p; - - p = ki->priv; - - if (ki->blocks) { - if (ki->root_block) { - camel_block_file_sync_block(ki->blocks, ki->root_block); - camel_block_file_unref_block(ki->blocks, ki->root_block); - } - camel_block_file_sync(ki->blocks); - camel_object_unref((CamelObject *)ki->blocks); - } - - pthread_mutex_destroy(&p->lock); - - g_free(p); - -} - -CamelType -camel_key_table_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_object_get_type(), "CamelKeyTable", - sizeof (CamelKeyTable), - sizeof (CamelKeyTableClass), - (CamelObjectClassInitFunc) camel_key_table_class_init, - NULL, - (CamelObjectInitFunc) camel_key_table_init, - (CamelObjectFinalizeFunc) camel_key_table_finalise); - } - - return type; -} - - -CamelKeyTable * -camel_key_table_new(CamelBlockFile *bs, camel_block_t root) -{ - CamelKeyTable *ki; - - ki = (CamelKeyTable *)camel_object_new(camel_key_table_get_type()); - - ki->blocks = bs; - camel_object_ref((CamelObject *)bs); - ki->rootid = root; - - ki->root_block = camel_block_file_get_block(bs, ki->rootid); - if (ki->root_block == NULL) { - camel_object_unref((CamelObject *)ki); - ki = NULL; - } else { - camel_block_file_detach_block(bs, ki->root_block); - ki->root = (CamelKeyRootBlock *)&ki->root_block->data; - - k(printf("Opening key index\n")); - k(printf(" first %u\n last %u\n free %u\n", ki->root->first, ki->root->last, ki->root->free)); - } - - return ki; -} - -int -camel_key_table_sync(CamelKeyTable *ki) -{ -#ifdef SYNC_UPDATES - return 0; -#else - return camel_block_file_sync_block(ki->blocks, ki->root_block); -#endif -} - -camel_key_t -camel_key_table_add(CamelKeyTable *ki, const char *key, camel_block_t data, unsigned int flags) -{ - CamelBlock *last, *next; - CamelKeyBlock *kblast, *kbnext; - int len, left; - unsigned int offset; - camel_key_t keyid = 0; - - /* Maximum key size = 128 chars */ - len = strlen(key); - if (len > CAMEL_KEY_TABLE_MAX_KEY) - len = 128; - - CAMEL_KEY_TABLE_LOCK(ki, lock); - - if (ki->root->last == 0) { - last = camel_block_file_new_block(ki->blocks); - if (last == NULL) - goto fail; - ki->root->last = ki->root->first = last->id; - camel_block_file_touch_block(ki->blocks, ki->root_block); - k(printf("adding first block, first = %u\n", ki->root->first)); - } else { - last = camel_block_file_get_block(ki->blocks, ki->root->last); - if (last == NULL) - goto fail; - } - - kblast = (CamelKeyBlock *)&last->data; - - if (kblast->used >= 127) - goto fail; - - if (kblast->used > 0) { - /*left = &kblast->u.keydata[kblast->u.keys[kblast->used-1].offset] - (char *)(&kblast->u.keys[kblast->used+1]);*/ - left = kblast->u.keys[kblast->used-1].offset - sizeof(kblast->u.keys[0])*(kblast->used+1); - d(printf("key '%s' used = %d (%d), filled = %d, left = %d len = %d?\n", - key, kblast->used, kblast->used * sizeof(kblast->u.keys[0]), - sizeof(kblast->u.keydata) - kblast->u.keys[kblast->used-1].offset, - left, len)); - if (left < len) { - next = camel_block_file_new_block(ki->blocks); - if (next == NULL) { - camel_block_file_unref_block(ki->blocks, last); - goto fail; - } - kbnext = (CamelKeyBlock *)&next->data; - kblast->next = next->id; - ki->root->last = next->id; - d(printf("adding new block, first = %u, last = %u\n", ki->root->first, ki->root->last)); - camel_block_file_touch_block(ki->blocks, ki->root_block); - camel_block_file_touch_block(ki->blocks, last); - camel_block_file_unref_block(ki->blocks, last); - kblast = kbnext; - last = next; - } - } - - if (kblast->used > 0) - offset = kblast->u.keys[kblast->used-1].offset - len; - else - offset = sizeof(kblast->u.keydata)-len; - - kblast->u.keys[kblast->used].flags = flags; - kblast->u.keys[kblast->used].data = data; - kblast->u.keys[kblast->used].offset = offset; - memcpy(kblast->u.keydata + offset, key, len); - - keyid = (last->id & (~(CAMEL_BLOCK_SIZE-1))) | kblast->used; - - kblast->used++; - - g_assert(kblast->used < 127); - - camel_block_file_touch_block(ki->blocks, last); - camel_block_file_unref_block(ki->blocks, last); - -#ifdef SYNC_UPDATES - camel_block_file_sync_block(ki->blocks, ki->root_block); -#endif -fail: - CAMEL_KEY_TABLE_UNLOCK(ki, lock); - - return keyid; -} - -void -camel_key_table_set_data(CamelKeyTable *ki, camel_key_t keyid, camel_block_t data) -{ - CamelBlock *bl; - camel_block_t blockid; - int index; - CamelKeyBlock *kb; - - if (keyid == 0) - return; - - blockid = keyid & (~(CAMEL_BLOCK_SIZE-1)); - index = keyid & (CAMEL_BLOCK_SIZE-1); - - bl = camel_block_file_get_block(ki->blocks, blockid); - if (bl == NULL) - return; - kb = (CamelKeyBlock *)&bl->data; - - CAMEL_KEY_TABLE_LOCK(ki, lock); - - if (kb->u.keys[index].data != data) { - kb->u.keys[index].data = data; - camel_block_file_touch_block(ki->blocks, bl); - } - - CAMEL_KEY_TABLE_UNLOCK(ki, lock); - - camel_block_file_unref_block(ki->blocks, bl); -} - -void -camel_key_table_set_flags(CamelKeyTable *ki, camel_key_t keyid, unsigned int flags, unsigned int set) -{ - CamelBlock *bl; - camel_block_t blockid; - int index; - CamelKeyBlock *kb; - unsigned int old; - - if (keyid == 0) - return; - - blockid = keyid & (~(CAMEL_BLOCK_SIZE-1)); - index = keyid & (CAMEL_BLOCK_SIZE-1); - - bl = camel_block_file_get_block(ki->blocks, blockid); - if (bl == NULL) - return; - kb = (CamelKeyBlock *)&bl->data; - - g_assert(kb->used < 127); - g_assert(index < kb->used); - - CAMEL_KEY_TABLE_LOCK(ki, lock); - - old = kb->u.keys[index].flags; - if ((old & set) != (flags & set)) { - kb->u.keys[index].flags = (old & (~set)) | (flags & set); - camel_block_file_touch_block(ki->blocks, bl); - } - - CAMEL_KEY_TABLE_UNLOCK(ki, lock); - - camel_block_file_unref_block(ki->blocks, bl); -} - -camel_block_t -camel_key_table_lookup(CamelKeyTable *ki, camel_key_t keyid, char **keyp, unsigned int *flags) -{ - CamelBlock *bl; - camel_block_t blockid; - int index, len, off; - char *key; - CamelKeyBlock *kb; - - if (keyp) - *keyp = 0; - if (flags) - *flags = 0; - if (keyid == 0) - return 0; - - blockid = keyid & (~(CAMEL_BLOCK_SIZE-1)); - index = keyid & (CAMEL_BLOCK_SIZE-1); - - bl = camel_block_file_get_block(ki->blocks, blockid); - if (bl == NULL) - return 0; - - kb = (CamelKeyBlock *)&bl->data; - -#if 1 - g_assert(kb->used < 127); /* this should be more accurate */ - g_assert(index < kb->used); -#else - if (kb->used >=127 || index >= kb->used) { - g_warning("Block %x: Invalid index or content: index %d used %d\n", blockid, index, kb->used); - return 0; - } -#endif - - CAMEL_KEY_TABLE_LOCK(ki, lock); - - blockid = kb->u.keys[index].data; - if (flags) - *flags = kb->u.keys[index].flags; - - if (keyp) { - off = kb->u.keys[index].offset; - if (index == 0) - len = sizeof(kb->u.keydata) - off; - else - len = kb->u.keys[index-1].offset - off; - *keyp = key = g_malloc(len+1); - memcpy(key, kb->u.keydata + off, len); - key[len] = 0; - } - - CAMEL_KEY_TABLE_UNLOCK(ki, lock); - - camel_block_file_unref_block(ki->blocks, bl); - - return blockid; -} - -/* iterate through all keys */ -camel_key_t -camel_key_table_next(CamelKeyTable *ki, camel_key_t next, char **keyp, unsigned int *flagsp, camel_block_t *datap) -{ - CamelBlock *bl; - CamelKeyBlock *kb; - camel_block_t blockid; - int index; - - if (keyp) - *keyp = 0; - if (flagsp) - *flagsp = 0; - if (datap) - *datap = 0; - - CAMEL_KEY_TABLE_LOCK(ki, lock); - - if (next == 0) { - next = ki->root->first; - if (next == 0) { - CAMEL_KEY_TABLE_UNLOCK(ki, lock); - return 0; - } - } else - next++; - - do { - blockid = next & (~(CAMEL_BLOCK_SIZE-1)); - index = next & (CAMEL_BLOCK_SIZE-1); - - bl = camel_block_file_get_block(ki->blocks, blockid); - if (bl == NULL) { - CAMEL_KEY_TABLE_UNLOCK(ki, lock); - return 0; - } - - kb = (CamelKeyBlock *)&bl->data; - - /* see if we need to goto the next block */ - if (index >= kb->used) { - /* FIXME: check for loops */ - next = kb->next; - camel_block_file_unref_block(ki->blocks, bl); - bl = NULL; - } - } while (bl == NULL); - - /* invalid block data */ - if ((kb->u.keys[index].offset >= sizeof(kb->u.keydata) - /*|| kb->u.keys[index].offset < kb->u.keydata - (char *)&kb->u.keys[kb->used])*/ - || kb->u.keys[index].offset < sizeof(kb->u.keys[0]) * kb->used - || (index > 0 && - (kb->u.keys[index-1].offset >= sizeof(kb->u.keydata) - /*|| kb->u.keys[index-1].offset < kb->u.keydata - (char *)&kb->u.keys[kb->used]))) {*/ - || kb->u.keys[index-1].offset < sizeof(kb->u.keys[0]) * kb->used)))) { - g_warning("Block %u invalid scanning keys", bl->id); - camel_block_file_unref_block(ki->blocks, bl); - CAMEL_KEY_TABLE_UNLOCK(ki, lock); - return 0; - } - - if (datap) - *datap = kb->u.keys[index].data; - - if (flagsp) - *flagsp = kb->u.keys[index].flags; - - if (keyp) { - int len, off = kb->u.keys[index].offset; - char *key; - - if (index == 0) - len = sizeof(kb->u.keydata) - off; - else - len = kb->u.keys[index-1].offset - off; - *keyp = key = g_malloc(len+1); - memcpy(key, kb->u.keydata + off, len); - key[len] = 0; - } - - CAMEL_KEY_TABLE_UNLOCK(ki, lock); - - camel_block_file_unref_block(ki->blocks, bl); - - return next; -} - -/* ********************************************************************** */ diff --git a/camel/camel-partition-table.h b/camel/camel-partition-table.h deleted file mode 100644 index 3433da3cf1..0000000000 --- a/camel/camel-partition-table.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2001 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_PARTITION_TABLE_H -#define _CAMEL_PARTITION_TABLE_H - -#include -#include -#include - -#include "camel-block-file.h" - -/* ********************************************************************** */ - -/* CamelPartitionTable - index of key to keyid */ - -typedef guint32 camel_hash_t; /* a hashed key */ - -typedef struct _CamelPartitionKey CamelPartitionKey; -typedef struct _CamelPartitionKeyBlock CamelPartitionKeyBlock; -typedef struct _CamelPartitionMap CamelPartitionMap; -typedef struct _CamelPartitionMapBlock CamelPartitionMapBlock; - -typedef struct _CamelPartitionTable CamelPartitionTable; -typedef struct _CamelPartitionTableClass CamelPartitionTableClass; - -struct _CamelPartitionKey { - camel_hash_t hashid; - camel_key_t keyid; -}; - -struct _CamelPartitionKeyBlock { - guint32 used; - struct _CamelPartitionKey keys[(CAMEL_BLOCK_SIZE-4)/sizeof(struct _CamelPartitionKey)]; -}; - -struct _CamelPartitionMap { - camel_hash_t hashid; - camel_block_t blockid; -}; - -struct _CamelPartitionMapBlock { - camel_block_t next; - guint32 used; - struct _CamelPartitionMap partition[(CAMEL_BLOCK_SIZE-8)/sizeof(struct _CamelPartitionMap)]; -}; - -struct _CamelPartitionTable { - CamelObject parent; - - struct _CamelPartitionTablePrivate *priv; - - CamelBlockFile *blocks; - camel_block_t rootid; - - int (*is_key)(CamelPartitionTable *cpi, const char *key, camel_key_t keyid, void *data); - void *is_key_data; - - /* we keep a list of partition blocks active at all times */ - EDList partition; -}; - -struct _CamelPartitionTableClass { - CamelObjectClass parent; -}; - -CamelType camel_partition_table_get_type(void); - -CamelPartitionTable *camel_partition_table_new(struct _CamelBlockFile *bs, camel_block_t root); -int camel_partition_table_sync(CamelPartitionTable *cpi); -int camel_partition_table_add(CamelPartitionTable *cpi, const char *key, camel_key_t keyid); -camel_key_t camel_partition_table_lookup(CamelPartitionTable *cpi, const char *key); -void camel_partition_table_remove(CamelPartitionTable *cpi, const char *key); - -/* ********************************************************************** */ - -/* CamelKeyTable - index of keyid to key and flag and data mapping */ - -typedef struct _CamelKeyBlock CamelKeyBlock; -typedef struct _CamelKeyRootBlock CamelKeyRootBlock; - -typedef struct _CamelKeyTable CamelKeyTable; -typedef struct _CamelKeyTableClass CamelKeyTableClass; - -struct _CamelKeyRootBlock { - camel_block_t first; - camel_block_t last; - camel_key_t free; /* free list */ -}; - -struct _CamelKeyKey { - camel_block_t data; - unsigned int offset:10; - unsigned int flags:22; -}; - -struct _CamelKeyBlock { - camel_block_t next; - guint32 used; - union { - struct _CamelKeyKey keys[(CAMEL_BLOCK_SIZE-8)/sizeof(struct _CamelKeyKey)]; - char keydata[CAMEL_BLOCK_SIZE-8]; - } u; -}; - -#define CAMEL_KEY_TABLE_MAX_KEY (128) /* max size of any key */ - -struct _CamelKeyTable { - CamelObject parent; - - struct _CamelKeyTablePrivate *priv; - - CamelBlockFile *blocks; - - camel_block_t rootid; - - CamelKeyRootBlock *root; - CamelBlock *root_block; -}; - -struct _CamelKeyTableClass { - CamelObjectClass parent; -}; - -CamelType camel_key_table_get_type(void); - -CamelKeyTable * camel_key_table_new(CamelBlockFile *bs, camel_block_t root); -int camel_key_table_sync(CamelKeyTable *ki); -camel_key_t camel_key_table_add(CamelKeyTable *ki, const char *key, camel_block_t data, unsigned int flags); -void camel_key_table_set_data(CamelKeyTable *ki, camel_key_t keyid, camel_block_t data); -void camel_key_table_set_flags(CamelKeyTable *ki, camel_key_t keyid, unsigned int flags, unsigned int set); -camel_block_t camel_key_table_lookup(CamelKeyTable *ki, camel_key_t keyid, char **key, unsigned int *flags); -camel_key_t camel_key_table_next(CamelKeyTable *ki, camel_key_t next, char **keyp, unsigned int *flagsp, camel_block_t *datap); - -#endif /* ! _CAMEL_PARTITION_TABLE_H */ diff --git a/camel/camel-private.h b/camel/camel-private.h deleted file mode 100644 index 87aeeff4b7..0000000000 --- a/camel/camel-private.h +++ /dev/null @@ -1,168 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * camel-private.h: Private info for class implementers. - * - * Authors: Michael Zucchi - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_PRIVATE_H -#define CAMEL_PRIVATE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* need a way to configure and save this data, if this header is to - be installed. For now, dont install it */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -struct _CamelFolderPrivate { - EMutex *lock; - EMutex *change_lock; - /* must require the 'change_lock' to access this */ - int frozen; - struct _CamelFolderChangeInfo *changed_frozen; /* queues changed events */ -}; - -#define CAMEL_FOLDER_LOCK(f, l) (e_mutex_lock(((CamelFolder *)f)->priv->l)) -#define CAMEL_FOLDER_UNLOCK(f, l) (e_mutex_unlock(((CamelFolder *)f)->priv->l)) - - -struct _CamelStorePrivate { - EMutex *folder_lock; /* for locking folder operations */ -}; - -#define CAMEL_STORE_LOCK(f, l) (e_mutex_lock(((CamelStore *)f)->priv->l)) -#define CAMEL_STORE_UNLOCK(f, l) (e_mutex_unlock(((CamelStore *)f)->priv->l)) - - -struct _CamelTransportPrivate { - GMutex *send_lock; /* for locking send operations */ -}; - -#define CAMEL_TRANSPORT_LOCK(f, l) (g_mutex_lock(((CamelTransport *)f)->priv->l)) -#define CAMEL_TRANSPORT_UNLOCK(f, l) (g_mutex_unlock(((CamelTransport *)f)->priv->l)) - - -struct _CamelServicePrivate { - EMutex *connect_lock; /* for locking connection operations */ - EMutex *connect_op_lock;/* for locking the connection_op */ -}; - -#define CAMEL_SERVICE_LOCK(f, l) (e_mutex_lock(((CamelService *)f)->priv->l)) -#define CAMEL_SERVICE_UNLOCK(f, l) (e_mutex_unlock(((CamelService *)f)->priv->l)) -#define CAMEL_SERVICE_ASSERT_LOCKED(f, l) (e_mutex_assert_locked (((CamelService *)f)->priv->l)) - - -struct _CamelSessionPrivate { - GMutex *lock; /* for locking everything basically */ - GMutex *thread_lock; /* locking threads */ - - int thread_id; - GHashTable *thread_active; - EThread *thread_queue; - - GHashTable *thread_msg_op; -}; - -#define CAMEL_SESSION_LOCK(f, l) (g_mutex_lock(((CamelSession *)f)->priv->l)) -#define CAMEL_SESSION_UNLOCK(f, l) (g_mutex_unlock(((CamelSession *)f)->priv->l)) - - -/* most of this stuff really is private, but the lock can be used by subordinate classes */ -struct _CamelFolderSummaryPrivate { - GHashTable *filter_charset; /* CamelMimeFilterCharset's indexed by source charset */ - - struct _CamelMimeFilterIndex *filter_index; - struct _CamelMimeFilterBasic *filter_64; - struct _CamelMimeFilterBasic *filter_qp; - struct _CamelMimeFilterBasic *filter_uu; - struct _CamelMimeFilterSave *filter_save; - struct _CamelMimeFilterHTML *filter_html; - - struct _CamelStreamFilter *filter_stream; - - struct _CamelIndex *index; - - GMutex *summary_lock; /* for the summary hashtable/array */ - GMutex *io_lock; /* load/save lock, for access to saved_count, etc */ - GMutex *filter_lock; /* for accessing any of the filtering/indexing stuff, since we share them */ - GMutex *alloc_lock; /* for setting up and using allocators */ - GMutex *ref_lock; /* for reffing/unreffing messageinfo's ALWAYS obtain before summary_lock */ -}; - -#define CAMEL_SUMMARY_LOCK(f, l) (g_mutex_lock(((CamelFolderSummary *)f)->priv->l)) -#define CAMEL_SUMMARY_UNLOCK(f, l) (g_mutex_unlock(((CamelFolderSummary *)f)->priv->l)) - - -struct _CamelStoreSummaryPrivate { - GMutex *summary_lock; /* for the summary hashtable/array */ - GMutex *io_lock; /* load/save lock, for access to saved_count, etc */ - GMutex *alloc_lock; /* for setting up and using allocators */ - GMutex *ref_lock; /* for reffing/unreffing messageinfo's ALWAYS obtain before summary_lock */ -}; - -#define CAMEL_STORE_SUMMARY_LOCK(f, l) (g_mutex_lock(((CamelStoreSummary *)f)->priv->l)) -#define CAMEL_STORE_SUMMARY_UNLOCK(f, l) (g_mutex_unlock(((CamelStoreSummary *)f)->priv->l)) - - -struct _CamelVeeFolderPrivate { - GList *folders; /* lock using subfolder_lock before changing/accessing */ - GList *folders_changed; /* for list of folders that have changed between updates */ - int freeze_count; - - GMutex *summary_lock; /* for locking vfolder summary */ - GMutex *subfolder_lock; /* for locking the subfolder list */ - GMutex *changed_lock; /* for locking the folders-changed list */ -}; - -#define CAMEL_VEE_FOLDER_LOCK(f, l) (g_mutex_lock(((CamelVeeFolder *)f)->priv->l)) -#define CAMEL_VEE_FOLDER_UNLOCK(f, l) (g_mutex_unlock(((CamelVeeFolder *)f)->priv->l)) - - -struct _CamelDataWrapperPrivate { - pthread_mutex_t stream_lock; -}; - -#define CAMEL_DATA_WRAPPER_LOCK(dw, l) (pthread_mutex_lock(&((CamelDataWrapper *)dw)->priv->l)) -#define CAMEL_DATA_WRAPPER_UNLOCK(dw, l) (pthread_mutex_unlock(&((CamelDataWrapper *)dw)->priv->l)) - - -/* most of this stuff really is private, but the lock can be used by subordinate classes */ -struct _CamelCertDBPrivate { - GMutex *db_lock; /* for the db hashtable/array */ - GMutex *io_lock; /* load/save lock, for access to saved_count, etc */ - GMutex *alloc_lock; /* for setting up and using allocators */ - GMutex *ref_lock; /* for reffing/unreffing certs */ -}; - -#define CAMEL_CERTDB_LOCK(db, l) (g_mutex_lock (((CamelCertDB *) db)->priv->l)) -#define CAMEL_CERTDB_UNLOCK(db, l) (g_mutex_unlock (((CamelCertDB *) db)->priv->l)) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_PRIVATE_H */ diff --git a/camel/camel-process.c b/camel/camel-process.c deleted file mode 100644 index 04de281294..0000000000 --- a/camel/camel-process.c +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "camel-process.h" - - -pid_t -camel_process_fork (const char *path, char **argv, int *infd, int *outfd, int *errfd, CamelException *ex) -{ - int errnosav, fd[6], i; - pid_t pid; - - for (i = 0; i < 6; i++) - fds[i] = -1; - - for (i = 0; i < 6; i += 2) { - if (pipe (fd + i) == -1) { - errnosav = errno; - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to create pipe to '%s': %s"), - argv[0], strerror (errno)); - - for (i = 0; i < 6; i++) { - if (fd[i] == -1) - break; - close (fd[i]); - } - - errno = errnosav; - - return -1; - } - } - - if (!(pid = fork ())) { - /* child process */ - int maxfd, nullfd = -1; - - if (!outfd || !errfd) - nullfd = open ("/dev/null", O_WRONLY); - - if (dup2 (fd[0], STDIN_FILENO) == -1) - _exit (255); - - if (dup2 (outfd ? fd[3] : nullfd, STDOUT_FILENO) == -1) - _exit (255); - - if (dup2 (errfd ? fd[5] : nullfd, STDERR_FILENO) == -1) - _exit (255); - - setsid (); - - if ((maxfd = sysconf (_SC_OPEN_MAX)) > 0) { - for (i = 3; i < maxfd; i++) - fcntl (i, F_SETFD, FD_CLOEXEC); - } - - execv (path, argv); - _exit (255); - } else if (pid == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to create create child process '%s': %s"), - argv[0], strerror (errno)); - return -1; - } - - /* parent process */ - close (fd[0]); - close (fd[3]); - close (fd[5]); - - if (infd) - *infd = fd[1]; - else - close (fd[1]); - - if (outfd) - *outfd = fd[2]; - else - close (fd[2]); - - if (errfd) - *errfd = fd[4]; - else - close (fd[4]); - - return pid; -} - - -int -camel_process_wait (pid_t pid) -{ - sigset_t mask, omask; - int status; - pid_t r; - - sigemptyset (&mask); - sigaddset (&mask, SIGALRM); - sigprocmask (SIG_BLOCK, &mask, &omask); - alarm (1); - - r = waitpid (pid, &status, 0); - - alarm (0); - sigprocmask (SIG_SETMASK, &omask, NULL); - - if (r == (pid_t) -1 && errno == EINTR) { - kill (pid, SIGTERM); - sleep (1); - r = waitpid (pid, &status, WNOHANG); - if (r == (pid_t) 0) { - kill (pid, SIGKILL); - sleep (1); - r = waitpid (pid, &status, WNOHANG); - } - } - - if (r != (pid_t) -1 && WIFEXITED (status)) - return WEXITSTATUS (status); - else - return -1; -} diff --git a/camel/camel-process.h b/camel/camel-process.h deleted file mode 100644 index a87db24d5c..0000000000 --- a/camel/camel-process.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __CAMEL_PROCESS_H__ -#define __CAMEL_PROCESS_H__ - -#include - -#include - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -pid_t camel_process_fork (const char *path, char **argv, int *infd, int *outfd, int *errfd, CamelException *ex); - -int camel_process_wait (pid_t pid); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_PROCESS_H__ */ diff --git a/camel/camel-provider.c b/camel/camel-provider.c deleted file mode 100644 index 321b3077cd..0000000000 --- a/camel/camel-provider.c +++ /dev/null @@ -1,192 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-provider.c: provider framework */ - -/* - * - * Authors: - * Bertrand Guiheneuf - * Dan Winship - * Jeffrey Stedfast - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -/* FIXME: Shouldn't we add a version number to providers ? */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include - -#include "camel-provider.h" -#include "camel-exception.h" -#include "camel-string-utils.h" - - -/** - * camel_provider_init: - * - * Initialize the Camel provider system by reading in the .urls - * files in the provider directory and creating a hash table mapping - * URLs to module names. - * - * A .urls file has the same initial prefix as the shared library it - * correspond to, and consists of a series of lines containing the URL - * protocols that that library handles. - * - * Return value: a hash table mapping URLs to module names - **/ -GHashTable * -camel_provider_init (void) -{ - GHashTable *providers; - DIR *dir; - struct dirent *d; - char *p, *name, buf[80]; - - providers = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); - - dir = opendir (CAMEL_PROVIDERDIR); - if (!dir) { - g_error ("Could not open camel provider directory (%s): %s", - CAMEL_PROVIDERDIR, g_strerror (errno)); - return NULL; - } - - while ((d = readdir (dir))) { - FILE *fp; - - p = strchr (d->d_name, '.'); - if (!p || strcmp (p, ".urls") != 0) - continue; - - name = g_strdup_printf ("%s/%s", CAMEL_PROVIDERDIR, d->d_name); - fp = fopen (name, "r"); - if (!fp) { - g_warning ("Could not read provider info file %s: %s", - name, g_strerror (errno)); - g_free (name); - continue; - } - - p = strrchr (name, '.'); - strcpy (p, ".so"); - while ((fgets (buf, sizeof (buf), fp))) { - buf[sizeof (buf) - 1] = '\0'; - p = strchr (buf, '\n'); - if (p) - *p = '\0'; - - if (*buf) - g_hash_table_insert (providers, g_strdup (buf), g_strdup (name)); - } - - g_free (name); - fclose (fp); - } - - closedir (dir); - return providers; -} - -/** - * camel_provider_load: - * @session: the current session - * @path: the path to a shared library - * @ex: a CamelException - * - * Loads the provider at @path, and calls its initialization function, - * passing @session as an argument. The provider should then register - * itself with @session. - **/ -void -camel_provider_load (CamelSession *session, const char *path, CamelException *ex) -{ - GModule *module; - CamelProvider *(*camel_provider_module_init) (); - - if (!g_module_supported ()) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not load %s: Module loading " - "not supported on this system."), - path); - return; - } - - module = g_module_open (path, 0); - if (!module) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not load %s: %s"), - path, g_module_error ()); - return; - } - - if (!g_module_symbol (module, "camel_provider_module_init", - (gpointer *)&camel_provider_module_init)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not load %s: No initialization " - "code in module."), path); - g_module_close (module); - return; - } - - camel_provider_module_init (session); -} - - -/** - * camel_provider_auto_detect: - * @provider: camel provider - * @settings: currently set settings - * @auto_detected: output hash table of auto-detected values - * @ex: exception - * - * After filling in the standard Username/Hostname/Port/Path settings - * (which must be set in @settings), if the provider supports it, you - * may wish to have the provider auto-detect further settings based on - * the aformentioned settings. - * - * If the provider does not support auto-detection, @auto_detected - * will be set to %NULL. Otherwise the provider will attempt to - * auto-detect whatever it can and file them into @auto_detected. If - * for some reason it cannot auto-detect anything (not enough - * information provided in @settings?) then @auto_deetected will be - * set to %NULL and an exception may be set to explain why it failed. - * - * Returns 0 on success or -1 on fail. - **/ -int -camel_provider_auto_detect (CamelProvider *provider, CamelURL *url, - GHashTable **auto_detected, CamelException *ex) -{ - g_return_val_if_fail (provider != NULL, -1); - - if (provider->auto_detect) { - return provider->auto_detect (url, auto_detected, ex); - } else { - *auto_detected = NULL; - return 0; - } -} diff --git a/camel/camel-provider.h b/camel/camel-provider.h deleted file mode 100644 index 98c5a3ed6a..0000000000 --- a/camel/camel-provider.h +++ /dev/null @@ -1,201 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-provider.h : provider definition */ - -/* - * - * Authors: - * Bertrand Guiheneuf - * Jeffrey Stedfast - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_PROVIDER_H -#define CAMEL_PROVIDER_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include -#include -#include - -#define CAMEL_PROVIDER(obj) ((CamelProvider *)(obj)) - -typedef enum { - CAMEL_PROVIDER_STORE, - CAMEL_PROVIDER_TRANSPORT, - CAMEL_NUM_PROVIDER_TYPES -} CamelProviderType; - -extern char *camel_provider_type_name[CAMEL_NUM_PROVIDER_TYPES]; - -/* Provider flags: - * - * _IS_REMOTE the provider works with remote data - * _IS_LOCAL it can be used as a backend for local folder - * tree folders. (*Not* just the opposite of _IS_REMOTE) - * _IS_SOURCE mail arrives there, so it should be offered as an - * option in the mail config dialog. - * _IS_STORAGE mail is stored there. it will appear in the folder tree. - * _IS_EXTERNAL it appears in the folder tree but is not created by - * the mail component. - */ -#define CAMEL_PROVIDER_IS_REMOTE (1 << 0) -#define CAMEL_PROVIDER_IS_LOCAL (1 << 1) -#define CAMEL_PROVIDER_IS_EXTERNAL (1 << 2) -#define CAMEL_PROVIDER_IS_SOURCE (1 << 3) -#define CAMEL_PROVIDER_IS_STORAGE (1 << 4) -#define CAMEL_PROVIDER_SUPPORTS_SSL (1 << 5) - - -/* Flags for url_flags. "ALLOW" means the config dialog will let - * the user configure it. "NEED" implies "ALLOW" but means the user - * must configure it. Service code can assume that any url part - * for which it has set the NEED flag will be set when the service - * is created. - */ -#define CAMEL_URL_PART_USER (1 << 0) -#define CAMEL_URL_PART_AUTH (1 << 1) -#define CAMEL_URL_PART_PASSWORD (1 << 2) -#define CAMEL_URL_PART_HOST (1 << 3) -#define CAMEL_URL_PART_PORT (1 << 4) -#define CAMEL_URL_PART_PATH (1 << 5) - -#define CAMEL_URL_PART_NEED 8 - -/* Use these macros to test a provider's url_flags */ -#define CAMEL_PROVIDER_ALLOWS(prov, flags) (prov->url_flags & (flags | (flags << CAMEL_URL_PART_NEED))) -#define CAMEL_PROVIDER_NEEDS(prov, flags) (prov->url_flags & (flags << CAMEL_URL_PART_NEED)) - -/* Providers use these macros to actually define their url_flags */ -#define CAMEL_URL_ALLOW_USER (CAMEL_URL_PART_USER) -#define CAMEL_URL_ALLOW_AUTH (CAMEL_URL_PART_AUTH) -#define CAMEL_URL_ALLOW_PASSWORD (CAMEL_URL_PART_PASSWORD) -#define CAMEL_URL_ALLOW_HOST (CAMEL_URL_PART_HOST) -#define CAMEL_URL_ALLOW_PORT (CAMEL_URL_PART_PORT) -#define CAMEL_URL_ALLOW_PATH (CAMEL_URL_PART_PATH) - -#define CAMEL_URL_NEED_USER (CAMEL_URL_PART_USER << CAMEL_URL_PART_NEED) -#define CAMEL_URL_NEED_AUTH (CAMEL_URL_PART_AUTH << CAMEL_URL_PART_NEED) -#define CAMEL_URL_NEED_PASSWORD (CAMEL_URL_PART_PASSWORD << CAMEL_URL_PART_NEED) -#define CAMEL_URL_NEED_HOST (CAMEL_URL_PART_HOST << CAMEL_URL_PART_NEED) -#define CAMEL_URL_NEED_PORT (CAMEL_URL_PART_PORT << CAMEL_URL_PART_NEED) -#define CAMEL_URL_NEED_PATH (CAMEL_URL_PART_PATH << CAMEL_URL_PART_NEED) - -#define CAMEL_URL_FRAGMENT_IS_PATH (1 << 30) /* url uses fragment for folder name path, not path */ -#define CAMEL_URL_PATH_IS_ABSOLUTE (1 << 31) - - -#define CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT(prov) (prov->object_types[CAMEL_PROVIDER_STORE] && prov->object_types[CAMEL_PROVIDER_TRANSPORT]) - -/* Generic extra config stuff */ -typedef enum { - CAMEL_PROVIDER_CONF_END, - CAMEL_PROVIDER_CONF_SECTION_START, - CAMEL_PROVIDER_CONF_SECTION_END, - CAMEL_PROVIDER_CONF_CHECKBOX, - CAMEL_PROVIDER_CONF_CHECKSPIN, - CAMEL_PROVIDER_CONF_ENTRY, - CAMEL_PROVIDER_CONF_LABEL, -} CamelProviderConfType; - -typedef struct { - CamelProviderConfType type; - char *name, *depname; - char *text, *value; -} CamelProviderConfEntry; - - -/* Some defaults */ -#define CAMEL_PROVIDER_CONF_DEFAULT_USERNAME { CAMEL_PROVIDER_CONF_LABEL, "username", NULL, N_("User_name:"), NULL } -#define CAMEL_PROVIDER_CONF_DEFAULT_HOSTNAME { CAMEL_PROVIDER_CONF_LABEL, "hostname", NULL, N_("_Host:"), NULL } -#define CAMEL_PROVIDER_CONF_DEFAULT_PATH { CAMEL_PROVIDER_CONF_ENTRY, "path", NULL, N_("_Path:"), "" } - -typedef int (*CamelProviderAutoDetectFunc) (CamelURL *url, GHashTable **auto_detected, CamelException *ex); - -typedef struct { - /* Provider name used in CamelURLs. */ - char *protocol; - - /* Provider name as used by people. (May be the same as protocol) */ - char *name; - - /* Description of the provider. A novice user should be able - * to read this description, and the information provided by - * an ISP, IS department, etc, and determine whether or not - * this provider is relevant to him, and if so, which - * information goes with it. - */ - char *description; - - /* The category of message that this provider works with. - * (evolution-mail will only list a provider in the store/transport - * config dialogs if its domain is "mail".) - */ - char *domain; - - /* Flags describing the provider, flags describing its URLs */ - int flags, url_flags; - - /* Extra configuration information */ - CamelProviderConfEntry *extra_conf; - - /* auto-detection function */ - CamelProviderAutoDetectFunc auto_detect; - - /* CamelType(s) of its store and/or transport. If both are - * set, then they are assumed to be linked together and the - * transport type can only be used in an account that also - * uses the store type (eg, Exchange or NNTP). - */ - CamelType object_types[CAMEL_NUM_PROVIDER_TYPES]; - - /* GList of CamelServiceAuthTypes the provider supports */ - GList *authtypes; - - CamelObjectBag *service_cache[CAMEL_NUM_PROVIDER_TYPES]; - - GHashFunc url_hash; - GCompareFunc url_equal; - - /* gettext translation domain (NULL for providers in the - * evolution source tree). - */ - char *translation_domain; -} CamelProvider; - -GHashTable *camel_provider_init (void); -void camel_provider_load (CamelSession *session, const char *path, CamelException *ex); - -/* This is defined by each module, not by camel-provider.c. */ -void camel_provider_module_init (CamelSession *session); - - -int camel_provider_auto_detect (CamelProvider *provider, CamelURL *url, - GHashTable **auto_detected, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_PROVIDER_H */ diff --git a/camel/camel-sasl-anonymous.c b/camel/camel-sasl-anonymous.c deleted file mode 100644 index 9b97fdbc07..0000000000 --- a/camel/camel-sasl-anonymous.c +++ /dev/null @@ -1,152 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "camel-sasl-anonymous.h" -#include "camel-internet-address.h" -#include - - -CamelServiceAuthType camel_sasl_anonymous_authtype = { - N_("Anonymous"), - - N_("This option will connect to the server using an anonymous login."), - - "ANONYMOUS", - FALSE -}; - -static CamelSaslClass *parent_class = NULL; - -/* Returns the class for a CamelSaslAnonymous */ -#define CSA_CLASS(so) CAMEL_SASL_ANONYMOUS_CLASS (CAMEL_OBJECT_GET_CLASS (so)) - -static GByteArray *anon_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex); - -static void -camel_sasl_anonymous_class_init (CamelSaslAnonymousClass *camel_sasl_anonymous_class) -{ - CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_anonymous_class); - - parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ())); - - /* virtual method overload */ - camel_sasl_class->challenge = anon_challenge; -} - -static void -camel_sasl_anonymous_finalize (CamelObject *object) -{ - CamelSaslAnonymous *sasl = CAMEL_SASL_ANONYMOUS (object); - - g_free (sasl->trace_info); -} - - -CamelType -camel_sasl_anonymous_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_sasl_get_type (), - "CamelSaslAnonymous", - sizeof (CamelSaslAnonymous), - sizeof (CamelSaslAnonymousClass), - (CamelObjectClassInitFunc) camel_sasl_anonymous_class_init, - NULL, - NULL, - (CamelObjectFinalizeFunc) camel_sasl_anonymous_finalize); - } - - return type; -} - -CamelSasl * -camel_sasl_anonymous_new (CamelSaslAnonTraceType type, const char *trace_info) -{ - CamelSaslAnonymous *sasl_anon; - - if (!trace_info && type != CAMEL_SASL_ANON_TRACE_EMPTY) return NULL; - - sasl_anon = CAMEL_SASL_ANONYMOUS (camel_object_new (camel_sasl_anonymous_get_type ())); - sasl_anon->trace_info = g_strdup (trace_info); - sasl_anon->type = type; - - return CAMEL_SASL (sasl_anon); -} - -static GByteArray * -anon_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) -{ - CamelSaslAnonymous *sasl_anon = CAMEL_SASL_ANONYMOUS (sasl); - CamelInternetAddress *cia; - GByteArray *ret = NULL; - - if (token) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Authentication failed.")); - return NULL; - } - - switch (sasl_anon->type) { - case CAMEL_SASL_ANON_TRACE_EMAIL: - cia = camel_internet_address_new (); - if (camel_internet_address_add (cia, NULL, sasl_anon->trace_info) != 1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Invalid email address trace information:\n%s"), - sasl_anon->trace_info); - camel_object_unref (cia); - return NULL; - } - camel_object_unref (cia); - ret = g_byte_array_new (); - g_byte_array_append (ret, sasl_anon->trace_info, strlen (sasl_anon->trace_info)); - break; - case CAMEL_SASL_ANON_TRACE_OPAQUE: - if (strchr (sasl_anon->trace_info, '@')) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Invalid opaque trace information:\n%s"), - sasl_anon->trace_info); - return NULL; - } - ret = g_byte_array_new (); - g_byte_array_append (ret, sasl_anon->trace_info, strlen (sasl_anon->trace_info)); - break; - case CAMEL_SASL_ANON_TRACE_EMPTY: - ret = g_byte_array_new (); - break; - default: - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Invalid trace information:\n%s"), - sasl_anon->trace_info); - return NULL; - } - - sasl->authenticated = TRUE; - return ret; -} diff --git a/camel/camel-sasl-anonymous.h b/camel/camel-sasl-anonymous.h deleted file mode 100644 index 5c8bed4a4b..0000000000 --- a/camel/camel-sasl-anonymous.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef CAMEL_SASL_ANONYMOUS_H -#define CAMEL_SASL_ANONYMOUS_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include - -#define CAMEL_SASL_ANONYMOUS_TYPE (camel_sasl_anonymous_get_type ()) -#define CAMEL_SASL_ANONYMOUS(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_ANONYMOUS_TYPE, CamelSaslAnonymous)) -#define CAMEL_SASL_ANONYMOUS_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_ANONYMOUS_TYPE, CamelSaslAnonymousClass)) -#define CAMEL_IS_SASL_ANONYMOUS(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_ANONYMOUS_TYPE)) - -typedef enum { - CAMEL_SASL_ANON_TRACE_EMAIL, - CAMEL_SASL_ANON_TRACE_OPAQUE, - CAMEL_SASL_ANON_TRACE_EMPTY -} CamelSaslAnonTraceType; - -typedef struct _CamelSaslAnonymous { - CamelSasl parent_object; - - char *trace_info; - CamelSaslAnonTraceType type; -} CamelSaslAnonymous; - - -typedef struct _CamelSaslAnonymousClass { - CamelSaslClass parent_class; - -} CamelSaslAnonymousClass; - - -/* Standard Camel function */ -CamelType camel_sasl_anonymous_get_type (void); - -/* public methods */ -CamelSasl *camel_sasl_anonymous_new (CamelSaslAnonTraceType type, const char *trace_info); - -extern CamelServiceAuthType camel_sasl_anonymous_authtype; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SASL_ANONYMOUS_H */ diff --git a/camel/camel-sasl-cram-md5.c b/camel/camel-sasl-cram-md5.c deleted file mode 100644 index f544d48a22..0000000000 --- a/camel/camel-sasl-cram-md5.c +++ /dev/null @@ -1,142 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include "camel-sasl-cram-md5.h" -#include "camel-mime-utils.h" -#include "camel-service.h" -#include - -CamelServiceAuthType camel_sasl_cram_md5_authtype = { - N_("CRAM-MD5"), - - N_("This option will connect to the server using a " - "secure CRAM-MD5 password, if the server supports it."), - - "CRAM-MD5", - TRUE -}; - -static CamelSaslClass *parent_class = NULL; - -/* Returns the class for a CamelSaslCramMd5 */ -#define CSCM_CLASS(so) CAMEL_SASL_CRAM_MD5_CLASS (CAMEL_OBJECT_GET_CLASS (so)) - -static GByteArray *cram_md5_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex); - -static void -camel_sasl_cram_md5_class_init (CamelSaslCramMd5Class *camel_sasl_cram_md5_class) -{ - CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_cram_md5_class); - - parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ())); - - /* virtual method overload */ - camel_sasl_class->challenge = cram_md5_challenge; -} - -CamelType -camel_sasl_cram_md5_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_sasl_get_type (), - "CamelSaslCramMd5", - sizeof (CamelSaslCramMd5), - sizeof (CamelSaslCramMd5Class), - (CamelObjectClassInitFunc) camel_sasl_cram_md5_class_init, - NULL, - NULL, - NULL); - } - - return type; -} - -/* CRAM-MD5 algorithm: - * MD5 ((passwd XOR opad), MD5 ((passwd XOR ipad), timestamp)) - */ - -static GByteArray * -cram_md5_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) -{ - char *passwd; - guchar digest[16], md5asc[33], *s, *p; - GByteArray *ret = NULL; - guchar ipad[64]; - guchar opad[64]; - MD5Context ctx; - int i, pw_len; - - /* Need to wait for the server */ - if (!token) - return NULL; - - g_return_val_if_fail (sasl->service->url->passwd != NULL, NULL); - - memset (ipad, 0, sizeof (ipad)); - memset (opad, 0, sizeof (opad)); - - passwd = sasl->service->url->passwd; - pw_len = strlen (passwd); - if (pw_len <= 64) { - memcpy (ipad, passwd, pw_len); - memcpy (opad, passwd, pw_len); - } else { - md5_get_digest (passwd, pw_len, ipad); - memcpy (opad, ipad, 16); - } - - for (i = 0; i < 64; i++) { - ipad[i] ^= 0x36; - opad[i] ^= 0x5c; - } - - md5_init (&ctx); - md5_update (&ctx, ipad, 64); - md5_update (&ctx, token->data, token->len); - md5_final (&ctx, digest); - - md5_init (&ctx); - md5_update (&ctx, opad, 64); - md5_update (&ctx, digest, 16); - md5_final (&ctx, digest); - - /* lowercase hexify that bad-boy... */ - for (s = digest, p = md5asc; p < md5asc + 32; s++, p += 2) - sprintf (p, "%.2x", *s); - - ret = g_byte_array_new (); - g_byte_array_append (ret, sasl->service->url->user, strlen (sasl->service->url->user)); - g_byte_array_append (ret, " ", 1); - g_byte_array_append (ret, md5asc, 32); - - sasl->authenticated = TRUE; - - return ret; -} diff --git a/camel/camel-sasl-cram-md5.h b/camel/camel-sasl-cram-md5.h deleted file mode 100644 index 2404b453f6..0000000000 --- a/camel/camel-sasl-cram-md5.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef CAMEL_SASL_CRAM_MD5_H -#define CAMEL_SASL_CRAM_MD5_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include - -#define CAMEL_SASL_CRAM_MD5_TYPE (camel_sasl_cram_md5_get_type ()) -#define CAMEL_SASL_CRAM_MD5(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_CRAM_MD5_TYPE, CamelSaslCramMd5)) -#define CAMEL_SASL_CRAM_MD5_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_CRAM_MD5_TYPE, CamelSaslCramMd5Class)) -#define CAMEL_IS_SASL_CRAM_MD5(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_CRAM_MD5_TYPE)) - -typedef struct _CamelSaslCramMd5 { - CamelSasl parent_object; - -} CamelSaslCramMd5; - - -typedef struct _CamelSaslCramMd5Class { - CamelSaslClass parent_class; - -} CamelSaslCramMd5Class; - - -/* Standard Camel function */ -CamelType camel_sasl_cram_md5_get_type (void); - -extern CamelServiceAuthType camel_sasl_cram_md5_authtype; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SASL_CRAM_MD5_H */ diff --git a/camel/camel-sasl-digest-md5.c b/camel/camel-sasl-digest-md5.c deleted file mode 100644 index e421bd5294..0000000000 --- a/camel/camel-sasl-digest-md5.c +++ /dev/null @@ -1,898 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include - -#include - -#include "camel-charset-map.h" -#include "camel-mime-utils.h" -#include "camel-sasl-digest-md5.h" - -#define d(x) - -#define PARANOID(x) x - -/* Implements rfc2831 */ - -CamelServiceAuthType camel_sasl_digest_md5_authtype = { - N_("DIGEST-MD5"), - - N_("This option will connect to the server using a " - "secure DIGEST-MD5 password, if the server supports it."), - - "DIGEST-MD5", - TRUE -}; - -static CamelSaslClass *parent_class = NULL; - -/* Returns the class for a CamelSaslDigestMd5 */ -#define CSCM_CLASS(so) CAMEL_SASL_DIGEST_MD5_CLASS (CAMEL_OBJECT_GET_CLASS (so)) - -static GByteArray *digest_md5_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex); - -enum { - STATE_AUTH, - STATE_FINAL -}; - -typedef struct { - char *name; - guint type; -} DataType; - -enum { - DIGEST_REALM, - DIGEST_NONCE, - DIGEST_QOP, - DIGEST_STALE, - DIGEST_MAXBUF, - DIGEST_CHARSET, - DIGEST_ALGORITHM, - DIGEST_CIPHER, - DIGEST_UNKNOWN -}; - -static DataType digest_args[] = { - { "realm", DIGEST_REALM }, - { "nonce", DIGEST_NONCE }, - { "qop", DIGEST_QOP }, - { "stale", DIGEST_STALE }, - { "maxbuf", DIGEST_MAXBUF }, - { "charset", DIGEST_CHARSET }, - { "algorithm", DIGEST_ALGORITHM }, - { "cipher", DIGEST_CIPHER }, - { NULL, DIGEST_UNKNOWN } -}; - -#define QOP_AUTH (1<<0) -#define QOP_AUTH_INT (1<<1) -#define QOP_AUTH_CONF (1<<2) -#define QOP_INVALID (1<<3) - -static DataType qop_types[] = { - { "auth", QOP_AUTH }, - { "auth-int", QOP_AUTH_INT }, - { "auth-conf", QOP_AUTH_CONF }, - { NULL, QOP_INVALID } -}; - -#define CIPHER_DES (1<<0) -#define CIPHER_3DES (1<<1) -#define CIPHER_RC4 (1<<2) -#define CIPHER_RC4_40 (1<<3) -#define CIPHER_RC4_56 (1<<4) -#define CIPHER_INVALID (1<<5) - -static DataType cipher_types[] = { - { "des", CIPHER_DES }, - { "3des", CIPHER_3DES }, - { "rc4", CIPHER_RC4 }, - { "rc4-40", CIPHER_RC4_40 }, - { "rc4-56", CIPHER_RC4_56 }, - { NULL, CIPHER_INVALID } -}; - -struct _param { - char *name; - char *value; -}; - -struct _DigestChallenge { - GPtrArray *realms; - char *nonce; - guint qop; - gboolean stale; - gint32 maxbuf; - char *charset; - char *algorithm; - guint cipher; - GList *params; -}; - -struct _DigestURI { - char *type; - char *host; - char *name; -}; - -struct _DigestResponse { - char *username; - char *realm; - char *nonce; - char *cnonce; - char nc[9]; - guint qop; - struct _DigestURI *uri; - char resp[33]; - guint32 maxbuf; - char *charset; - guint cipher; - char *authzid; - char *param; -}; - -struct _CamelSaslDigestMd5Private { - struct _DigestChallenge *challenge; - struct _DigestResponse *response; - int state; -}; - -static void -camel_sasl_digest_md5_class_init (CamelSaslDigestMd5Class *camel_sasl_digest_md5_class) -{ - CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_digest_md5_class); - - parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ())); - - /* virtual method overload */ - camel_sasl_class->challenge = digest_md5_challenge; -} - -static void -camel_sasl_digest_md5_init (gpointer object, gpointer klass) -{ - CamelSaslDigestMd5 *sasl_digest = CAMEL_SASL_DIGEST_MD5 (object); - - sasl_digest->priv = g_new0 (struct _CamelSaslDigestMd5Private, 1); -} - -static void -camel_sasl_digest_md5_finalize (CamelObject *object) -{ - CamelSaslDigestMd5 *sasl = CAMEL_SASL_DIGEST_MD5 (object); - struct _DigestChallenge *c = sasl->priv->challenge; - struct _DigestResponse *r = sasl->priv->response; - GList *p; - int i; - - for (i = 0; i < c->realms->len; i++) - g_free (c->realms->pdata[i]); - g_ptr_array_free (c->realms, TRUE); - g_free (c->nonce); - g_free (c->charset); - g_free (c->algorithm); - for (p = c->params; p; p = p->next) { - struct _param *param = p->data; - - g_free (param->name); - g_free (param->value); - g_free (param); - } - g_list_free (c->params); - g_free (c); - - g_free (r->username); - g_free (r->realm); - g_free (r->nonce); - g_free (r->cnonce); - if (r->uri) { - g_free (r->uri->type); - g_free (r->uri->host); - g_free (r->uri->name); - } - g_free (r->charset); - g_free (r->authzid); - g_free (r->param); - g_free (r); - - g_free (sasl->priv); -} - - -CamelType -camel_sasl_digest_md5_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_sasl_get_type (), - "CamelSaslDigestMd5", - sizeof (CamelSaslDigestMd5), - sizeof (CamelSaslDigestMd5Class), - (CamelObjectClassInitFunc) camel_sasl_digest_md5_class_init, - NULL, - (CamelObjectInitFunc) camel_sasl_digest_md5_init, - (CamelObjectFinalizeFunc) camel_sasl_digest_md5_finalize); - } - - return type; -} - -static void -decode_lwsp (const char **in) -{ - const char *inptr = *in; - - while (isspace (*inptr)) - inptr++; - - *in = inptr; -} - -static char * -decode_quoted_string (const char **in) -{ - const char *inptr = *in; - char *out = NULL, *outptr; - int outlen; - int c; - - decode_lwsp (&inptr); - if (*inptr == '"') { - const char *intmp; - int skip = 0; - - /* first, calc length */ - inptr++; - intmp = inptr; - while ((c = *intmp++) && c != '"') { - if (c == '\\' && *intmp) { - intmp++; - skip++; - } - } - - outlen = intmp - inptr - skip; - out = outptr = g_malloc (outlen + 1); - - while ((c = *inptr++) && c != '"') { - if (c == '\\' && *inptr) { - c = *inptr++; - } - *outptr++ = c; - } - *outptr = '\0'; - } - - *in = inptr; - - return out; -} - -static char * -decode_token (const char **in) -{ - const char *inptr = *in; - const char *start; - - decode_lwsp (&inptr); - start = inptr; - - while (*inptr && *inptr != '=' && *inptr != ',') - inptr++; - - if (inptr > start) { - *in = inptr; - return g_strndup (start, inptr - start); - } else { - return NULL; - } -} - -static char * -decode_value (const char **in) -{ - const char *inptr = *in; - - decode_lwsp (&inptr); - if (*inptr == '"') { - d(printf ("decoding quoted string token\n")); - return decode_quoted_string (in); - } else { - d(printf ("decoding string token\n")); - return decode_token (in); - } -} - -static GList * -parse_param_list (const char *tokens) -{ - GList *params = NULL; - struct _param *param; - const char *ptr; - - for (ptr = tokens; ptr && *ptr; ) { - param = g_new0 (struct _param, 1); - param->name = decode_token (&ptr); - if (*ptr == '=') { - ptr++; - param->value = decode_value (&ptr); - } - - params = g_list_prepend (params, param); - - if (*ptr == ',') - ptr++; - } - - return params; -} - -static guint -decode_data_type (DataType *dtype, const char *name) -{ - int i; - - for (i = 0; dtype[i].name; i++) { - if (!strcasecmp (dtype[i].name, name)) - break; - } - - return dtype[i].type; -} - -#define get_digest_arg(name) decode_data_type (digest_args, name) -#define decode_qop(name) decode_data_type (qop_types, name) -#define decode_cipher(name) decode_data_type (cipher_types, name) - -static const char * -type_to_string (DataType *dtype, guint type) -{ - int i; - - for (i = 0; dtype[i].name; i++) { - if (dtype[i].type == type) - break; - } - - return dtype[i].name; -} - -#define qop_to_string(type) type_to_string (qop_types, type) -#define cipher_to_string(type) type_to_string (cipher_types, type) - -static void -digest_abort (gboolean *have_type, gboolean *abort) -{ - if (*have_type) - *abort = TRUE; - *have_type = TRUE; -} - -static struct _DigestChallenge * -parse_server_challenge (const char *tokens, gboolean *abort) -{ - struct _DigestChallenge *challenge = NULL; - GList *params, *p; - const char *ptr; -#ifdef PARANOID - gboolean got_algorithm = FALSE; - gboolean got_stale = FALSE; - gboolean got_maxbuf = FALSE; - gboolean got_charset = FALSE; -#endif /* PARANOID */ - - params = parse_param_list (tokens); - if (!params) { - *abort = TRUE; - return NULL; - } - - *abort = FALSE; - - challenge = g_new0 (struct _DigestChallenge, 1); - challenge->realms = g_ptr_array_new (); - challenge->maxbuf = 65536; - - for (p = params; p; p = p->next) { - struct _param *param = p->data; - int type; - - type = get_digest_arg (param->name); - switch (type) { - case DIGEST_REALM: - for (ptr = param->value; ptr && *ptr; ) { - char *token; - - token = decode_token (&ptr); - if (token) - g_ptr_array_add (challenge->realms, token); - - if (*ptr == ',') - ptr++; - } - g_free (param->value); - g_free (param->name); - g_free (param); - break; - case DIGEST_NONCE: - g_free (challenge->nonce); - challenge->nonce = param->value; - g_free (param->name); - g_free (param); - break; - case DIGEST_QOP: - for (ptr = param->value; ptr && *ptr; ) { - char *token; - - token = decode_token (&ptr); - if (token) - challenge->qop |= decode_qop (token); - - if (*ptr == ',') - ptr++; - } - - if (challenge->qop & QOP_INVALID) - challenge->qop = QOP_INVALID; - g_free (param->value); - g_free (param->name); - g_free (param); - break; - case DIGEST_STALE: - PARANOID (digest_abort (&got_stale, abort)); - if (!strcasecmp (param->value, "true")) - challenge->stale = TRUE; - else - challenge->stale = FALSE; - g_free (param->value); - g_free (param->name); - g_free (param); - break; - case DIGEST_MAXBUF: - PARANOID (digest_abort (&got_maxbuf, abort)); - challenge->maxbuf = atoi (param->value); - g_free (param->value); - g_free (param->name); - g_free (param); - break; - case DIGEST_CHARSET: - PARANOID (digest_abort (&got_charset, abort)); - g_free (challenge->charset); - if (param->value && *param->value) - challenge->charset = param->value; - else - challenge->charset = NULL; - g_free (param->name); - g_free (param); - break; - case DIGEST_ALGORITHM: - PARANOID (digest_abort (&got_algorithm, abort)); - g_free (challenge->algorithm); - challenge->algorithm = param->value; - g_free (param->name); - g_free (param); - break; - case DIGEST_CIPHER: - for (ptr = param->value; ptr && *ptr; ) { - char *token; - - token = decode_token (&ptr); - if (token) - challenge->cipher |= decode_cipher (token); - - if (*ptr == ',') - ptr++; - } - if (challenge->cipher & CIPHER_INVALID) - challenge->cipher = CIPHER_INVALID; - g_free (param->value); - g_free (param->name); - g_free (param); - break; - default: - challenge->params = g_list_prepend (challenge->params, param); - break; - } - } - - g_list_free (params); - - return challenge; -} - -static void -digest_hex (guchar *digest, guchar hex[33]) -{ - guchar *s, *p; - - /* lowercase hexify that bad-boy... */ - for (s = digest, p = hex; p < hex + 32; s++, p += 2) - sprintf (p, "%.2x", *s); -} - -static char * -digest_uri_to_string (struct _DigestURI *uri) -{ - if (uri->name) - return g_strdup_printf ("%s/%s/%s", uri->type, uri->host, uri->name); - else - return g_strdup_printf ("%s/%s", uri->type, uri->host); -} - -static void -compute_response (struct _DigestResponse *resp, const char *passwd, gboolean client, guchar out[33]) -{ - guchar hex_a1[33], hex_a2[33]; - guchar digest[16]; - MD5Context ctx; - char *buf; - - /* compute A1 */ - md5_init (&ctx); - md5_update (&ctx, resp->username, strlen (resp->username)); - md5_update (&ctx, ":", 1); - md5_update (&ctx, resp->realm, strlen (resp->realm)); - md5_update (&ctx, ":", 1); - md5_update (&ctx, passwd, strlen (passwd)); - md5_final (&ctx, digest); - - md5_init (&ctx); - md5_update (&ctx, digest, 16); - md5_update (&ctx, ":", 1); - md5_update (&ctx, resp->nonce, strlen (resp->nonce)); - md5_update (&ctx, ":", 1); - md5_update (&ctx, resp->cnonce, strlen (resp->cnonce)); - if (resp->authzid) { - md5_update (&ctx, ":", 1); - md5_update (&ctx, resp->authzid, strlen (resp->authzid)); - } - - /* hexify A1 */ - md5_final (&ctx, digest); - digest_hex (digest, hex_a1); - - /* compute A2 */ - md5_init (&ctx); - if (client) { - /* we are calculating the client response */ - md5_update (&ctx, "AUTHENTICATE:", strlen ("AUTHENTICATE:")); - } else { - /* we are calculating the server rspauth */ - md5_update (&ctx, ":", 1); - } - - buf = digest_uri_to_string (resp->uri); - md5_update (&ctx, buf, strlen (buf)); - g_free (buf); - - if (resp->qop == QOP_AUTH_INT || resp->qop == QOP_AUTH_CONF) - md5_update (&ctx, ":00000000000000000000000000000000", 33); - - /* now hexify A2 */ - md5_final (&ctx, digest); - digest_hex (digest, hex_a2); - - /* compute KD */ - md5_init (&ctx); - md5_update (&ctx, hex_a1, 32); - md5_update (&ctx, ":", 1); - md5_update (&ctx, resp->nonce, strlen (resp->nonce)); - md5_update (&ctx, ":", 1); - md5_update (&ctx, resp->nc, 8); - md5_update (&ctx, ":", 1); - md5_update (&ctx, resp->cnonce, strlen (resp->cnonce)); - md5_update (&ctx, ":", 1); - md5_update (&ctx, qop_to_string (resp->qop), strlen (qop_to_string (resp->qop))); - md5_update (&ctx, ":", 1); - md5_update (&ctx, hex_a2, 32); - md5_final (&ctx, digest); - - digest_hex (digest, out); -} - -static struct _DigestResponse * -generate_response (struct _DigestChallenge *challenge, struct hostent *host, - const char *protocol, const char *user, const char *passwd) -{ - struct _DigestResponse *resp; - struct _DigestURI *uri; - char *bgen, digest[16]; - - resp = g_new0 (struct _DigestResponse, 1); - resp->username = g_strdup (user); - /* FIXME: we should use the preferred realm */ - if (challenge->realms && challenge->realms->len > 0) - resp->realm = g_strdup (challenge->realms->pdata[0]); - else - resp->realm = g_strdup (""); - - resp->nonce = g_strdup (challenge->nonce); - - /* generate the cnonce */ - bgen = g_strdup_printf ("%p:%lu:%lu", resp, - (unsigned long) getpid (), - (unsigned long) time (0)); - md5_get_digest (bgen, strlen (bgen), digest); - g_free (bgen); - /* take our recommended 64 bits of entropy */ - resp->cnonce = camel_base64_encode_simple (digest, 8); - - /* we don't support re-auth so the nonce count is always 1 */ - strcpy (resp->nc, "00000001"); - - /* choose the QOP */ - /* FIXME: choose - probably choose "auth" ??? */ - resp->qop = QOP_AUTH; - - /* create the URI */ - uri = g_new0 (struct _DigestURI, 1); - uri->type = g_strdup (protocol); - uri->host = g_strdup (host->h_name); - uri->name = NULL; - resp->uri = uri; - - /* charsets... yay */ - if (challenge->charset) { - /* I believe that this is only ever allowed to be - * UTF-8. We strdup the charset specified by the - * challenge anyway, just in case it's not UTF-8. - */ - resp->charset = g_strdup (challenge->charset); - } - - resp->cipher = CIPHER_INVALID; - if (resp->qop == QOP_AUTH_CONF) { - /* FIXME: choose a cipher? */ - resp->cipher = CIPHER_INVALID; - } - - /* we don't really care about this... */ - resp->authzid = NULL; - - compute_response (resp, passwd, TRUE, resp->resp); - - return resp; -} - -static GByteArray * -digest_response (struct _DigestResponse *resp) -{ - GByteArray *buffer; - const char *str; - char *buf; - - buffer = g_byte_array_new (); - g_byte_array_append (buffer, "username=\"", 10); - if (resp->charset) { - /* Encode the username using the requested charset */ - char *username, *outbuf; - const char *charset; - size_t len, outlen; - const char *inbuf; - iconv_t cd; - - charset = e_iconv_locale_charset (); - if (!charset) - charset = "iso-8859-1"; - - cd = e_iconv_open (resp->charset, charset); - - len = strlen (resp->username); - outlen = 2 * len; /* plenty of space */ - - outbuf = username = g_malloc0 (outlen + 1); - inbuf = resp->username; - if (cd == (iconv_t) -1 || e_iconv (cd, &inbuf, &len, &outbuf, &outlen) == (size_t) -1) { - /* We can't convert to UTF-8 - pretend we never got a charset param? */ - g_free (resp->charset); - resp->charset = NULL; - - /* Set the username to the non-UTF-8 version */ - g_free (username); - username = g_strdup (resp->username); - } - - if (cd != (iconv_t) -1) - e_iconv_close (cd); - - g_byte_array_append (buffer, username, strlen (username)); - g_free (username); - } else { - g_byte_array_append (buffer, resp->username, strlen (resp->username)); - } - - g_byte_array_append (buffer, "\",realm=\"", 9); - g_byte_array_append (buffer, resp->realm, strlen (resp->realm)); - - g_byte_array_append (buffer, "\",nonce=\"", 9); - g_byte_array_append (buffer, resp->nonce, strlen (resp->nonce)); - - g_byte_array_append (buffer, "\",cnonce=\"", 10); - g_byte_array_append (buffer, resp->cnonce, strlen (resp->cnonce)); - - g_byte_array_append (buffer, "\",nc=", 5); - g_byte_array_append (buffer, resp->nc, 8); - - g_byte_array_append (buffer, ",qop=", 5); - str = qop_to_string (resp->qop); - g_byte_array_append (buffer, str, strlen (str)); - - g_byte_array_append (buffer, ",digest-uri=\"", 13); - buf = digest_uri_to_string (resp->uri); - g_byte_array_append (buffer, buf, strlen (buf)); - g_free (buf); - - g_byte_array_append (buffer, "\",response=", 11); - g_byte_array_append (buffer, resp->resp, 32); - - if (resp->maxbuf > 0) { - g_byte_array_append (buffer, ",maxbuf=", 8); - buf = g_strdup_printf ("%d", resp->maxbuf); - g_byte_array_append (buffer, buf, strlen (buf)); - g_free (buf); - } - - if (resp->charset) { - g_byte_array_append (buffer, ",charset=", 9); - g_byte_array_append (buffer, resp->charset, strlen (resp->charset)); - } - - if (resp->cipher != CIPHER_INVALID) { - str = cipher_to_string (resp->cipher); - if (str) { - g_byte_array_append (buffer, ",cipher=\"", 9); - g_byte_array_append (buffer, str, strlen (str)); - g_byte_array_append (buffer, "\"", 1); - } - } - - if (resp->authzid) { - g_byte_array_append (buffer, ",authzid=\"", 10); - g_byte_array_append (buffer, resp->authzid, strlen (resp->authzid)); - g_byte_array_append (buffer, "\"", 1); - } - - return buffer; -} - -static GByteArray * -digest_md5_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) -{ - CamelSaslDigestMd5 *sasl_digest = CAMEL_SASL_DIGEST_MD5 (sasl); - struct _CamelSaslDigestMd5Private *priv = sasl_digest->priv; - struct _param *rspauth; - GByteArray *ret = NULL; - gboolean abort = FALSE; - struct hostent *h; - const char *ptr; - guchar out[33]; - char *tokens; - - /* Need to wait for the server */ - if (!token) - return NULL; - - g_return_val_if_fail (sasl->service->url->passwd != NULL, NULL); - - switch (priv->state) { - case STATE_AUTH: - if (token->len > 2048) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Server challenge too long (>2048 octets)\n")); - return NULL; - } - - tokens = g_strndup (token->data, token->len); - priv->challenge = parse_server_challenge (tokens, &abort); - g_free (tokens); - if (!priv->challenge || abort) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Server challenge invalid\n")); - return NULL; - } - - if (priv->challenge->qop == QOP_INVALID) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Server challenge contained invalid " - "\"Quality of Protection\" token\n")); - return NULL; - } - - h = camel_service_gethost (sasl->service, ex); - priv->response = generate_response (priv->challenge, h, sasl->service_name, - sasl->service->url->user, - sasl->service->url->passwd); - camel_free_host(h); - ret = digest_response (priv->response); - - break; - case STATE_FINAL: - if (token->len) - tokens = g_strndup (token->data, token->len); - else - tokens = NULL; - - if (!tokens || !*tokens) { - g_free (tokens); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Server response did not contain authorization data\n")); - return NULL; - } - - rspauth = g_new0 (struct _param, 1); - - ptr = tokens; - rspauth->name = decode_token (&ptr); - if (*ptr == '=') { - ptr++; - rspauth->value = decode_value (&ptr); - } - g_free (tokens); - - if (!rspauth->value) { - g_free (rspauth->name); - g_free (rspauth); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Server response contained incomplete authorization data\n")); - return NULL; - } - - compute_response (priv->response, sasl->service->url->passwd, FALSE, out); - if (memcmp (out, rspauth->value, 32) != 0) { - g_free (rspauth->name); - g_free (rspauth->value); - g_free (rspauth); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Server response does not match\n")); - sasl->authenticated = TRUE; - - return NULL; - } - - g_free (rspauth->name); - g_free (rspauth->value); - g_free (rspauth); - - ret = g_byte_array_new (); - - sasl->authenticated = TRUE; - default: - break; - } - - priv->state++; - - return ret; -} diff --git a/camel/camel-sasl-digest-md5.h b/camel/camel-sasl-digest-md5.h deleted file mode 100644 index b71abaa1df..0000000000 --- a/camel/camel-sasl-digest-md5.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef CAMEL_SASL_DIGEST_MD5_H -#define CAMEL_SASL_DIGEST_MD5_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include -#include - -#define CAMEL_SASL_DIGEST_MD5_TYPE (camel_sasl_digest_md5_get_type ()) -#define CAMEL_SASL_DIGEST_MD5(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_DIGEST_MD5_TYPE, CamelSaslDigestMd5)) -#define CAMEL_SASL_DIGEST_MD5_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_DIGEST_MD5_TYPE, CamelSaslDigestMd5Class)) -#define CAMEL_IS_SASL_DIGEST_MD5(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_DIGEST_MD5_TYPE)) - -typedef struct _CamelSaslDigestMd5 { - CamelSasl parent_object; - struct _CamelSaslDigestMd5Private *priv; - -} CamelSaslDigestMd5; - - -typedef struct _CamelSaslDigestMd5Class { - CamelSaslClass parent_class; - -} CamelSaslDigestMd5Class; - - -/* Standard Camel function */ -CamelType camel_sasl_digest_md5_get_type (void); - -extern CamelServiceAuthType camel_sasl_digest_md5_authtype; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SASL_DIGEST_MD5_H */ diff --git a/camel/camel-sasl-gssapi.c b/camel/camel-sasl-gssapi.c deleted file mode 100644 index 4f15c43821..0000000000 --- a/camel/camel-sasl-gssapi.c +++ /dev/null @@ -1,340 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_KRB5 - -#include -#include -#ifdef HAVE_MIT_KRB5 -#include -#include -#else /* HAVE_HEIMDAL_KRB5 */ -#include -#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE -#endif -#include - -#ifndef GSS_C_OID_KRBV5_DES -#define GSS_C_OID_KRBV5_DES GSS_C_NO_OID -#endif - -#include "camel-sasl-gssapi.h" - -CamelServiceAuthType camel_sasl_gssapi_authtype = { - N_("GSSAPI"), - - N_("This option will connect to the server using " - "Kerberos 5 authentication."), - - "GSSAPI", - FALSE -}; - -enum { - GSSAPI_STATE_INIT, - GSSAPI_STATE_CONTINUE_NEEDED, - GSSAPI_STATE_COMPLETE, - GSSAPI_STATE_AUTHENTICATED -}; - -#define GSSAPI_SECURITY_LAYER_NONE (1 << 0) -#define GSSAPI_SECURITY_LAYER_INTEGRITY (1 << 1) -#define GSSAPI_SECURITY_LAYER_PRIVACY (1 << 2) - -#define DESIRED_SECURITY_LAYER GSSAPI_SECURITY_LAYER_NONE - -struct _CamelSaslGssapiPrivate { - int state; - gss_ctx_id_t ctx; - gss_name_t target; -}; - - -static GByteArray *gssapi_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex); - - -static CamelSaslClass *parent_class = NULL; - - -static void -camel_sasl_gssapi_class_init (CamelSaslGssapiClass *klass) -{ - CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (klass); - - parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ())); - - /* virtual method overload */ - camel_sasl_class->challenge = gssapi_challenge; -} - -static void -camel_sasl_gssapi_init (gpointer object, gpointer klass) -{ - CamelSaslGssapi *gssapi = CAMEL_SASL_GSSAPI (object); - - gssapi->priv = g_new (struct _CamelSaslGssapiPrivate, 1); - gssapi->priv->state = GSSAPI_STATE_INIT; - gssapi->priv->ctx = GSS_C_NO_CONTEXT; - gssapi->priv->target = GSS_C_NO_NAME; -} - -static void -camel_sasl_gssapi_finalize (CamelObject *object) -{ - CamelSaslGssapi *gssapi = CAMEL_SASL_GSSAPI (object); - guint32 status; - - if (gssapi->priv->ctx != GSS_C_NO_CONTEXT) - gss_delete_sec_context (&status, &gssapi->priv->ctx, GSS_C_NO_BUFFER); - - if (gssapi->priv->target != GSS_C_NO_NAME) - gss_release_name (&status, &gssapi->priv->target); - - g_free (gssapi->priv); -} - - -CamelType -camel_sasl_gssapi_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register ( - camel_sasl_get_type (), - "CamelSaslGssapi", - sizeof (CamelSaslGssapi), - sizeof (CamelSaslGssapiClass), - (CamelObjectClassInitFunc) camel_sasl_gssapi_class_init, - NULL, - (CamelObjectInitFunc) camel_sasl_gssapi_init, - (CamelObjectFinalizeFunc) camel_sasl_gssapi_finalize); - } - - return type; -} - -static void -gssapi_set_exception (OM_uint32 major, OM_uint32 minor, CamelException *ex) -{ - const char *str; - - switch (major) { - case GSS_S_BAD_MECH: - str = _("The specified mechanism is not supported by the " - "provided credential, or is unrecognized by the " - "implementation."); - break; - case GSS_S_BAD_NAME: - str = _("The provided target_name parameter was ill-formed."); - break; - case GSS_S_BAD_NAMETYPE: - str = _("The provided target_name parameter contained an " - "invalid or unsupported type of name."); - break; - case GSS_S_BAD_BINDINGS: - str = _("The input_token contains different channel " - "bindings to those specified via the " - "input_chan_bindings parameter."); - break; - case GSS_S_BAD_SIG: - str = _("The input_token contains an invalid signature, or a " - "signature that could not be verified."); - break; - case GSS_S_NO_CRED: - str = _("The supplied credentials were not valid for context " - "initiation, or the credential handle did not " - "reference any credentials."); - break; - case GSS_S_NO_CONTEXT: - str = _("The supplied context handle did not refer to a valid context."); - break; - case GSS_S_DEFECTIVE_TOKEN: - str = _("The consistency checks performed on the input_token failed."); - break; - case GSS_S_DEFECTIVE_CREDENTIAL: - str = _("The consistency checks performed on the credential failed."); - break; - case GSS_S_CREDENTIALS_EXPIRED: - str = _("The referenced credentials have expired."); - break; - case GSS_S_FAILURE: - str = error_message (minor); - break; - default: - str = _("Bad authentication response from server."); - } - - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, str); -} - -static GByteArray * -gssapi_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) -{ - struct _CamelSaslGssapiPrivate *priv = CAMEL_SASL_GSSAPI (sasl)->priv; - OM_uint32 major, minor, flags, time; - gss_buffer_desc inbuf, outbuf; - GByteArray *challenge = NULL; - gss_buffer_t input_token; - struct hostent *h; - int conf_state; - gss_qop_t qop; - gss_OID mech; - char *str; - - switch (priv->state) { - case GSSAPI_STATE_INIT: - if (!(h = camel_service_gethost (sasl->service, ex))) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to resolve host `%s': %s"), - sasl->service->url->host, g_strerror (errno)); - return NULL; - } - - str = g_strdup_printf ("%s@%s", sasl->service_name, h->h_name); - camel_free_host (h); - - inbuf.value = str; - inbuf.length = strlen (str); - major = gss_import_name (&minor, &inbuf, gss_nt_service_name, &priv->target); - g_free (str); - - if (major != GSS_S_COMPLETE) { - gssapi_set_exception (major, minor, ex); - return NULL; - } - - input_token = GSS_C_NO_BUFFER; - - goto challenge; - break; - case GSSAPI_STATE_CONTINUE_NEEDED: - if (token == NULL) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Bad authentication response from server.")); - return NULL; - } - - inbuf.value = token->data; - inbuf.length = token->len; - input_token = &inbuf; - - challenge: - major = gss_init_sec_context (&minor, GSS_C_NO_CREDENTIAL, &priv->ctx, priv->target, - GSS_C_OID_KRBV5_DES, GSS_C_MUTUAL_FLAG | - GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG, - 0, GSS_C_NO_CHANNEL_BINDINGS, - input_token, &mech, &outbuf, &flags, &time); - - switch (major) { - case GSS_S_COMPLETE: - priv->state = GSSAPI_STATE_COMPLETE; - break; - case GSS_S_CONTINUE_NEEDED: - priv->state = GSSAPI_STATE_CONTINUE_NEEDED; - break; - default: - gssapi_set_exception (major, minor, ex); - return NULL; - } - - challenge = g_byte_array_new (); - g_byte_array_append (challenge, outbuf.value, outbuf.length); -#ifndef HAVE_HEIMDAL_KRB5 - gss_release_buffer (&minor, &outbuf); -#endif - break; - case GSSAPI_STATE_COMPLETE: - if (token == NULL) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Bad authentication response from server.")); - return NULL; - } - - inbuf.value = token->data; - inbuf.length = token->len; - - major = gss_unwrap (&minor, priv->ctx, &inbuf, &outbuf, &conf_state, &qop); - if (major != GSS_S_COMPLETE) { - gssapi_set_exception (major, minor, ex); - return NULL; - } - - if (outbuf.length < 4) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Bad authentication response from server.")); -#ifndef HAVE_HEIMDAL_KRB5 - gss_release_buffer (&minor, &outbuf); -#endif - return NULL; - } - - /* check that our desired security layer is supported */ - if ((((unsigned char *) outbuf.value)[0] & DESIRED_SECURITY_LAYER) != DESIRED_SECURITY_LAYER) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Unsupported security layer.")); - gss_release_buffer (&minor, &outbuf); - return NULL; - } - - inbuf.length = 4 + strlen (sasl->service->url->user); - inbuf.value = str = g_malloc (inbuf.length); - memcpy (inbuf.value, outbuf.value, 4); - str[0] = DESIRED_SECURITY_LAYER; - memcpy (str + 4, sasl->service->url->user, inbuf.length - 4); - -#ifndef HAVE_HEIMDAL_KRB5 - gss_release_buffer (&minor, &outbuf); -#endif - - major = gss_wrap (&minor, priv->ctx, FALSE, qop, &inbuf, &conf_state, &outbuf); - if (major != GSS_S_COMPLETE) { - gssapi_set_exception (major, minor, ex); - g_free (str); - return NULL; - } - - g_free (str); - challenge = g_byte_array_new (); - g_byte_array_append (challenge, outbuf.value, outbuf.length); - -#ifndef HAVE_HEIMDAL_KRB5 - gss_release_buffer (&minor, &outbuf); -#endif - - priv->state = GSSAPI_STATE_AUTHENTICATED; - - sasl->authenticated = TRUE; - break; - default: - return NULL; - } - - return challenge; -} - -#endif /* HAVE_KRB5 */ diff --git a/camel/camel-sasl-gssapi.h b/camel/camel-sasl-gssapi.h deleted file mode 100644 index b4a3fbc1a5..0000000000 --- a/camel/camel-sasl-gssapi.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __CAMEL_SASL_GSSAPI_H__ -#define __CAMEL_SASL_GSSAPI_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include - -#define CAMEL_SASL_GSSAPI_TYPE (camel_sasl_gssapi_get_type ()) -#define CAMEL_SASL_GSSAPI(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_GSSAPI_TYPE, CamelSaslGssapi)) -#define CAMEL_SASL_GSSAPI_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_GSSAPI_TYPE, CamelSaslGssapiClass)) -#define CAMEL_IS_SASL_GSSAPI(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_GSSAPI_TYPE)) - -typedef struct _CamelSaslGssapi CamelSaslGssapi; -typedef struct _CamelSaslGssapiClass CamelSaslGssapiClass; - -struct _CamelSaslGssapi { - CamelSasl parent_object; - - struct _CamelSaslGssapiPrivate *priv; - -}; - -struct _CamelSaslGssapiClass { - CamelSaslClass parent_class; - -}; - -/* Standard Camel function */ -CamelType camel_sasl_gssapi_get_type (void); - -extern CamelServiceAuthType camel_sasl_gssapi_authtype; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_SASL_GSSAPI_H__ */ diff --git a/camel/camel-sasl-kerberos4.c b/camel/camel-sasl-kerberos4.c deleted file mode 100644 index e225c1a26c..0000000000 --- a/camel/camel-sasl-kerberos4.c +++ /dev/null @@ -1,224 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_KRB4 - -#include -/* MIT krb4 des.h #defines _. Sigh. We don't need it. #undef it here - * so we get the gettexty _ definition later. - */ -#undef _ - -#include -#include "camel-string-utils.h" -#include "camel-sasl-kerberos4.h" -#include "camel-service.h" - -CamelServiceAuthType camel_sasl_kerberos4_authtype = { - N_("Kerberos 4"), - - N_("This option will connect to the server using " - "Kerberos 4 authentication."), - - "KERBEROS_V4", - FALSE -}; - -#define KERBEROS_V4_PROTECTION_NONE 1 -#define KERBEROS_V4_PROTECTION_INTEGRITY 2 -#define KERBEROS_V4_PROTECTION_PRIVACY 4 - -static CamelSaslClass *parent_class = NULL; - -/* Returns the class for a CamelSaslKerberos4 */ -#define CSK4_CLASS(so) CAMEL_SASL_KERBEROS4_CLASS (CAMEL_OBJECT_GET_CLASS (so)) - -static GByteArray *krb4_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex); - -struct _CamelSaslKerberos4Private { - int state; - - guint32 nonce_n; - guint32 nonce_h; - - des_cblock session; - des_key_schedule schedule; -}; - -static void -camel_sasl_kerberos4_class_init (CamelSaslKerberos4Class *camel_sasl_kerberos4_class) -{ - CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_kerberos4_class); - - parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ())); - - /* virtual method overload */ - camel_sasl_class->challenge = krb4_challenge; -} - -static void -camel_sasl_kerberos4_init (gpointer object, gpointer klass) -{ - CamelSaslKerberos4 *sasl_krb4 = CAMEL_SASL_KERBEROS4 (object); - - sasl_krb4->priv = g_new0 (struct _CamelSaslKerberos4Private, 1); -} - -static void -camel_sasl_kerberos4_finalize (CamelObject *object) -{ - CamelSaslKerberos4 *sasl = CAMEL_SASL_KERBEROS4 (object); - - if (sasl->priv) { - memset (sasl->priv, 0, sizeof (sasl->priv)); - g_free (sasl->priv); - } -} - - -CamelType -camel_sasl_kerberos4_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_sasl_get_type (), - "CamelSaslKerberos4", - sizeof (CamelSaslKerberos4), - sizeof (CamelSaslKerberos4Class), - (CamelObjectClassInitFunc) camel_sasl_kerberos4_class_init, - NULL, - (CamelObjectInitFunc) camel_sasl_kerberos4_init, - (CamelObjectFinalizeFunc) camel_sasl_kerberos4_finalize); - } - - return type; -} - -static GByteArray * -krb4_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) -{ - struct _CamelSaslKerberos4Private *priv = CAMEL_SASL_KERBEROS4 (sasl)->priv; - GByteArray *ret = NULL; - char *inst, *realm, *username; - struct hostent *h; - int status, len; - KTEXT_ST authenticator; - CREDENTIALS credentials; - guint32 plus1; - - /* Need to wait for the server */ - if (!token) - return NULL; - - switch (priv->state) { - case 0: - if (token->len != 4) - goto lose; - - memcpy (&priv->nonce_n, token->data, 4); - priv->nonce_h = ntohl (priv->nonce_n); - - /* Our response is an authenticator including that number. */ - h = camel_service_gethost (sasl->service, ex); - inst = g_strndup (h->h_name, strcspn (h->h_name, ".")); - camel_strdown (inst); - realm = g_strdup (krb_realmofhost (h->h_name)); - camel_free_host(h); - status = krb_mk_req (&authenticator, sasl->service_name, inst, realm, priv->nonce_h); - if (status == KSUCCESS) { - status = krb_get_cred (sasl->service_name, inst, realm, &credentials); - memcpy (priv->session, credentials.session, sizeof (priv->session)); - memset (&credentials, 0, sizeof (credentials)); - } - g_free (inst); - g_free (realm); - - if (status != KSUCCESS) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Could not get Kerberos ticket:\n%s"), - krb_err_txt[status]); - goto lose; - } - des_key_sched (&priv->session, priv->schedule); - - ret = g_byte_array_new (); - g_byte_array_append (ret, (const guint8 *)authenticator.dat, authenticator.length); - break; - - case 1: - if (token->len != 8) - goto lose; - - /* This one is encrypted. */ - des_ecb_encrypt ((des_cblock *)token->data, (des_cblock *)token->data, priv->schedule, 0); - - /* Check that the returned value is the original nonce plus one. */ - memcpy (&plus1, token->data, 4); - if (ntohl (plus1) != priv->nonce_h + 1) - goto lose; - - /* "the fifth octet contain[s] a bit-mask specifying the - * protection mechanisms supported by the server" - */ - if (!(token->data[4] & KERBEROS_V4_PROTECTION_NONE)) { - g_warning ("Server does not support `no protection' :-("); - goto lose; - } - - username = sasl->service->url->user; - len = strlen (username) + 9; - len += 8 - len % 8; - ret = g_byte_array_new (); - g_byte_array_set_size (ret, len); - memset (ret->data, 0, len); - memcpy (ret->data, &priv->nonce_n, 4); - ret->data[4] = KERBEROS_V4_PROTECTION_NONE; - ret->data[5] = ret->data[6] = ret->data[7] = 0; - strcpy (ret->data + 8, username); - - des_pcbc_encrypt ((void *)ret->data, (void *)ret->data, len, - priv->schedule, &priv->session, 1); - memset (&priv->session, 0, sizeof (priv->session)); - - sasl->authenticated = TRUE; - break; - } - - priv->state++; - return ret; - - lose: - memset (&priv->session, 0, sizeof (priv->session)); - - if (!camel_exception_is_set (ex)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Bad authentication response from server.")); - } - return NULL; -} - -#endif /* HAVE_KRB4 */ diff --git a/camel/camel-sasl-kerberos4.h b/camel/camel-sasl-kerberos4.h deleted file mode 100644 index d807fc70bc..0000000000 --- a/camel/camel-sasl-kerberos4.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef CAMEL_SASL_KERBEROS4_H -#define CAMEL_SASL_KERBEROS4_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include -#include - -#define CAMEL_SASL_KERBEROS4_TYPE (camel_sasl_kerberos4_get_type ()) -#define CAMEL_SASL_KERBEROS4(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_KERBEROS4_TYPE, CamelSaslKerberos4)) -#define CAMEL_SASL_KERBEROS4_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_KERBEROS4_TYPE, CamelSaslKerberos4Class)) -#define CAMEL_IS_SASL_KERBEROS4(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_KERBEROS4_TYPE)) - -typedef struct _CamelSaslKerberos4 { - CamelSasl parent_object; - struct _CamelSaslKerberos4Private *priv; - -} CamelSaslKerberos4; - - -typedef struct _CamelSaslKerberos4Class { - CamelSaslClass parent_class; - -} CamelSaslKerberos4Class; - - -/* Standard Camel function */ -CamelType camel_sasl_kerberos4_get_type (void); - -extern CamelServiceAuthType camel_sasl_kerberos4_authtype; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SASL_KERBEROS4_H */ diff --git a/camel/camel-sasl-login.c b/camel/camel-sasl-login.c deleted file mode 100644 index f6c3c9e5f8..0000000000 --- a/camel/camel-sasl-login.c +++ /dev/null @@ -1,134 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "camel-sasl-login.h" -#include "camel-service.h" - -CamelServiceAuthType camel_sasl_login_authtype = { - N_("Login"), - - N_("This option will connect to the server using a " - "simple password."), - - "LOGIN", - TRUE -}; - -enum { - LOGIN_USER, - LOGIN_PASSWD -}; - -static CamelSaslClass *parent_class = NULL; - -/* Returns the class for a CamelSaslLogin */ -#define CSP_CLASS(so) CAMEL_SASL_LOGIN_CLASS (CAMEL_OBJECT_GET_CLASS (so)) - -static GByteArray *login_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex); - -struct _CamelSaslLoginPrivate { - int state; -}; - -static void -camel_sasl_login_class_init (CamelSaslLoginClass *camel_sasl_login_class) -{ - CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_login_class); - - parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ())); - - /* virtual method overload */ - camel_sasl_class->challenge = login_challenge; -} - -static void -camel_sasl_login_init (gpointer object, gpointer klass) -{ - CamelSaslLogin *sasl_login = CAMEL_SASL_LOGIN (object); - - sasl_login->priv = g_new0 (struct _CamelSaslLoginPrivate, 1); -} - -static void -camel_sasl_login_finalize (CamelObject *object) -{ - CamelSaslLogin *sasl = CAMEL_SASL_LOGIN (object); - - g_free (sasl->priv); -} - - -CamelType -camel_sasl_login_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_sasl_get_type (), - "CamelSaslLogin", - sizeof (CamelSaslLogin), - sizeof (CamelSaslLoginClass), - (CamelObjectClassInitFunc) camel_sasl_login_class_init, - NULL, - (CamelObjectInitFunc) camel_sasl_login_init, - (CamelObjectFinalizeFunc) camel_sasl_login_finalize); - } - - return type; -} - -static GByteArray * -login_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) -{ - struct _CamelSaslLoginPrivate *priv = CAMEL_SASL_LOGIN (sasl)->priv; - GByteArray *buf = NULL; - CamelURL *url = sasl->service->url; - - g_return_val_if_fail (url->passwd != NULL, NULL); - - switch (priv->state) { - case LOGIN_USER: - buf = g_byte_array_new (); - g_byte_array_append (buf, url->user, strlen (url->user)); - break; - case LOGIN_PASSWD: - buf = g_byte_array_new (); - g_byte_array_append (buf, url->passwd, strlen (url->passwd)); - - sasl->authenticated = TRUE; - break; - default: - if (!camel_exception_is_set (ex)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Unknown authentication state.")); - } - } - - priv->state++; - - return buf; -} diff --git a/camel/camel-sasl-login.h b/camel/camel-sasl-login.h deleted file mode 100644 index dffa657202..0000000000 --- a/camel/camel-sasl-login.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef CAMEL_SASL_LOGIN_H -#define CAMEL_SASL_LOGIN_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include - -#define CAMEL_SASL_LOGIN_TYPE (camel_sasl_login_get_type ()) -#define CAMEL_SASL_LOGIN(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_LOGIN_TYPE, CamelSaslLogin)) -#define CAMEL_SASL_LOGIN_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_LOGIN_TYPE, CamelSaslLoginClass)) -#define CAMEL_IS_SASL_LOGIN(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_LOGIN_TYPE)) - -typedef struct _CamelSaslLogin { - CamelSasl parent_object; - - struct _CamelSaslLoginPrivate *priv; - -} CamelSaslLogin; - - -typedef struct _CamelSaslLoginClass { - CamelSaslClass parent_class; - -} CamelSaslLoginClass; - - -/* Standard Camel function */ -CamelType camel_sasl_login_get_type (void); - -extern CamelServiceAuthType camel_sasl_login_authtype; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SASL_LOGIN_H */ diff --git a/camel/camel-sasl-ntlm.c b/camel/camel-sasl-ntlm.c deleted file mode 100644 index ad341353c4..0000000000 --- a/camel/camel-sasl-ntlm.c +++ /dev/null @@ -1,706 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "camel-sasl-ntlm.h" - -#include -#include - -CamelServiceAuthType camel_sasl_ntlm_authtype = { - N_("NTLM / SPA"), - - N_("This option will connect to a Windows-based server using " - "NTLM / Secure Password Authentication."), - - "NTLM", - TRUE -}; - -static CamelSaslClass *parent_class = NULL; - -static GByteArray *ntlm_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex); - -static void -camel_sasl_ntlm_class_init (CamelSaslNTLMClass *camel_sasl_ntlm_class) -{ - CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_ntlm_class); - - parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ())); - - /* virtual method overload */ - camel_sasl_class->challenge = ntlm_challenge; -} - -CamelType -camel_sasl_ntlm_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register ( - camel_sasl_get_type (), "CamelSaslNTLM", - sizeof (CamelSaslNTLM), - sizeof (CamelSaslNTLMClass), - (CamelObjectClassInitFunc) camel_sasl_ntlm_class_init, - NULL, NULL, NULL); - } - - return type; -} - -#define NTLM_REQUEST "NTLMSSP\x00\x01\x00\x00\x00\x06\x82\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\x30\x00\x00\x00" - -#define NTLM_CHALLENGE_NONCE_OFFSET 24 -#define NTLM_CHALLENGE_DOMAIN_OFFSET 48 -#define NTLM_CHALLENGE_DOMAIN_LEN_OFFSET 44 - -#define NTLM_RESPONSE_HEADER "NTLMSSP\x00\x03\x00\x00\x00" -#define NTLM_RESPONSE_FLAGS "\x82\x01" -#define NTLM_RESPONSE_BASE_SIZE 64 -#define NTLM_RESPONSE_LM_RESP_OFFSET 12 -#define NTLM_RESPONSE_NT_RESP_OFFSET 20 -#define NTLM_RESPONSE_DOMAIN_OFFSET 28 -#define NTLM_RESPONSE_USER_OFFSET 36 -#define NTLM_RESPONSE_HOST_OFFSET 44 -#define NTLM_RESPONSE_FLAGS_OFFSET 60 - -static void ntlm_calc_response (const guchar key[21], - const guchar plaintext[8], - guchar results[24]); -static void ntlm_lanmanager_hash (const char *password, char hash[21]); -static void ntlm_nt_hash (const char *password, char hash[21]); -static void ntlm_set_string (GByteArray *ba, int offset, - const char *data, int len); - -static GByteArray * -ntlm_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) -{ - GByteArray *ret; - guchar nonce[8], hash[21], lm_resp[24], nt_resp[24]; - - ret = g_byte_array_new (); - - if (!token || !token->len) { - g_byte_array_append (ret, NTLM_REQUEST, - sizeof (NTLM_REQUEST) - 1); - return ret; - } - - memcpy (nonce, token->data + NTLM_CHALLENGE_NONCE_OFFSET, 8); - ntlm_lanmanager_hash (sasl->service->url->passwd, hash); - ntlm_calc_response (hash, nonce, lm_resp); - ntlm_nt_hash (sasl->service->url->passwd, hash); - ntlm_calc_response (hash, nonce, nt_resp); - - ret = g_byte_array_new (); - g_byte_array_set_size (ret, NTLM_RESPONSE_BASE_SIZE); - memset (ret->data, 0, NTLM_RESPONSE_BASE_SIZE); - memcpy (ret->data, NTLM_RESPONSE_HEADER, - sizeof (NTLM_RESPONSE_HEADER) - 1); - memcpy (ret->data + NTLM_RESPONSE_FLAGS_OFFSET, - NTLM_RESPONSE_FLAGS, sizeof (NTLM_RESPONSE_FLAGS) - 1); - - ntlm_set_string (ret, NTLM_RESPONSE_DOMAIN_OFFSET, - token->data + NTLM_CHALLENGE_DOMAIN_OFFSET, - atoi (token->data + NTLM_CHALLENGE_DOMAIN_LEN_OFFSET)); - ntlm_set_string (ret, NTLM_RESPONSE_USER_OFFSET, - sasl->service->url->user, - strlen (sasl->service->url->user)); - ntlm_set_string (ret, NTLM_RESPONSE_HOST_OFFSET, - "UNKNOWN", sizeof ("UNKNOWN") - 1); - ntlm_set_string (ret, NTLM_RESPONSE_LM_RESP_OFFSET, - lm_resp, sizeof (lm_resp)); - ntlm_set_string (ret, NTLM_RESPONSE_NT_RESP_OFFSET, - nt_resp, sizeof (nt_resp)); - - sasl->authenticated = TRUE; - return ret; -} - -/* MD4 */ -static void md4sum (const unsigned char *in, - int nbytes, - unsigned char digest[16]); - -/* DES */ -typedef unsigned long DES_KS[16][2]; /* Single-key DES key schedule */ - -static void deskey (DES_KS, unsigned char *, int); - -static void des (DES_KS, unsigned char *); - -static void setup_schedule (const guchar *key_56, DES_KS ks); - - - -#define LM_PASSWORD_MAGIC "\x4B\x47\x53\x21\x40\x23\x24\x25" \ - "\x4B\x47\x53\x21\x40\x23\x24\x25" \ - "\x00\x00\x00\x00\x00" - -static void -ntlm_lanmanager_hash (const char *password, char hash[21]) -{ - guchar lm_password [15]; - DES_KS ks; - int i; - - for (i = 0; i < 14 && password [i]; i++) - lm_password [i] = toupper ((unsigned char) password [i]); - - for (; i < 15; i++) - lm_password [i] = '\0'; - - memcpy (hash, LM_PASSWORD_MAGIC, 21); - - setup_schedule (lm_password, ks); - des (ks, hash); - - setup_schedule (lm_password + 7, ks); - des (ks, hash + 8); -} - -static void -ntlm_nt_hash (const char *password, char hash[21]) -{ - unsigned char *buf, *p; - - p = buf = g_malloc (strlen (password) * 2); - - while (*password) { - *p++ = *password++; - *p++ = '\0'; - } - - md4sum (buf, p - buf, hash); - memset (hash + 16, 0, 5); - - g_free (buf); -} - -static void -ntlm_set_string (GByteArray *ba, int offset, const char *data, int len) -{ - ba->data[offset ] = ba->data[offset + 2] = len & 0xFF; - ba->data[offset + 1] = ba->data[offset + 3] = (len >> 8) & 0xFF; - ba->data[offset + 4] = ba->len & 0xFF; - ba->data[offset + 5] = (ba->len >> 8) & 0xFF; - g_byte_array_append (ba, data, len); -} - - -#define KEYBITS(k,s) \ - (((k[(s)/8] << ((s)%8)) & 0xFF) | (k[(s)/8+1] >> (8-(s)%8))) - -/* DES utils */ -/* Set up a key schedule based on a 56bit key */ -static void -setup_schedule (const guchar *key_56, DES_KS ks) -{ - guchar key[8]; - int i, c, bit; - - for (i = 0; i < 8; i++) { - key [i] = KEYBITS (key_56, i * 7); - - /* Fix parity */ - for (c = bit = 0; bit < 8; bit++) - if (key [i] & (1 << bit)) - c++; - if (!(c & 1)) - key [i] ^= 0x01; - } - - deskey (ks, key, 0); -} - -static void -ntlm_calc_response (const guchar key[21], const guchar plaintext[8], - guchar results[24]) -{ - DES_KS ks; - - memcpy (results, plaintext, 8); - memcpy (results + 8, plaintext, 8); - memcpy (results + 16, plaintext, 8); - - setup_schedule (key, ks); - des (ks, results); - - setup_schedule (key + 7, ks); - des (ks, results + 8); - - setup_schedule (key + 14, ks); - des (ks, results + 16); -} - - -/* - * MD4 encoder. (The one everyone else uses is not GPL-compatible; - * this is a reimplementation from spec.) This doesn't need to be - * efficient for our purposes, although it would be nice to fix - * it to not malloc()... - */ - -#define F(X,Y,Z) ( ((X)&(Y)) | ((~(X))&(Z)) ) -#define G(X,Y,Z) ( ((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)) ) -#define H(X,Y,Z) ( (X)^(Y)^(Z) ) -#define ROT(val, n) ( ((val) << (n)) | ((val) >> (32 - (n))) ) - -static void -md4sum (const unsigned char *in, int nbytes, unsigned char digest[16]) -{ - unsigned char *M; - guint32 A, B, C, D, AA, BB, CC, DD, X[16]; - int pbytes, nbits = nbytes * 8, i, j; - - pbytes = (120 - (nbytes % 64)) % 64; - M = alloca (nbytes + pbytes + 8); - memcpy (M, in, nbytes); - memset (M + nbytes, 0, pbytes + 8); - M[nbytes] = 0x80; - M[nbytes + pbytes] = nbits & 0xFF; - M[nbytes + pbytes + 1] = (nbits >> 8) & 0xFF; - M[nbytes + pbytes + 2] = (nbits >> 16) & 0xFF; - M[nbytes + pbytes + 3] = (nbits >> 24) & 0xFF; - - A = 0x67452301; - B = 0xEFCDAB89; - C = 0x98BADCFE; - D = 0x10325476; - - for (i = 0; i < nbytes + pbytes + 8; i += 64) { - for (j = 0; j < 16; j++) { - X[j] = (M[i + j*4]) | - (M[i + j*4 + 1] << 8) | - (M[i + j*4 + 2] << 16) | - (M[i + j*4 + 3] << 24); - } - - AA = A; - BB = B; - CC = C; - DD = D; - - A = ROT (A + F(B, C, D) + X[0], 3); - D = ROT (D + F(A, B, C) + X[1], 7); - C = ROT (C + F(D, A, B) + X[2], 11); - B = ROT (B + F(C, D, A) + X[3], 19); - A = ROT (A + F(B, C, D) + X[4], 3); - D = ROT (D + F(A, B, C) + X[5], 7); - C = ROT (C + F(D, A, B) + X[6], 11); - B = ROT (B + F(C, D, A) + X[7], 19); - A = ROT (A + F(B, C, D) + X[8], 3); - D = ROT (D + F(A, B, C) + X[9], 7); - C = ROT (C + F(D, A, B) + X[10], 11); - B = ROT (B + F(C, D, A) + X[11], 19); - A = ROT (A + F(B, C, D) + X[12], 3); - D = ROT (D + F(A, B, C) + X[13], 7); - C = ROT (C + F(D, A, B) + X[14], 11); - B = ROT (B + F(C, D, A) + X[15], 19); - - A = ROT (A + G(B, C, D) + X[0] + 0x5A827999, 3); - D = ROT (D + G(A, B, C) + X[4] + 0x5A827999, 5); - C = ROT (C + G(D, A, B) + X[8] + 0x5A827999, 9); - B = ROT (B + G(C, D, A) + X[12] + 0x5A827999, 13); - A = ROT (A + G(B, C, D) + X[1] + 0x5A827999, 3); - D = ROT (D + G(A, B, C) + X[5] + 0x5A827999, 5); - C = ROT (C + G(D, A, B) + X[9] + 0x5A827999, 9); - B = ROT (B + G(C, D, A) + X[13] + 0x5A827999, 13); - A = ROT (A + G(B, C, D) + X[2] + 0x5A827999, 3); - D = ROT (D + G(A, B, C) + X[6] + 0x5A827999, 5); - C = ROT (C + G(D, A, B) + X[10] + 0x5A827999, 9); - B = ROT (B + G(C, D, A) + X[14] + 0x5A827999, 13); - A = ROT (A + G(B, C, D) + X[3] + 0x5A827999, 3); - D = ROT (D + G(A, B, C) + X[7] + 0x5A827999, 5); - C = ROT (C + G(D, A, B) + X[11] + 0x5A827999, 9); - B = ROT (B + G(C, D, A) + X[15] + 0x5A827999, 13); - - A = ROT (A + H(B, C, D) + X[0] + 0x6ED9EBA1, 3); - D = ROT (D + H(A, B, C) + X[8] + 0x6ED9EBA1, 9); - C = ROT (C + H(D, A, B) + X[4] + 0x6ED9EBA1, 11); - B = ROT (B + H(C, D, A) + X[12] + 0x6ED9EBA1, 15); - A = ROT (A + H(B, C, D) + X[2] + 0x6ED9EBA1, 3); - D = ROT (D + H(A, B, C) + X[10] + 0x6ED9EBA1, 9); - C = ROT (C + H(D, A, B) + X[6] + 0x6ED9EBA1, 11); - B = ROT (B + H(C, D, A) + X[14] + 0x6ED9EBA1, 15); - A = ROT (A + H(B, C, D) + X[1] + 0x6ED9EBA1, 3); - D = ROT (D + H(A, B, C) + X[9] + 0x6ED9EBA1, 9); - C = ROT (C + H(D, A, B) + X[5] + 0x6ED9EBA1, 11); - B = ROT (B + H(C, D, A) + X[13] + 0x6ED9EBA1, 15); - A = ROT (A + H(B, C, D) + X[3] + 0x6ED9EBA1, 3); - D = ROT (D + H(A, B, C) + X[11] + 0x6ED9EBA1, 9); - C = ROT (C + H(D, A, B) + X[7] + 0x6ED9EBA1, 11); - B = ROT (B + H(C, D, A) + X[15] + 0x6ED9EBA1, 15); - - A += AA; - B += BB; - C += CC; - D += DD; - } - - digest[0] = A & 0xFF; - digest[1] = (A >> 8) & 0xFF; - digest[2] = (A >> 16) & 0xFF; - digest[3] = (A >> 24) & 0xFF; - digest[4] = B & 0xFF; - digest[5] = (B >> 8) & 0xFF; - digest[6] = (B >> 16) & 0xFF; - digest[7] = (B >> 24) & 0xFF; - digest[8] = C & 0xFF; - digest[9] = (C >> 8) & 0xFF; - digest[10] = (C >> 16) & 0xFF; - digest[11] = (C >> 24) & 0xFF; - digest[12] = D & 0xFF; - digest[13] = (D >> 8) & 0xFF; - digest[14] = (D >> 16) & 0xFF; - digest[15] = (D >> 24) & 0xFF; -} - - -/* Public domain DES implementation from Phil Karn */ -static unsigned long Spbox[8][64] = { - { 0x01010400, 0x00000000, 0x00010000, 0x01010404, - 0x01010004, 0x00010404, 0x00000004, 0x00010000, - 0x00000400, 0x01010400, 0x01010404, 0x00000400, - 0x01000404, 0x01010004, 0x01000000, 0x00000004, - 0x00000404, 0x01000400, 0x01000400, 0x00010400, - 0x00010400, 0x01010000, 0x01010000, 0x01000404, - 0x00010004, 0x01000004, 0x01000004, 0x00010004, - 0x00000000, 0x00000404, 0x00010404, 0x01000000, - 0x00010000, 0x01010404, 0x00000004, 0x01010000, - 0x01010400, 0x01000000, 0x01000000, 0x00000400, - 0x01010004, 0x00010000, 0x00010400, 0x01000004, - 0x00000400, 0x00000004, 0x01000404, 0x00010404, - 0x01010404, 0x00010004, 0x01010000, 0x01000404, - 0x01000004, 0x00000404, 0x00010404, 0x01010400, - 0x00000404, 0x01000400, 0x01000400, 0x00000000, - 0x00010004, 0x00010400, 0x00000000, 0x01010004 }, - { 0x80108020, 0x80008000, 0x00008000, 0x00108020, - 0x00100000, 0x00000020, 0x80100020, 0x80008020, - 0x80000020, 0x80108020, 0x80108000, 0x80000000, - 0x80008000, 0x00100000, 0x00000020, 0x80100020, - 0x00108000, 0x00100020, 0x80008020, 0x00000000, - 0x80000000, 0x00008000, 0x00108020, 0x80100000, - 0x00100020, 0x80000020, 0x00000000, 0x00108000, - 0x00008020, 0x80108000, 0x80100000, 0x00008020, - 0x00000000, 0x00108020, 0x80100020, 0x00100000, - 0x80008020, 0x80100000, 0x80108000, 0x00008000, - 0x80100000, 0x80008000, 0x00000020, 0x80108020, - 0x00108020, 0x00000020, 0x00008000, 0x80000000, - 0x00008020, 0x80108000, 0x00100000, 0x80000020, - 0x00100020, 0x80008020, 0x80000020, 0x00100020, - 0x00108000, 0x00000000, 0x80008000, 0x00008020, - 0x80000000, 0x80100020, 0x80108020, 0x00108000 }, - { 0x00000208, 0x08020200, 0x00000000, 0x08020008, - 0x08000200, 0x00000000, 0x00020208, 0x08000200, - 0x00020008, 0x08000008, 0x08000008, 0x00020000, - 0x08020208, 0x00020008, 0x08020000, 0x00000208, - 0x08000000, 0x00000008, 0x08020200, 0x00000200, - 0x00020200, 0x08020000, 0x08020008, 0x00020208, - 0x08000208, 0x00020200, 0x00020000, 0x08000208, - 0x00000008, 0x08020208, 0x00000200, 0x08000000, - 0x08020200, 0x08000000, 0x00020008, 0x00000208, - 0x00020000, 0x08020200, 0x08000200, 0x00000000, - 0x00000200, 0x00020008, 0x08020208, 0x08000200, - 0x08000008, 0x00000200, 0x00000000, 0x08020008, - 0x08000208, 0x00020000, 0x08000000, 0x08020208, - 0x00000008, 0x00020208, 0x00020200, 0x08000008, - 0x08020000, 0x08000208, 0x00000208, 0x08020000, - 0x00020208, 0x00000008, 0x08020008, 0x00020200 }, - { 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802080, 0x00800081, 0x00800001, 0x00002001, - 0x00000000, 0x00802000, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00800080, 0x00800001, - 0x00000001, 0x00002000, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002001, 0x00002080, - 0x00800081, 0x00000001, 0x00002080, 0x00800080, - 0x00002000, 0x00802080, 0x00802081, 0x00000081, - 0x00800080, 0x00800001, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00000000, 0x00802000, - 0x00002080, 0x00800080, 0x00800081, 0x00000001, - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802081, 0x00000081, 0x00000001, 0x00002000, - 0x00800001, 0x00002001, 0x00802080, 0x00800081, - 0x00002001, 0x00002080, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002000, 0x00802080 }, - { 0x00000100, 0x02080100, 0x02080000, 0x42000100, - 0x00080000, 0x00000100, 0x40000000, 0x02080000, - 0x40080100, 0x00080000, 0x02000100, 0x40080100, - 0x42000100, 0x42080000, 0x00080100, 0x40000000, - 0x02000000, 0x40080000, 0x40080000, 0x00000000, - 0x40000100, 0x42080100, 0x42080100, 0x02000100, - 0x42080000, 0x40000100, 0x00000000, 0x42000000, - 0x02080100, 0x02000000, 0x42000000, 0x00080100, - 0x00080000, 0x42000100, 0x00000100, 0x02000000, - 0x40000000, 0x02080000, 0x42000100, 0x40080100, - 0x02000100, 0x40000000, 0x42080000, 0x02080100, - 0x40080100, 0x00000100, 0x02000000, 0x42080000, - 0x42080100, 0x00080100, 0x42000000, 0x42080100, - 0x02080000, 0x00000000, 0x40080000, 0x42000000, - 0x00080100, 0x02000100, 0x40000100, 0x00080000, - 0x00000000, 0x40080000, 0x02080100, 0x40000100 }, - { 0x20000010, 0x20400000, 0x00004000, 0x20404010, - 0x20400000, 0x00000010, 0x20404010, 0x00400000, - 0x20004000, 0x00404010, 0x00400000, 0x20000010, - 0x00400010, 0x20004000, 0x20000000, 0x00004010, - 0x00000000, 0x00400010, 0x20004010, 0x00004000, - 0x00404000, 0x20004010, 0x00000010, 0x20400010, - 0x20400010, 0x00000000, 0x00404010, 0x20404000, - 0x00004010, 0x00404000, 0x20404000, 0x20000000, - 0x20004000, 0x00000010, 0x20400010, 0x00404000, - 0x20404010, 0x00400000, 0x00004010, 0x20000010, - 0x00400000, 0x20004000, 0x20000000, 0x00004010, - 0x20000010, 0x20404010, 0x00404000, 0x20400000, - 0x00404010, 0x20404000, 0x00000000, 0x20400010, - 0x00000010, 0x00004000, 0x20400000, 0x00404010, - 0x00004000, 0x00400010, 0x20004010, 0x00000000, - 0x20404000, 0x20000000, 0x00400010, 0x20004010 }, - { 0x00200000, 0x04200002, 0x04000802, 0x00000000, - 0x00000800, 0x04000802, 0x00200802, 0x04200800, - 0x04200802, 0x00200000, 0x00000000, 0x04000002, - 0x00000002, 0x04000000, 0x04200002, 0x00000802, - 0x04000800, 0x00200802, 0x00200002, 0x04000800, - 0x04000002, 0x04200000, 0x04200800, 0x00200002, - 0x04200000, 0x00000800, 0x00000802, 0x04200802, - 0x00200800, 0x00000002, 0x04000000, 0x00200800, - 0x04000000, 0x00200800, 0x00200000, 0x04000802, - 0x04000802, 0x04200002, 0x04200002, 0x00000002, - 0x00200002, 0x04000000, 0x04000800, 0x00200000, - 0x04200800, 0x00000802, 0x00200802, 0x04200800, - 0x00000802, 0x04000002, 0x04200802, 0x04200000, - 0x00200800, 0x00000000, 0x00000002, 0x04200802, - 0x00000000, 0x00200802, 0x04200000, 0x00000800, - 0x04000002, 0x04000800, 0x00000800, 0x00200002 }, - { 0x10001040, 0x00001000, 0x00040000, 0x10041040, - 0x10000000, 0x10001040, 0x00000040, 0x10000000, - 0x00040040, 0x10040000, 0x10041040, 0x00041000, - 0x10041000, 0x00041040, 0x00001000, 0x00000040, - 0x10040000, 0x10000040, 0x10001000, 0x00001040, - 0x00041000, 0x00040040, 0x10040040, 0x10041000, - 0x00001040, 0x00000000, 0x00000000, 0x10040040, - 0x10000040, 0x10001000, 0x00041040, 0x00040000, - 0x00041040, 0x00040000, 0x10041000, 0x00001000, - 0x00000040, 0x10040040, 0x00001000, 0x00041040, - 0x10001000, 0x00000040, 0x10000040, 0x10040000, - 0x10040040, 0x10000000, 0x00040000, 0x10001040, - 0x00000000, 0x10041040, 0x00040040, 0x10000040, - 0x10040000, 0x10001000, 0x10001040, 0x00000000, - 0x10041040, 0x00041000, 0x00041000, 0x00001040, - 0x00001040, 0x00040040, 0x10000000, 0x10041000 } -}; - -#undef F -#define F(l,r,key){\ - work = ((r >> 4) | (r << 28)) ^ key[0];\ - l ^= Spbox[6][work & 0x3f];\ - l ^= Spbox[4][(work >> 8) & 0x3f];\ - l ^= Spbox[2][(work >> 16) & 0x3f];\ - l ^= Spbox[0][(work >> 24) & 0x3f];\ - work = r ^ key[1];\ - l ^= Spbox[7][work & 0x3f];\ - l ^= Spbox[5][(work >> 8) & 0x3f];\ - l ^= Spbox[3][(work >> 16) & 0x3f];\ - l ^= Spbox[1][(work >> 24) & 0x3f];\ -} -/* Encrypt or decrypt a block of data in ECB mode */ -static void -des(ks,block) -unsigned long ks[16][2]; /* Key schedule */ -unsigned char block[8]; /* Data block */ -{ - unsigned long left,right,work; - - /* Read input block and place in left/right in big-endian order */ - left = ((unsigned long)block[0] << 24) - | ((unsigned long)block[1] << 16) - | ((unsigned long)block[2] << 8) - | (unsigned long)block[3]; - right = ((unsigned long)block[4] << 24) - | ((unsigned long)block[5] << 16) - | ((unsigned long)block[6] << 8) - | (unsigned long)block[7]; - - /* Hoey's clever initial permutation algorithm, from Outerbridge - * (see Schneier p 478) - * - * The convention here is the same as Outerbridge: rotate each - * register left by 1 bit, i.e., so that "left" contains permuted - * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32 - * (using origin-1 numbering as in the FIPS). This allows us to avoid - * one of the two rotates that would otherwise be required in each of - * the 16 rounds. - */ - work = ((left >> 4) ^ right) & 0x0f0f0f0f; - right ^= work; - left ^= work << 4; - work = ((left >> 16) ^ right) & 0xffff; - right ^= work; - left ^= work << 16; - work = ((right >> 2) ^ left) & 0x33333333; - left ^= work; - right ^= (work << 2); - work = ((right >> 8) ^ left) & 0xff00ff; - left ^= work; - right ^= (work << 8); - right = (right << 1) | (right >> 31); - work = (left ^ right) & 0xaaaaaaaa; - left ^= work; - right ^= work; - left = (left << 1) | (left >> 31); - - /* Now do the 16 rounds */ - F(left,right,ks[0]); - F(right,left,ks[1]); - F(left,right,ks[2]); - F(right,left,ks[3]); - F(left,right,ks[4]); - F(right,left,ks[5]); - F(left,right,ks[6]); - F(right,left,ks[7]); - F(left,right,ks[8]); - F(right,left,ks[9]); - F(left,right,ks[10]); - F(right,left,ks[11]); - F(left,right,ks[12]); - F(right,left,ks[13]); - F(left,right,ks[14]); - F(right,left,ks[15]); - - /* Inverse permutation, also from Hoey via Outerbridge and Schneier */ - right = (right << 31) | (right >> 1); - work = (left ^ right) & 0xaaaaaaaa; - left ^= work; - right ^= work; - left = (left >> 1) | (left << 31); - work = ((left >> 8) ^ right) & 0xff00ff; - right ^= work; - left ^= work << 8; - work = ((left >> 2) ^ right) & 0x33333333; - right ^= work; - left ^= work << 2; - work = ((right >> 16) ^ left) & 0xffff; - left ^= work; - right ^= work << 16; - work = ((right >> 4) ^ left) & 0x0f0f0f0f; - left ^= work; - right ^= work << 4; - - /* Put the block back into the user's buffer with final swap */ - block[0] = right >> 24; - block[1] = right >> 16; - block[2] = right >> 8; - block[3] = right; - block[4] = left >> 24; - block[5] = left >> 16; - block[6] = left >> 8; - block[7] = left; -} - -/* Key schedule-related tables from FIPS-46 */ - -/* permuted choice table (key) */ -static unsigned char pc1[] = { - 57, 49, 41, 33, 25, 17, 9, - 1, 58, 50, 42, 34, 26, 18, - 10, 2, 59, 51, 43, 35, 27, - 19, 11, 3, 60, 52, 44, 36, - - 63, 55, 47, 39, 31, 23, 15, - 7, 62, 54, 46, 38, 30, 22, - 14, 6, 61, 53, 45, 37, 29, - 21, 13, 5, 28, 20, 12, 4 -}; - -/* number left rotations of pc1 */ -static unsigned char totrot[] = { - 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 -}; - -/* permuted choice key (table) */ -static unsigned char pc2[] = { - 14, 17, 11, 24, 1, 5, - 3, 28, 15, 6, 21, 10, - 23, 19, 12, 4, 26, 8, - 16, 7, 27, 20, 13, 2, - 41, 52, 31, 37, 47, 55, - 30, 40, 51, 45, 33, 48, - 44, 49, 39, 56, 34, 53, - 46, 42, 50, 36, 29, 32 -}; - -/* End of DES-defined tables */ - - -/* bit 0 is left-most in byte */ -static int bytebit[] = { - 0200,0100,040,020,010,04,02,01 -}; - - -/* Generate key schedule for encryption or decryption - * depending on the value of "decrypt" - */ -static void -deskey(k,key,decrypt) -DES_KS k; /* Key schedule array */ -unsigned char *key; /* 64 bits (will use only 56) */ -int decrypt; /* 0 = encrypt, 1 = decrypt */ -{ - unsigned char pc1m[56]; /* place to modify pc1 into */ - unsigned char pcr[56]; /* place to rotate pc1 into */ - register int i,j,l; - int m; - unsigned char ks[8]; - - for (j=0; j<56; j++) { /* convert pc1 to bits of key */ - l=pc1[j]-1; /* integer bit location */ - m = l & 07; /* find bit */ - pc1m[j]=(key[l>>3] & /* find which key byte l is in */ - bytebit[m]) /* and which bit of that byte */ - ? 1 : 0; /* and store 1-bit result */ - } - for (i=0; i<16; i++) { /* key chunk for each iteration */ - memset(ks,0,sizeof(ks)); /* Clear key schedule */ - for (j=0; j<56; j++) /* rotate pc1 the right amount */ - pcr[j] = pc1m[(l=j+totrot[decrypt? 15-i : i])<(j<28? 28 : 56) ? l: l-28]; - /* rotate left and right halves independently */ - for (j=0; j<48; j++){ /* select bits individually */ - /* check bit that goes to ks[j] */ - if (pcr[pc2[j]-1]){ - /* mask it in if it's there */ - l= j % 6; - ks[j/6] |= bytebit[l] >> 2; - } - } - /* Now convert to packed odd/even interleaved form */ - k[i][0] = ((long)ks[0] << 24) - | ((long)ks[2] << 16) - | ((long)ks[4] << 8) - | ((long)ks[6]); - k[i][1] = ((long)ks[1] << 24) - | ((long)ks[3] << 16) - | ((long)ks[5] << 8) - | ((long)ks[7]); - } -} diff --git a/camel/camel-sasl-ntlm.h b/camel/camel-sasl-ntlm.h deleted file mode 100644 index 3818081c74..0000000000 --- a/camel/camel-sasl-ntlm.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef CAMEL_SASL_NTLM_H -#define CAMEL_SASL_NTLM_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include - -#define CAMEL_SASL_NTLM_TYPE (camel_sasl_ntlm_get_type ()) -#define CAMEL_SASL_NTLM(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_NTLM_TYPE, CamelSaslNTLM)) -#define CAMEL_SASL_NTLM_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_NTLM_TYPE, CamelSaslNTLMClass)) -#define CAMEL_IS_SASL_NTLM(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_NTLM_TYPE)) - -typedef struct _CamelSaslNTLM { - CamelSasl parent_object; - -} CamelSaslNTLM; - - -typedef struct _CamelSaslNTLMClass { - CamelSaslClass parent_class; - -} CamelSaslNTLMClass; - - -/* Standard Camel function */ -CamelType camel_sasl_ntlm_get_type (void); - -extern CamelServiceAuthType camel_sasl_ntlm_authtype; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SASL_NTLM_H */ diff --git a/camel/camel-sasl-plain.c b/camel/camel-sasl-plain.c deleted file mode 100644 index 48d1fc9a01..0000000000 --- a/camel/camel-sasl-plain.c +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "camel-sasl-plain.h" -#include "camel-service.h" - -CamelServiceAuthType camel_sasl_plain_authtype = { - N_("PLAIN"), - - N_("This option will connect to the server using a " - "simple password."), - - "PLAIN", - TRUE -}; - -static CamelSaslClass *parent_class = NULL; - -/* Returns the class for a CamelSaslPlain */ -#define CSP_CLASS(so) CAMEL_SASL_PLAIN_CLASS (CAMEL_OBJECT_GET_CLASS (so)) - -static GByteArray *plain_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex); - -static void -camel_sasl_plain_class_init (CamelSaslPlainClass *camel_sasl_plain_class) -{ - CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_plain_class); - - parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ())); - - /* virtual method overload */ - camel_sasl_class->challenge = plain_challenge; -} - -CamelType -camel_sasl_plain_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_sasl_get_type (), - "CamelSaslPlain", - sizeof (CamelSaslPlain), - sizeof (CamelSaslPlainClass), - (CamelObjectClassInitFunc) camel_sasl_plain_class_init, - NULL, - NULL, - NULL); - } - - return type; -} - -static GByteArray * -plain_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) -{ - GByteArray *buf = NULL; - CamelURL *url = sasl->service->url; - -#if 0 - if (token) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Authentication failed.")); - return NULL; - } -#endif - - g_return_val_if_fail (url->passwd != NULL, NULL); - - /* FIXME: make sure these are "UTF8-SAFE" */ - buf = g_byte_array_new (); - g_byte_array_append (buf, "", 1); - g_byte_array_append (buf, url->user, strlen (url->user)); - g_byte_array_append (buf, "", 1); - g_byte_array_append (buf, url->passwd, strlen (url->passwd)); - - sasl->authenticated = TRUE; - - return buf; -} diff --git a/camel/camel-sasl-plain.h b/camel/camel-sasl-plain.h deleted file mode 100644 index a23568047e..0000000000 --- a/camel/camel-sasl-plain.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef CAMEL_SASL_PLAIN_H -#define CAMEL_SASL_PLAIN_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include - -#define CAMEL_SASL_PLAIN_TYPE (camel_sasl_plain_get_type ()) -#define CAMEL_SASL_PLAIN(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_PLAIN_TYPE, CamelSaslPlain)) -#define CAMEL_SASL_PLAIN_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_PLAIN_TYPE, CamelSaslPlainClass)) -#define CAMEL_IS_SASL_PLAIN(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_PLAIN_TYPE)) - -typedef struct _CamelSaslPlain { - CamelSasl parent_object; - -} CamelSaslPlain; - - -typedef struct _CamelSaslPlainClass { - CamelSaslClass parent_class; - -} CamelSaslPlainClass; - - -/* Standard Camel function */ -CamelType camel_sasl_plain_get_type (void); - -extern CamelServiceAuthType camel_sasl_plain_authtype; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SASL_PLAIN_H */ diff --git a/camel/camel-sasl-popb4smtp.c b/camel/camel-sasl-popb4smtp.c deleted file mode 100644 index 329151872e..0000000000 --- a/camel/camel-sasl-popb4smtp.c +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Michael Zucchi - * - * Copyright 2001-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "camel-sasl-popb4smtp.h" -#include "camel-service.h" -#include "camel-session.h" - -CamelServiceAuthType camel_sasl_popb4smtp_authtype = { - N_("POP before SMTP"), - - N_("This option will authorise a POP connection before attempting SMTP"), - - "POPB4SMTP", - FALSE, -}; - -/* last time the pop was accessed (through the auth method anyway), *time_t */ -static GHashTable *poplast; - -/* use 1 hour as our pop timeout */ -#define POPB4SMTP_TIMEOUT (60*60) - -static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; -#define POPB4SMTP_LOCK(l) pthread_mutex_lock(&l) -#define POPB4SMTP_UNLOCK(l) pthread_mutex_unlock(&l) - -static CamelSaslClass *parent_class = NULL; - -/* Returns the class for a CamelSaslPOPB4SMTP */ -#define CSP_CLASS(so) CAMEL_SASL_POPB4SMTP_CLASS (CAMEL_OBJECT_GET_CLASS (so)) - -static GByteArray *popb4smtp_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex); - -static void -camel_sasl_popb4smtp_class_init (CamelSaslPOPB4SMTPClass *camel_sasl_popb4smtp_class) -{ - CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_popb4smtp_class); - - parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ())); - - /* virtual method overload */ - camel_sasl_class->challenge = popb4smtp_challenge; - - poplast = g_hash_table_new(g_str_hash, g_str_equal); -} - -CamelType -camel_sasl_popb4smtp_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_sasl_get_type (), - "CamelSaslPOPB4SMTP", - sizeof (CamelSaslPOPB4SMTP), - sizeof (CamelSaslPOPB4SMTPClass), - (CamelObjectClassInitFunc) camel_sasl_popb4smtp_class_init, - NULL, - NULL, - NULL); - } - - return type; -} - -static GByteArray * -popb4smtp_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) -{ - char *popuri; - CamelSession *session = sasl->service->session; - CamelStore *store; - time_t now, *timep; - - sasl->authenticated = FALSE; - - popuri = camel_session_get_password (session, _("POP Source URI"), FALSE, FALSE, - sasl->service, "popb4smtp_uri", ex); - - if (popuri == NULL) { - camel_exception_setv(ex, 1, _("POP Before SMTP auth using an unknown transport")); - return NULL; - } - - if (strncasecmp(popuri, "pop:", 4) != 0) { - camel_exception_setv(ex, 1, _("POP Before SMTP auth using a non-pop source")); - return NULL; - } - - /* check if we've done it before recently in this session */ - now = time(0); - - /* need to lock around the whole thing until finished with timep */ - - POPB4SMTP_LOCK(lock); - timep = g_hash_table_lookup(poplast, popuri); - if (timep) { - if ((*timep + POPB4SMTP_TIMEOUT) > now) { - sasl->authenticated = TRUE; - POPB4SMTP_UNLOCK(lock); - g_free(popuri); - return NULL; - } - } else { - timep = g_malloc0(sizeof(*timep)); - g_hash_table_insert(poplast, g_strdup(popuri), timep); - } - - /* connect to pop session */ - store = camel_session_get_store(session, popuri, ex); - if (store) { - sasl->authenticated = TRUE; - camel_object_unref((CamelObject *)store); - *timep = now; - } else { - sasl->authenticated = FALSE; - *timep = 0; - } - - POPB4SMTP_UNLOCK(lock); - - g_free(popuri); - - return NULL; -} diff --git a/camel/camel-sasl-popb4smtp.h b/camel/camel-sasl-popb4smtp.h deleted file mode 100644 index b94bed0d49..0000000000 --- a/camel/camel-sasl-popb4smtp.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Michael Zucchi - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef CAMEL_SASL_POPB4SMTP_H -#define CAMEL_SASL_POPB4SMTP_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include - -#define CAMEL_SASL_POPB4SMTP_TYPE (camel_sasl_popb4smtp_get_type ()) -#define CAMEL_SASL_POPB4SMTP(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_POPB4SMTP_TYPE, CamelSaslPOPB4SMTP)) -#define CAMEL_SASL_POPB4SMTP_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_POPB4SMTP_TYPE, CamelSaslPOPB4SMTPClass)) -#define CAMEL_IS_SASL_POPB4SMTP(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_POPB4SMTP_TYPE)) - -typedef struct _CamelSaslPOPB4SMTP { - CamelSasl parent_object; - -} CamelSaslPOPB4SMTP; - - -typedef struct _CamelSaslPOPB4SMTPClass { - CamelSaslClass parent_class; - -} CamelSaslPOPB4SMTPClass; - - -/* Standard Camel function */ -CamelType camel_sasl_popb4smtp_get_type (void); - -extern CamelServiceAuthType camel_sasl_popb4smtp_authtype; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SASL_POPB4SMTP_H */ diff --git a/camel/camel-sasl.c b/camel/camel-sasl.c deleted file mode 100644 index 24ee6e4d94..0000000000 --- a/camel/camel-sasl.c +++ /dev/null @@ -1,285 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "camel-sasl.h" -#include "camel-mime-utils.h" -#include "camel-service.h" - -#include "camel-sasl-cram-md5.h" -#include "camel-sasl-digest-md5.h" -#include "camel-sasl-gssapi.h" -#include "camel-sasl-kerberos4.h" -#include "camel-sasl-login.h" -#include "camel-sasl-plain.h" -#include "camel-sasl-popb4smtp.h" -#include "camel-sasl-ntlm.h" - - -#define w(x) - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelSasl */ -#define CS_CLASS(so) CAMEL_SASL_CLASS (CAMEL_OBJECT_GET_CLASS (so)) - -static GByteArray *sasl_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex); - -static void -camel_sasl_class_init (CamelSaslClass *camel_sasl_class) -{ - parent_class = camel_type_get_global_classfuncs (CAMEL_OBJECT_TYPE); - - /* virtual method definition */ - camel_sasl_class->challenge = sasl_challenge; -} - -static void -camel_sasl_finalize (CamelSasl *sasl) -{ - g_free (sasl->service_name); - g_free (sasl->mech); - camel_object_unref (sasl->service); -} - -CamelType -camel_sasl_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (CAMEL_OBJECT_TYPE, - "CamelSasl", - sizeof (CamelSasl), - sizeof (CamelSaslClass), - (CamelObjectClassInitFunc) camel_sasl_class_init, - NULL, - NULL, - (CamelObjectFinalizeFunc) camel_sasl_finalize); - } - - return type; -} - - -static GByteArray * -sasl_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) -{ - w(g_warning ("sasl_challenge: Using default implementation!")); - return NULL; -} - -/** - * camel_sasl_challenge: - * @sasl: a SASL object - * @token: a token, or %NULL - * @ex: exception - * - * If @token is %NULL, generate the initial SASL message to send to - * the server. (This will be %NULL if the client doesn't initiate the - * exchange.) Otherwise, @token is a challenge from the server, and - * the return value is the response. - * - * Return value: The SASL response or %NULL. If an error occurred, @ex - * will also be set. - **/ -GByteArray * -camel_sasl_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) -{ - g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL); - - return CS_CLASS (sasl)->challenge (sasl, token, ex); -} - -/** - * camel_sasl_challenge_base64: - * @sasl: a SASL object - * @token: a base64-encoded token - * @ex: exception - * - * As with camel_sasl_challenge(), but the challenge @token and the - * response are both base64-encoded. - * - * Return value: As with camel_sasl_challenge(), but base64-encoded. - **/ -char * -camel_sasl_challenge_base64 (CamelSasl *sasl, const char *token, CamelException *ex) -{ - GByteArray *token_binary, *ret_binary; - char *ret; - int len; - - g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL); - - if (token) { - token_binary = g_byte_array_new (); - len = strlen (token); - g_byte_array_append (token_binary, token, len); - token_binary->len = camel_base64_decode_simple (token_binary->data, len); - } else - token_binary = NULL; - - ret_binary = camel_sasl_challenge (sasl, token_binary, ex); - if (token_binary) - g_byte_array_free (token_binary, TRUE); - if (!ret_binary) - return NULL; - - ret = camel_base64_encode_simple (ret_binary->data, ret_binary->len); - g_byte_array_free (ret_binary, TRUE); - - return ret; -} - -/** - * camel_sasl_authenticated: - * @sasl: a SASL object - * - * Return value: whether or not @sasl has successfully authenticated - * the user. This will be %TRUE after it returns the last needed response. - * The caller must still pass that information on to the server and verify - * that it has accepted it. - **/ -gboolean -camel_sasl_authenticated (CamelSasl *sasl) -{ - return sasl->authenticated; -} - - -/** - * camel_sasl_new: - * @service_name: the SASL service name - * @mechanism: the SASL mechanism - * @service: the CamelService that will be using this SASL - * - * Return value: a new CamelSasl for the given @service_name, - * @mechanism, and @service, or %NULL if the mechanism is not - * supported. - **/ -CamelSasl * -camel_sasl_new (const char *service_name, const char *mechanism, CamelService *service) -{ - CamelSasl *sasl; - - g_return_val_if_fail (service_name != NULL, NULL); - g_return_val_if_fail (mechanism != NULL, NULL); - g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL); - - /* We don't do ANONYMOUS here, because it's a little bit weird. */ - - if (!strcmp (mechanism, "CRAM-MD5")) - sasl = (CamelSasl *) camel_object_new (CAMEL_SASL_CRAM_MD5_TYPE); - else if (!strcmp (mechanism, "DIGEST-MD5")) - sasl = (CamelSasl *) camel_object_new (CAMEL_SASL_DIGEST_MD5_TYPE); -#ifdef HAVE_KRB5 - else if (!strcmp (mechanism, "GSSAPI")) - sasl = (CamelSasl *) camel_object_new (CAMEL_SASL_GSSAPI_TYPE); -#endif -#ifdef HAVE_KRB4 - else if (!strcmp (mechanism, "KERBEROS_V4")) - sasl = (CamelSasl *) camel_object_new (CAMEL_SASL_KERBEROS4_TYPE); -#endif - else if (!strcmp (mechanism, "PLAIN")) - sasl = (CamelSasl *) camel_object_new (CAMEL_SASL_PLAIN_TYPE); - else if (!strcmp (mechanism, "LOGIN")) - sasl = (CamelSasl *) camel_object_new (CAMEL_SASL_LOGIN_TYPE); - else if (!strcmp (mechanism, "POPB4SMTP")) - sasl = (CamelSasl *) camel_object_new (CAMEL_SASL_POPB4SMTP_TYPE); - else if (!strcmp (mechanism, "NTLM")) - sasl = (CamelSasl *) camel_object_new (CAMEL_SASL_NTLM_TYPE); - else - return NULL; - - sasl->mech = g_strdup (mechanism); - sasl->service_name = g_strdup (service_name); - sasl->service = service; - camel_object_ref (service); - - return sasl; -} - -/** - * camel_sasl_authtype_list: - * @include_plain: whether or not to include the PLAIN mechanism - * - * Return value: a GList of SASL-supported authtypes. The caller must - * free the list, but not the contents. - **/ -GList * -camel_sasl_authtype_list (gboolean include_plain) -{ - GList *types = NULL; - - types = g_list_prepend (types, &camel_sasl_cram_md5_authtype); - types = g_list_prepend (types, &camel_sasl_digest_md5_authtype); -#ifdef HAVE_KRB5 - types = g_list_prepend (types, &camel_sasl_gssapi_authtype); -#endif -#ifdef HAVE_KRB4 - types = g_list_prepend (types, &camel_sasl_kerberos4_authtype); -#endif - types = g_list_prepend (types, &camel_sasl_ntlm_authtype); - if (include_plain) - types = g_list_prepend (types, &camel_sasl_plain_authtype); - - return types; -} - -/** - * camel_sasl_authtype: - * @mechanism: the SASL mechanism to get an authtype for - * - * Return value: a CamelServiceAuthType for the given mechanism, if - * it is supported. - **/ -CamelServiceAuthType * -camel_sasl_authtype (const char *mechanism) -{ - if (!strcmp (mechanism, "CRAM-MD5")) - return &camel_sasl_cram_md5_authtype; - else if (!strcmp (mechanism, "DIGEST-MD5")) - return &camel_sasl_digest_md5_authtype; -#ifdef HAVE_KRB5 - else if (!strcmp (mechanism, "GSSAPI")) - return &camel_sasl_gssapi_authtype; -#endif -#ifdef HAVE_KRB4 - else if (!strcmp (mechanism, "KERBEROS_V4")) - return &camel_sasl_kerberos4_authtype; -#endif - else if (!strcmp (mechanism, "PLAIN")) - return &camel_sasl_plain_authtype; - else if (!strcmp (mechanism, "LOGIN")) - return &camel_sasl_login_authtype; - else if (!strcmp(mechanism, "POPB4SMTP")) - return &camel_sasl_popb4smtp_authtype; - else if (!strcmp (mechanism, "NTLM")) - return &camel_sasl_ntlm_authtype; - else - return NULL; -} diff --git a/camel/camel-sasl.h b/camel/camel-sasl.h deleted file mode 100644 index 2b5db5c447..0000000000 --- a/camel/camel-sasl.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef CAMEL_SASL_H -#define CAMEL_SASL_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include -#include -#include - -#define CAMEL_SASL_TYPE (camel_sasl_get_type ()) -#define CAMEL_SASL(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_TYPE, CamelSasl)) -#define CAMEL_SASL_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_TYPE, CamelSaslClass)) -#define CAMEL_IS_SASL(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_TYPE)) - -typedef struct _CamelSasl { - CamelObject parent_object; - - char *service_name; - char *mech; /* mechanism */ - CamelService *service; - gboolean authenticated; -} CamelSasl; - - -typedef struct _CamelSaslClass { - CamelObjectClass parent_class; - - GByteArray * (*challenge) (CamelSasl *sasl, GByteArray *token, CamelException *ex); - -} CamelSaslClass; - - -/* Standard Camel function */ -CamelType camel_sasl_get_type (void); - -/* public methods */ -GByteArray *camel_sasl_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex); -char *camel_sasl_challenge_base64 (CamelSasl *sasl, const char *token, CamelException *ex); - -gboolean camel_sasl_authenticated (CamelSasl *sasl); - -/* utility functions */ -CamelSasl *camel_sasl_new (const char *service_name, const char *mechanism, CamelService *service); - -GList *camel_sasl_authtype_list (gboolean include_plain); -CamelServiceAuthType *camel_sasl_authtype (const char *mechanism); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SASL_H */ diff --git a/camel/camel-search-private.c b/camel/camel-search-private.c deleted file mode 100644 index 2ba908bea3..0000000000 --- a/camel/camel-search-private.c +++ /dev/null @@ -1,684 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * Michael Zucchi - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * Copyright 2001 Ximian Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -/* (from glibc headers: - POSIX says that must be included (by the caller) before . */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include "camel-exception.h" -#include "camel-mime-message.h" -#include "camel-multipart.h" -#include "camel-stream-mem.h" -#include "e-util/e-sexp.h" - -#include "camel-search-private.h" - -#include - -#define d(x) - -/* builds the regex into pattern */ -/* taken from camel-folder-search, with added isregex & exception parameter */ -/* Basically, we build a new regex, either based on subset regex's, or substrings, - that can be executed once over the whoel body, to match anything suitable. - This is more efficient than multiple searches, and probably most (naive) strstr - implementations, over long content. - - A small issue is that case-insenstivity wont work entirely correct for utf8 strings. */ -int -camel_search_build_match_regex (regex_t *pattern, camel_search_flags_t type, int argc, - struct _ESExpResult **argv, CamelException *ex) -{ - GString *match = g_string_new(""); - int c, i, count=0, err; - char *word; - int flags; - - /* build a regex pattern we can use to match the words, we OR them together */ - if (argc>1) - g_string_append_c (match, '('); - for (i = 0; i < argc; i++) { - if (argv[i]->type == ESEXP_RES_STRING) { - if (count > 0) - g_string_append_c (match, '|'); - - word = argv[i]->value.string; - if (type & CAMEL_SEARCH_MATCH_REGEX) { - /* no need to escape because this should already be a valid regex */ - g_string_append (match, word); - } else { - /* escape any special chars (not sure if this list is complete) */ - if (type & CAMEL_SEARCH_MATCH_START) - g_string_append_c (match, '^'); - while ((c = *word++)) { - if (strchr ("*\\.()[]^$+", c) != NULL) { - g_string_append_c (match, '\\'); - } - g_string_append_c (match, c); - } - if (type & CAMEL_SEARCH_MATCH_END) - g_string_append_c (match, '^'); - } - count++; - } else { - g_warning("Invalid type passed to body-contains match function"); - } - } - if (argc > 1) - g_string_append_c (match, ')'); - flags = REG_EXTENDED|REG_NOSUB; - if (type & CAMEL_SEARCH_MATCH_ICASE) - flags |= REG_ICASE; - if (type & CAMEL_SEARCH_MATCH_NEWLINE) - flags |= REG_NEWLINE; - err = regcomp (pattern, match->str, flags); - if (err != 0) { - /* regerror gets called twice to get the full error string - length to do proper posix error reporting */ - int len = regerror (err, pattern, 0, 0); - char *buffer = g_malloc0 (len + 1); - - regerror (err, pattern, buffer, len); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Regular expression compilation failed: %s: %s"), - match->str, buffer); - - regfree (pattern); - } - d(printf("Built regex: '%s'\n", match->str)); - g_string_free (match, TRUE); - - return err; -} - -static unsigned char soundex_table[256] = { - 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, 0, - 0, 0, 49, 50, 51, 0, 49, 50, 0, 0, 50, 50, 52, 53, 53, 0, - 49, 50, 54, 50, 51, 0, 49, 0, 50, 0, 50, 0, 0, 0, 0, 0, - 0, 0, 49, 50, 51, 0, 49, 50, 0, 0, 50, 50, 52, 53, 53, 0, - 49, 50, 54, 50, 51, 0, 49, 0, 50, 0, 50, 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, 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, 0, 0, 0, 0, 0, 0, 0, -}; - -static void -soundexify (const gchar *sound, gchar code[5]) -{ - guchar *c, last = '\0'; - gint n; - - for (c = (guchar *) sound; *c && !isalpha (*c); c++); - code[0] = toupper (*c); - memset (code + 1, '0', 3); - for (n = 1; *c && n < 5; c++) { - guchar ch = soundex_table[*c]; - - if (ch && ch != last) { - code[n++] = ch; - last = ch; - } - } - code[4] = '\0'; -} - -static gboolean -header_soundex (const char *header, const char *match) -{ - char mcode[5], hcode[5]; - const char *p; - char c; - GString *word; - int truth = FALSE; - - soundexify (match, mcode); - - /* split the header into words, and soundexify and compare each one */ - /* FIXME: Should this convert to utf8, and split based on that, and what not? - soundex only makes sense for us-ascii though ... */ - - word = g_string_new(""); - p = header; - do { - c = *p++; - if (c == 0 || isspace (c)) { - if (word->len > 0) { - soundexify (word->str, hcode); - if (strcmp (hcode, mcode) == 0) - truth = TRUE; - } - g_string_truncate (word, 0); - } else if (isalpha (c)) - g_string_append_c (word, c); - } while (c && !truth); - g_string_free (word, TRUE); - - return truth; -} - -/* FIXME: This is stupidly slow and needs to be removed */ -static gunichar -utf8_get (const char **inp) -{ - const unsigned char *p = *inp; - gunichar c; - - if (p == NULL) - return 0; - - c = g_utf8_get_char (p); - *inp = g_unichar_validate (c) ? g_utf8_next_char (p) : NULL; - - return c; -} - -const char * -camel_ustrstrcase (const char *haystack, const char *needle) -{ - gunichar *nuni, *puni; - gunichar u; - const char *p; - - g_return_val_if_fail (haystack != NULL, NULL); - g_return_val_if_fail (needle != NULL, NULL); - - if (strlen (needle) == 0) - return haystack; - if (strlen (haystack) == 0) - return NULL; - - puni = nuni = g_alloca (sizeof (gunichar) * strlen (needle)); - - p = needle; - while ((u = utf8_get (&p))) - *puni++ = g_unichar_tolower (u); - - /* NULL means there was illegal utf-8 sequence */ - if (!p) - return NULL; - - p = haystack; - while ((u = utf8_get (&p))) { - gunichar c; - - c = g_unichar_tolower (u); - /* We have valid stripped char */ - if (c == nuni[0]) { - const gchar *q = p; - gint npos = 1; - - while (nuni + npos < puni) { - u = utf8_get (&q); - if (!q || !u) - return NULL; - - c = g_unichar_tolower (u); - if (c != nuni[npos]) - break; - - npos++; - } - - if (nuni + npos == puni) - return p; - } - } - - return NULL; -} - -#define CAMEL_SEARCH_COMPARE(x, y, z) G_STMT_START { \ - if ((x) == (z)) { \ - if ((y) == (z)) \ - return 0; \ - else \ - return -1; \ - } else if ((y) == (z)) \ - return 1; \ -} G_STMT_END - -static int -camel_ustrcasecmp (const char *s1, const char *s2) -{ - gunichar u1, u2 = 0; - - CAMEL_SEARCH_COMPARE (s1, s2, NULL); - - u1 = utf8_get (&s1); - u2 = utf8_get (&s2); - while (u1 && u2) { - u1 = g_unichar_tolower (u1); - u2 = g_unichar_tolower (u2); - if (u1 < u2) - return -1; - else if (u1 > u2) - return 1; - - u1 = utf8_get (&s1); - u2 = utf8_get (&s2); - } - - /* end of one of the strings ? */ - CAMEL_SEARCH_COMPARE (u1, u2, 0); - - /* if we have invalid utf8 sequence ? */ - CAMEL_SEARCH_COMPARE (s1, s2, NULL); - - return 0; -} - -static int -camel_ustrncasecmp (const char *s1, const char *s2, size_t len) -{ - gunichar u1, u2 = 0; - - CAMEL_SEARCH_COMPARE (s1, s2, NULL); - - u1 = utf8_get (&s1); - u2 = utf8_get (&s2); - while (len > 0 && u1 && u2) { - u1 = g_unichar_tolower (u1); - u2 = g_unichar_tolower (u2); - if (u1 < u2) - return -1; - else if (u1 > u2) - return 1; - - len--; - u1 = utf8_get (&s1); - u2 = utf8_get (&s2); - } - - if (len == 0) - return 0; - - /* end of one of the strings ? */ - CAMEL_SEARCH_COMPARE (u1, u2, 0); - - /* if we have invalid utf8 sequence ? */ - CAMEL_SEARCH_COMPARE (s1, s2, NULL); - - return 0; -} - -/* value is the match value suitable for exact match if required */ -static int -header_match(const char *value, const char *match, camel_search_match_t how) -{ - const char *p; - int vlen, mlen; - - if (how == CAMEL_SEARCH_MATCH_SOUNDEX) - return header_soundex (value, match); - - vlen = strlen(value); - mlen = strlen(match); - if (vlen < mlen) - return FALSE; - - /* from dan the man, if we have mixed case, perform a case-sensitive match, - otherwise not */ - p = match; - while (*p) { - if (isupper(*p)) { - switch (how) { - case CAMEL_SEARCH_MATCH_EXACT: - return strcmp(value, match) == 0; - case CAMEL_SEARCH_MATCH_CONTAINS: - return strstr(value, match) != NULL; - case CAMEL_SEARCH_MATCH_STARTS: - return strncmp(value, match, mlen) == 0; - case CAMEL_SEARCH_MATCH_ENDS: - return strcmp(value + vlen - mlen, match) == 0; - default: - break; - } - return FALSE; - } - p++; - } - - switch (how) { - case CAMEL_SEARCH_MATCH_EXACT: - return camel_ustrcasecmp(value, match) == 0; - case CAMEL_SEARCH_MATCH_CONTAINS: - return camel_ustrstrcase(value, match) != NULL; - case CAMEL_SEARCH_MATCH_STARTS: - return camel_ustrncasecmp(value, match, mlen) == 0; - case CAMEL_SEARCH_MATCH_ENDS: - return camel_ustrcasecmp(value + vlen - mlen, match) == 0; - default: - break; - } - - return FALSE; -} - -/* searhces for match inside value, if match is mixed case, hten use case-sensitive, - else insensitive */ -gboolean -camel_search_header_match (const char *value, const char *match, camel_search_match_t how, camel_search_t type, const char *default_charset) -{ - const char *name, *addr; - int truth = FALSE, i; - CamelInternetAddress *cia; - char *v, *vdom, *mdom; - - while (*value && isspace (*value)) - value++; - - switch(type) { - case CAMEL_SEARCH_TYPE_ENCODED: - v = camel_header_decode_string(value, default_charset); /* FIXME: Find header charset */ - truth = header_match(v, match, how); - g_free(v); - break; - case CAMEL_SEARCH_TYPE_MLIST: - /* Special mailing list old-version domain hack - If one of the mailing list names doesn't have an @ in it, its old-style, so - only match against the pre-domain part, which should be common */ - - vdom = strchr(value, '@'); - mdom = strchr(match, '@'); - if (mdom == NULL && vdom != NULL) { - v = g_alloca(vdom-value+1); - memcpy(v, value, vdom-value); - v[vdom-value] = 0; - value = (char *)v; - } else if (mdom != NULL && vdom == NULL) { - v = g_alloca(mdom-match+1); - memcpy(v, match, mdom-match); - v[mdom-match] = 0; - match = (char *)v; - } - /* Falls through */ - case CAMEL_SEARCH_TYPE_ASIS: - truth = header_match(value, match, how); - break; - case CAMEL_SEARCH_TYPE_ADDRESS_ENCODED: - case CAMEL_SEARCH_TYPE_ADDRESS: - /* possible simple case to save some work if we can */ - if (header_match(value, match, how)) - return TRUE; - - /* Now we decode any addresses, and try asis matches on name and address parts */ - cia = camel_internet_address_new(); - if (type == CAMEL_SEARCH_TYPE_ADDRESS_ENCODED) - camel_address_decode((CamelAddress *)cia, value); - else - camel_address_unformat((CamelAddress *)cia, value); - - for (i=0; !truth && camel_internet_address_get(cia, i, &name, &addr);i++) - truth = (name && header_match(name, match, how)) || (addr && header_match(addr, match, how)); - - camel_object_unref (cia); - break; - } - - return truth; -} - -/* performs a 'slow' content-based match */ -/* there is also an identical copy of this in camel-filter-search.c */ -gboolean -camel_search_message_body_contains (CamelDataWrapper *object, regex_t *pattern) -{ - CamelDataWrapper *containee; - int truth = FALSE; - int parts, i; - - containee = camel_medium_get_content_object (CAMEL_MEDIUM (object)); - - if (containee == NULL) - return FALSE; - - /* using the object types is more accurate than using the mime/types */ - if (CAMEL_IS_MULTIPART (containee)) { - parts = camel_multipart_get_number (CAMEL_MULTIPART (containee)); - for (i = 0; i < parts && truth == FALSE; i++) { - CamelDataWrapper *part = (CamelDataWrapper *)camel_multipart_get_part (CAMEL_MULTIPART (containee), i); - if (part) - truth = camel_search_message_body_contains (part, pattern); - } - } else if (CAMEL_IS_MIME_MESSAGE (containee)) { - /* for messages we only look at its contents */ - truth = camel_search_message_body_contains ((CamelDataWrapper *)containee, pattern); - } else if (camel_content_type_is(CAMEL_DATA_WRAPPER (containee)->mime_type, "text", "*")) { - /* for all other text parts, we look inside, otherwise we dont care */ - CamelStreamMem *mem = (CamelStreamMem *)camel_stream_mem_new (); - - camel_data_wrapper_write_to_stream (containee, CAMEL_STREAM (mem)); - camel_stream_write (CAMEL_STREAM (mem), "", 1); - truth = regexec (pattern, mem->buffer->data, 0, NULL, 0) == 0; - camel_object_unref (mem); - } - - return truth; -} - -static inline guint32 -camel_utf8_getc(const unsigned char **ptr) -{ - register unsigned char *p = (unsigned char *)*ptr; - register unsigned char c, r; - register guint32 v, m; - -again: - r = *p++; -loop: - if (r < 0x80) { - *ptr = p; - v = r; - } else if (r < 0xfe) { /* valid start char? */ - v = r; - m = 0x7f80; /* used to mask out the length bits */ - do { - c = *p++; - if ((c & 0xc0) != 0x80) { - r = c; - goto loop; - } - v = (v<<6) | (c & 0x3f); - r<<=1; - m<<=5; - } while (r & 0x40); - - *ptr = p; - - v &= ~m; - } else { - goto again; - } - - return v; -} - -static void -output_c(GString *w, guint32 c, int *type) -{ - int utf8len; - char utf8[8]; - - if (!g_unichar_isalnum(c)) - *type = CAMEL_SEARCH_WORD_COMPLEX | (*type & CAMEL_SEARCH_WORD_8BIT); - else - c = g_unichar_tolower(c); - - if (c > 0x80) - *type |= CAMEL_SEARCH_WORD_8BIT; - - /* FIXME: use camel_utf8_putc */ - utf8len = g_unichar_to_utf8(c, utf8); - utf8[utf8len] = 0; - g_string_append(w, utf8); -} - -static void -output_w(GString *w, GPtrArray *list, int type) -{ - struct _camel_search_word *word; - - if (w->len) { - word = g_malloc0(sizeof(*word)); - word->word = g_strdup(w->str); - word->type = type; - g_ptr_array_add(list, word); - g_string_truncate(w, 0); - } -} - -struct _camel_search_words * -camel_search_words_split(const unsigned char *in) -{ - int type = CAMEL_SEARCH_WORD_SIMPLE, all = 0; - GString *w; - struct _camel_search_words *words; - GPtrArray *list = g_ptr_array_new(); - guint32 c; - int inquote = 0; - - words = g_malloc0(sizeof(*words)); - w = g_string_new(""); - - do { - c = camel_utf8_getc(&in); - - if (c == 0 - || (inquote && c == '"') - || (!inquote && g_unichar_isspace(c))) { - output_w(w, list, type); - all |= type; - type = CAMEL_SEARCH_WORD_SIMPLE; - inquote = 0; - } else { - if (c == '\\') { - c = camel_utf8_getc(&in); - if (c) - output_c(w, c, &type); - else { - output_w(w, list, type); - all |= type; - } - } else if (c == '\"') { - inquote = 1; - } else { - output_c(w, c, &type); - } - } - } while (c); - - g_string_free(w, TRUE); - words->len = list->len; - words->words = (struct _camel_search_word **)list->pdata; - words->type = all; - g_ptr_array_free(list, FALSE); - - return words; -} - -/* takes an existing 'words' list, and converts it to another consisting of - only simple words, with any punctuation etc stripped */ -struct _camel_search_words * -camel_search_words_simple(struct _camel_search_words *wordin) -{ - int i; - const unsigned char *ptr, *start, *last; - int type = CAMEL_SEARCH_WORD_SIMPLE, all = 0; - GPtrArray *list = g_ptr_array_new(); - struct _camel_search_word *word; - struct _camel_search_words *words; - guint32 c; - - words = g_malloc0(sizeof(*words)); - - for (i=0;ilen;i++) { - if ((wordin->words[i]->type & CAMEL_SEARCH_WORD_COMPLEX) == 0) { - word = g_malloc0(sizeof(*word)); - word->type = wordin->words[i]->type; - word->word = g_strdup(wordin->words[i]->word); - g_ptr_array_add(list, word); - } else { - ptr = wordin->words[i]->word; - start = last = ptr; - do { - c = camel_utf8_getc(&ptr); - if (c == 0 || !g_unichar_isalnum(c)) { - if (last > start) { - word = g_malloc0(sizeof(*word)); - word->word = g_strndup(start, last-start); - word->type = type; - g_ptr_array_add(list, word); - all |= type; - type = CAMEL_SEARCH_WORD_SIMPLE; - } - start = ptr; - } - if (c > 0x80) - type = CAMEL_SEARCH_WORD_8BIT; - last = ptr; - } while (c); - } - } - - words->len = list->len; - words->words = (struct _camel_search_word **)list->pdata; - words->type = all; - g_ptr_array_free(list, FALSE); - - return words; -} - -void -camel_search_words_free(struct _camel_search_words *words) -{ - int i; - - for (i=0;ilen;i++) { - struct _camel_search_word *word = words->words[i]; - - g_free(word->word); - g_free(word); - } - g_free(words->words); - g_free(words); -} - diff --git a/camel/camel-search-private.h b/camel/camel-search-private.h deleted file mode 100644 index 8e83f7aed3..0000000000 --- a/camel/camel-search-private.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2001 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_SEARCH_PRIVATE_H -#define _CAMEL_SEARCH_PRIVATE_H - -#include - -typedef enum { - CAMEL_SEARCH_MATCH_START = 1<<0, - CAMEL_SEARCH_MATCH_END = 1<<1, - CAMEL_SEARCH_MATCH_REGEX = 1<<2, /* disables the first 2 */ - CAMEL_SEARCH_MATCH_ICASE = 1<<3, - CAMEL_SEARCH_MATCH_NEWLINE = 1<<4, -} camel_search_flags_t; - -typedef enum { - CAMEL_SEARCH_MATCH_EXACT, - CAMEL_SEARCH_MATCH_CONTAINS, - CAMEL_SEARCH_MATCH_STARTS, - CAMEL_SEARCH_MATCH_ENDS, - CAMEL_SEARCH_MATCH_SOUNDEX, -} camel_search_match_t; - -typedef enum { - CAMEL_SEARCH_TYPE_ASIS, - CAMEL_SEARCH_TYPE_ENCODED, - CAMEL_SEARCH_TYPE_ADDRESS, - CAMEL_SEARCH_TYPE_ADDRESS_ENCODED, - CAMEL_SEARCH_TYPE_MLIST, /* its a mailing list pseudo-header */ -} camel_search_t; - -/* builds a regex that represents a string search */ -int camel_search_build_match_regex(regex_t *pattern, camel_search_flags_t type, int argc, struct _ESExpResult **argv, CamelException *ex); -gboolean camel_search_message_body_contains(CamelDataWrapper *object, regex_t *pattern); - -gboolean camel_search_header_match(const char *value, const char *match, camel_search_match_t how, camel_search_t type, const char *default_charset); -gboolean camel_search_camel_header_soundex(const char *header, const char *match); - -/* TODO: replace with a real search function */ -const char *camel_ustrstrcase(const char *haystack, const char *needle); - -/* Some crappy utility functions for handling multiple search words */ -enum _camel_search_word_t { - CAMEL_SEARCH_WORD_SIMPLE = 1, - CAMEL_SEARCH_WORD_COMPLEX = 2, - CAMEL_SEARCH_WORD_8BIT = 4, -}; -struct _camel_search_word { - enum _camel_search_word_t type; - char *word; -}; - -struct _camel_search_words { - int len; - enum _camel_search_word_t type; /* OR of all word types in list */ - struct _camel_search_word **words; -}; - -struct _camel_search_words *camel_search_words_split(const unsigned char *in); -struct _camel_search_words *camel_search_words_simple(struct _camel_search_words *wordin); -void camel_search_words_free(struct _camel_search_words *); - -#endif /* ! _CAMEL_SEARCH_PRIVATE_H */ - diff --git a/camel/camel-seekable-stream.c b/camel/camel-seekable-stream.c deleted file mode 100644 index 874d68e40c..0000000000 --- a/camel/camel-seekable-stream.c +++ /dev/null @@ -1,202 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * Author: - * Bertrand Guiheneuf - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "camel-seekable-stream.h" - -static CamelStreamClass *parent_class = NULL; - -/* Returns the class for a CamelSeekableStream */ -#define CSS_CLASS(so) CAMEL_SEEKABLE_STREAM_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static off_t seek (CamelSeekableStream *stream, off_t offset, - CamelStreamSeekPolicy policy); -static off_t stream_tell (CamelSeekableStream *stream); -static int reset (CamelStream *stream); -static int set_bounds (CamelSeekableStream *stream, off_t start, off_t end); - -static void -camel_seekable_stream_class_init (CamelSeekableStreamClass *camel_seekable_stream_class) -{ - CamelStreamClass *camel_stream_class = - CAMEL_STREAM_CLASS (camel_seekable_stream_class); - - parent_class = CAMEL_STREAM_CLASS( camel_type_get_global_classfuncs( CAMEL_STREAM_TYPE ) ); - - /* seekable stream methods */ - camel_seekable_stream_class->seek = seek; - camel_seekable_stream_class->tell = stream_tell; - camel_seekable_stream_class->set_bounds = set_bounds; - - /* camel stream methods overload */ - camel_stream_class->reset = reset; -} - -static void -camel_seekable_stream_init (void *o) -{ - CamelSeekableStream *stream = (CamelSeekableStream *)o; - - stream->bound_start = 0; - stream->bound_end = CAMEL_STREAM_UNBOUND; -} - -CamelType -camel_seekable_stream_get_type (void) -{ - static CamelType camel_seekable_stream_type = CAMEL_INVALID_TYPE; - - if (camel_seekable_stream_type == CAMEL_INVALID_TYPE) { - camel_seekable_stream_type = camel_type_register( CAMEL_STREAM_TYPE, - "CamelSeekableStream", - sizeof( CamelSeekableStream ), - sizeof( CamelSeekableStreamClass ), - (CamelObjectClassInitFunc) camel_seekable_stream_class_init, - NULL, - (CamelObjectInitFunc) camel_seekable_stream_init, - NULL ); - } - - return camel_seekable_stream_type; -} - - -static off_t -seek (CamelSeekableStream *stream, off_t offset, - CamelStreamSeekPolicy policy) -{ - g_warning ("CamelSeekableStream::seek called on default " - "implementation\n"); - return -1; -} - -/** - * camel_stream_seek: - * @stream: a CamelStream object. - * @offset: offset value - * @policy: what to do with the offset - * - * Seek to the specified position in @stream. - * - * If @policy is CAMEL_STREAM_SET, seeks to @offset. - * - * If @policy is CAMEL_STREAM_CUR, seeks to the current position plus - * @offset. - * - * If @policy is CAMEL_STREAM_END, seeks to the end of the stream plus - * @offset. - * - * Regardless of @policy, the stream's final position will be clamped - * to the range specified by its lower and upper bounds, and the - * stream's eos state will be updated. - * - * Return value: new position, -1 if operation failed. - **/ -off_t -camel_seekable_stream_seek (CamelSeekableStream *stream, off_t offset, - CamelStreamSeekPolicy policy) -{ - g_return_val_if_fail (CAMEL_IS_SEEKABLE_STREAM (stream), -1); - - return CSS_CLASS (stream)->seek (stream, offset, policy); -} - - -static off_t -stream_tell (CamelSeekableStream *stream) -{ - return stream->position; -} - -/** - * camel_seekable_stream_tell: - * @stream: seekable stream object - * - * Get the current position of a seekable stream. - * - * Return value: the position. - **/ -off_t -camel_seekable_stream_tell (CamelSeekableStream *stream) -{ - g_return_val_if_fail (CAMEL_IS_SEEKABLE_STREAM (stream), -1); - - return CSS_CLASS (stream)->tell (stream); -} - -static int -set_bounds (CamelSeekableStream *stream, off_t start, off_t end) -{ - /* store the bounds */ - stream->bound_start = start; - stream->bound_end = end; - - if (start > stream->position) - return camel_seekable_stream_seek (stream, start, CAMEL_STREAM_SET); - - return 0; -} - -/** - * camel_seekable_stream_set_bounds: - * @stream: a seekable stream - * @start: the first valid position - * @end: the first invalid position, or CAMEL_STREAM_UNBOUND - * - * Set the range of valid data this stream is allowed to cover. If - * there is to be no @end value, then @end should be set to - * #CAMEL_STREAM_UNBOUND. - * - * Return value: -1 on error. - **/ -int -camel_seekable_stream_set_bounds (CamelSeekableStream *stream, - off_t start, off_t end) -{ - g_return_val_if_fail (CAMEL_IS_SEEKABLE_STREAM (stream), -1); - g_return_val_if_fail (end == CAMEL_STREAM_UNBOUND || end >= start, -1); - - return CSS_CLASS (stream)->set_bounds (stream, start, end); -} - -/* a default implementation of reset for seekable streams */ -static int -reset (CamelStream *stream) -{ - CamelSeekableStream *seekable_stream; - - seekable_stream = CAMEL_SEEKABLE_STREAM (stream); - - return camel_seekable_stream_seek (seekable_stream, - seekable_stream->bound_start, - CAMEL_STREAM_SET); -} - - - - - - diff --git a/camel/camel-seekable-stream.h b/camel/camel-seekable-stream.h deleted file mode 100644 index 9ac73c7ee8..0000000000 --- a/camel/camel-seekable-stream.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-stream-fs.h :stream based on unix filesystem */ - -/* - * Author: - * Bertrand Guiheneuf - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_SEEKABLE_STREAM_H -#define CAMEL_SEEKABLE_STREAM_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include -#include - -#define CAMEL_SEEKABLE_STREAM_TYPE (camel_seekable_stream_get_type ()) -#define CAMEL_SEEKABLE_STREAM(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SEEKABLE_STREAM_TYPE, CamelSeekableStream)) -#define CAMEL_SEEKABLE_STREAM_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SEEKABLE_STREAM_TYPE, CamelSeekableStreamClass)) -#define CAMEL_IS_SEEKABLE_STREAM(o) (CAMEL_CHECK_TYPE((o), CAMEL_SEEKABLE_STREAM_TYPE)) - - -typedef enum -{ - CAMEL_STREAM_SET = SEEK_SET, - CAMEL_STREAM_CUR = SEEK_CUR, - CAMEL_STREAM_END = SEEK_END -} CamelStreamSeekPolicy; - -#define CAMEL_STREAM_UNBOUND (~0) - -struct _CamelSeekableStream -{ - CamelStream parent_object; - - off_t position; /* current postion in the stream */ - off_t bound_start; /* first valid position */ - off_t bound_end; /* first invalid position */ -}; - -typedef struct { - CamelStreamClass parent_class; - - /* Virtual methods */ - off_t (*seek) (CamelSeekableStream *stream, off_t offset, - CamelStreamSeekPolicy policy); - off_t (*tell) (CamelSeekableStream *stream); - int (*set_bounds) (CamelSeekableStream *stream, - off_t start, off_t end); -} CamelSeekableStreamClass; - -/* Standard Camel function */ -CamelType camel_seekable_stream_get_type (void); - -/* public methods */ -off_t camel_seekable_stream_seek (CamelSeekableStream *stream, off_t offset, - CamelStreamSeekPolicy policy); -off_t camel_seekable_stream_tell (CamelSeekableStream *stream); -int camel_seekable_stream_set_bounds (CamelSeekableStream *, off_t start, off_t end); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SEEKABLE_STREAM_H */ diff --git a/camel/camel-seekable-substream.c b/camel/camel-seekable-substream.c deleted file mode 100644 index e92f4e0549..0000000000 --- a/camel/camel-seekable-substream.c +++ /dev/null @@ -1,302 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-stream-fs.c : file system based stream - * - * Authors: Bertrand Guiheneuf - * Michael Zucchi - * - * Copyright 1999-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "camel-seekable-substream.h" - -static CamelSeekableStreamClass *parent_class = NULL; - -/* Returns the class for a CamelSeekableSubStream */ -#define CSS_CLASS(so) CAMEL_SEEKABLE_SUBSTREAM_CLASS (CAMEL_OBJECT(so)->klass) - -static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n); -static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n); -static int stream_flush (CamelStream *stream); -static int stream_close (CamelStream *stream); -static gboolean eos (CamelStream *stream); -static off_t stream_seek (CamelSeekableStream *stream, off_t offset, - CamelStreamSeekPolicy policy); - -static void -camel_seekable_substream_class_init (CamelSeekableSubstreamClass *camel_seekable_substream_class) -{ - CamelSeekableStreamClass *camel_seekable_stream_class = - CAMEL_SEEKABLE_STREAM_CLASS (camel_seekable_substream_class); - CamelStreamClass *camel_stream_class = - CAMEL_STREAM_CLASS (camel_seekable_substream_class); - - parent_class = CAMEL_SEEKABLE_STREAM_CLASS (camel_type_get_global_classfuncs (camel_seekable_stream_get_type ())); - - /* virtual method definition */ - - /* virtual method overload */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->flush = stream_flush; - camel_stream_class->close = stream_close; - camel_stream_class->eos = eos; - - camel_seekable_stream_class->seek = stream_seek; - -} - -static void -camel_seekable_substream_finalize (CamelObject *object) -{ - CamelSeekableSubstream *seekable_substream = - CAMEL_SEEKABLE_SUBSTREAM (object); - - if (seekable_substream->parent_stream) - camel_object_unref (seekable_substream->parent_stream); -} - - -CamelType -camel_seekable_substream_get_type (void) -{ - static CamelType camel_seekable_substream_type = CAMEL_INVALID_TYPE; - - if (camel_seekable_substream_type == CAMEL_INVALID_TYPE) { - camel_seekable_substream_type = camel_type_register (camel_seekable_stream_get_type (), "CamelSeekableSubstream", - sizeof (CamelSeekableSubstream), - sizeof (CamelSeekableSubstreamClass), - (CamelObjectClassInitFunc) camel_seekable_substream_class_init, - NULL, - NULL, - (CamelObjectFinalizeFunc) camel_seekable_substream_finalize); - } - - return camel_seekable_substream_type; -} - -/** - * camel_seekable_substream_new: - * @parent_stream: a seekable parent stream - * @inf_bound: a lower bound - * @sup_bound: an upper bound - * - * Creates a new CamelSeekableSubstream that references the portion - * of @parent_stream from @inf_bound to @sup_bound. (If @sup_bound is - * #CAMEL_STREAM_UNBOUND, it references to the end of stream, even if - * the stream grows.) - * - * While the substream is open, the caller cannot assume anything about - * the current position of @parent_stream. After the substream has been - * closed, @parent_stream will stabilize again. - * - * Return value: the substream - **/ -CamelStream * -camel_seekable_substream_new(CamelSeekableStream *parent_stream, off_t start, off_t end) -{ - CamelSeekableSubstream *seekable_substream; - - g_return_val_if_fail (CAMEL_IS_SEEKABLE_STREAM (parent_stream), NULL); - - /* Create the seekable substream. */ - seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (camel_object_new (camel_seekable_substream_get_type ())); - - /* Initialize it. */ - seekable_substream->parent_stream = parent_stream; - camel_object_ref (parent_stream); - - /* Set the bound of the substream. We can ignore any possible error - * here, because if we fail to seek now, it will try again later. - */ - camel_seekable_stream_set_bounds ((CamelSeekableStream *)seekable_substream, start, end); - - return CAMEL_STREAM (seekable_substream); -} - -static gboolean -parent_reset (CamelSeekableSubstream *seekable_substream, CamelSeekableStream *parent) -{ - CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (seekable_substream); - - if (camel_seekable_stream_tell (parent) == seekable_stream->position) - return TRUE; - - return camel_seekable_stream_seek (parent, seekable_stream->position, CAMEL_STREAM_SET) == seekable_stream->position; -} - -static ssize_t -stream_read (CamelStream *stream, char *buffer, size_t n) -{ - CamelSeekableStream *parent; - CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (stream); - CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (stream); - ssize_t v; - - if (n == 0) - return 0; - - parent = seekable_substream->parent_stream; - - /* Go to our position in the parent stream. */ - if (!parent_reset (seekable_substream, parent)) { - stream->eos = TRUE; - return 0; - } - - /* Compute how many bytes should be read. */ - if (seekable_stream->bound_end != CAMEL_STREAM_UNBOUND) - n = MIN (seekable_stream->bound_end - seekable_stream->position, n); - - if (n == 0) { - stream->eos = TRUE; - return 0; - } - - v = camel_stream_read (CAMEL_STREAM (parent), buffer, n); - - /* ignore <0 - it's an error, let the caller deal */ - if (v > 0) - seekable_stream->position += v; - - return v; -} - -static ssize_t -stream_write (CamelStream *stream, const char *buffer, size_t n) -{ - CamelSeekableStream *parent; - CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM(stream); - CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM(stream); - ssize_t v; - - if (n == 0) - return 0; - - parent = seekable_substream->parent_stream; - - /* Go to our position in the parent stream. */ - if (!parent_reset (seekable_substream, parent)) { - stream->eos = TRUE; - return 0; - } - - /* Compute how many bytes should be written. */ - if (seekable_stream->bound_end != CAMEL_STREAM_UNBOUND) - n = MIN (seekable_stream->bound_end - seekable_stream->position, n); - - if (n == 0) { - stream->eos = TRUE; - return 0; - } - - v = camel_stream_write((CamelStream *)parent, buffer, n); - - /* ignore <0 - it's an error, let the caller deal */ - if (v > 0) - seekable_stream->position += v; - - return v; - -} - -static int -stream_flush (CamelStream *stream) -{ - CamelSeekableSubstream *sus = (CamelSeekableSubstream *)stream; - - return camel_stream_flush(CAMEL_STREAM(sus->parent_stream)); -} - -static int -stream_close (CamelStream *stream) -{ - /* we dont really want to close the substream ... */ - return 0; -} - -static gboolean -eos (CamelStream *stream) -{ - CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM(stream); - CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM(stream); - CamelSeekableStream *parent; - gboolean eos; - - if (stream->eos) - eos = TRUE; - else { - parent = seekable_substream->parent_stream; - if (!parent_reset (seekable_substream, parent)) - return TRUE; - - eos = camel_stream_eos (CAMEL_STREAM (parent)); - if (!eos && (seekable_stream->bound_end != CAMEL_STREAM_UNBOUND)) { - eos = seekable_stream->position >= seekable_stream->bound_end; - } - } - - return eos; -} - -static off_t -stream_seek (CamelSeekableStream *seekable_stream, off_t offset, - CamelStreamSeekPolicy policy) -{ - CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM(seekable_stream); - CamelStream *stream = CAMEL_STREAM(seekable_stream); - off_t real_offset = 0; - - stream->eos = FALSE; - - switch (policy) { - case CAMEL_STREAM_SET: - real_offset = offset; - break; - - case CAMEL_STREAM_CUR: - real_offset = seekable_stream->position + offset; - break; - - case CAMEL_STREAM_END: - if (seekable_stream->bound_end == CAMEL_STREAM_UNBOUND) { - real_offset = camel_seekable_stream_seek(seekable_substream->parent_stream, - offset, - CAMEL_STREAM_END); - if (real_offset != -1) { - if (real_offsetbound_start) - real_offset = seekable_stream->bound_start; - seekable_stream->position = real_offset; - } - return real_offset; - } - real_offset = seekable_stream->bound_end + offset; - break; - } - - if (seekable_stream->bound_end != CAMEL_STREAM_UNBOUND) - real_offset = MIN (real_offset, seekable_stream->bound_end); - - if (real_offsetbound_start) - real_offset = seekable_stream->bound_start; - - seekable_stream->position = real_offset; - return real_offset; -} diff --git a/camel/camel-seekable-substream.h b/camel/camel-seekable-substream.h deleted file mode 100644 index b500944298..0000000000 --- a/camel/camel-seekable-substream.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-seekable-substream.h: stream that piggybacks on another stream */ - -/* - * Author: - * Bertrand Guiheneuf - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_SEEKABLE_SUBSTREAM_H -#define CAMEL_SEEKABLE_SUBSTREAM_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include - -#define CAMEL_SEEKABLE_SUBSTREAM_TYPE (camel_seekable_substream_get_type ()) -#define CAMEL_SEEKABLE_SUBSTREAM(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SEEKABLE_SUBSTREAM_TYPE, CamelSeekableSubstream)) -#define CAMEL_SEEKABLE_SUBSTREAM_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SEEKABLE_SUBSTREAM_TYPE, CamelSeekableSubstreamClass)) -#define CAMEL_IS_SEEKABLE_SUBSTREAM(o) (CAMEL_CHECK_TYPE((o), CAMEL_SEEKABLE_SUBSTREAM_TYPE)) - -struct _CamelSeekableSubstream -{ - CamelSeekableStream parent_object; - - /* --**-- Private fields --**-- */ - CamelSeekableStream *parent_stream; -}; - -typedef struct { - CamelSeekableStreamClass parent_class; - -} CamelSeekableSubstreamClass; - -/* Standard Camel function */ -CamelType camel_seekable_substream_get_type (void); - -/* public methods */ - -/* obtain a new seekable substream */ -CamelStream * -camel_seekable_substream_new(CamelSeekableStream *parent_stream, off_t start, off_t end); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SEEKABLE_SUBSTREAM_H */ diff --git a/camel/camel-service.c b/camel/camel-service.c deleted file mode 100644 index cd66bb9cb1..0000000000 --- a/camel/camel-service.c +++ /dev/null @@ -1,958 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-service.c : Abstract class for an email service */ - -/* - * - * Author : - * Bertrand Guiheneuf - * - * Copyright 1999-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "e-util/e-msgport.h" - -#include "e-util/e-host-utils.h" - -#include "camel-service.h" -#include "camel-session.h" -#include "camel-exception.h" -#include "camel-operation.h" -#include "camel-private.h" - -#define d(x) -#define w(x) - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelService */ -#define CSERV_CLASS(so) CAMEL_SERVICE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static void construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex); -static gboolean service_connect(CamelService *service, CamelException *ex); -static gboolean service_disconnect(CamelService *service, gboolean clean, - CamelException *ex); -static void cancel_connect (CamelService *service); -static GList *query_auth_types (CamelService *service, CamelException *ex); -static char *get_name (CamelService *service, gboolean brief); -static char *get_path (CamelService *service); - -static int service_setv (CamelObject *object, CamelException *ex, CamelArgV *args); -static int service_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args); - - -static void -camel_service_class_init (CamelServiceClass *camel_service_class) -{ - CamelObjectClass *object_class = CAMEL_OBJECT_CLASS (camel_service_class); - - parent_class = camel_type_get_global_classfuncs (CAMEL_OBJECT_TYPE); - - /* virtual method overloading */ - object_class->setv = service_setv; - object_class->getv = service_getv; - - /* virtual method definition */ - camel_service_class->construct = construct; - camel_service_class->connect = service_connect; - camel_service_class->disconnect = service_disconnect; - camel_service_class->cancel_connect = cancel_connect; - camel_service_class->query_auth_types = query_auth_types; - camel_service_class->get_name = get_name; - camel_service_class->get_path = get_path; -} - -static void -camel_service_init (void *o, void *k) -{ - CamelService *service = o; - - service->priv = g_malloc0(sizeof(*service->priv)); - service->priv->connect_lock = e_mutex_new(E_MUTEX_REC); - service->priv->connect_op_lock = e_mutex_new(E_MUTEX_SIMPLE); -} - -static void -camel_service_finalize (CamelObject *object) -{ - CamelService *service = CAMEL_SERVICE (object); - - if (service->status == CAMEL_SERVICE_CONNECTED) { - CamelException ex; - - camel_exception_init (&ex); - CSERV_CLASS (service)->disconnect (service, TRUE, &ex); - if (camel_exception_is_set (&ex)) { - w(g_warning ("camel_service_finalize: silent disconnect failure: %s", - camel_exception_get_description (&ex))); - } - camel_exception_clear (&ex); - } - - if (service->url) - camel_url_free (service->url); - if (service->session) - camel_object_unref (service->session); - - e_mutex_destroy (service->priv->connect_lock); - e_mutex_destroy (service->priv->connect_op_lock); - - g_free (service->priv); -} - - - -CamelType -camel_service_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = - camel_type_register (CAMEL_OBJECT_TYPE, - "CamelService", - sizeof (CamelService), - sizeof (CamelServiceClass), - (CamelObjectClassInitFunc) camel_service_class_init, - NULL, - (CamelObjectInitFunc) camel_service_init, - camel_service_finalize ); - } - - return type; -} - - -static int -service_setv (CamelObject *object, CamelException *ex, CamelArgV *args) -{ - CamelService *service = (CamelService *) object; - CamelURL *url = service->url; - gboolean reconnect = FALSE; - guint32 tag; - int i; - - for (i = 0; i < args->argc; i++) { - tag = args->argv[i].tag; - - /* make sure this arg wasn't already handled */ - if (tag & CAMEL_ARG_IGNORE) - continue; - - /* make sure this is an arg we're supposed to handle */ - if ((tag & CAMEL_ARG_TAG) <= CAMEL_SERVICE_ARG_FIRST || - (tag & CAMEL_ARG_TAG) >= CAMEL_SERVICE_ARG_FIRST + 100) - continue; - - if (tag == CAMEL_SERVICE_USERNAME) { - /* set the username */ - if (strcmp (url->user, args->argv[i].ca_str) != 0) { - camel_url_set_user (url, args->argv[i].ca_str); - reconnect = TRUE; - } - } else if (tag == CAMEL_SERVICE_AUTH) { - /* set the auth mechanism */ - if (strcmp (url->authmech, args->argv[i].ca_str) != 0) { - camel_url_set_authmech (url, args->argv[i].ca_str); - reconnect = TRUE; - } - } else if (tag == CAMEL_SERVICE_HOSTNAME) { - /* set the hostname */ - if (strcmp (url->host, args->argv[i].ca_str) != 0) { - camel_url_set_host (url, args->argv[i].ca_str); - reconnect = TRUE; - } - } else if (tag == CAMEL_SERVICE_PORT) { - /* set the port */ - if (url->port != args->argv[i].ca_int) { - camel_url_set_port (url, args->argv[i].ca_int); - reconnect = TRUE; - } - } else if (tag == CAMEL_SERVICE_PATH) { - /* set the path */ - if (strcmp (url->path, args->argv[i].ca_str) != 0) { - camel_url_set_host (url, args->argv[i].ca_str); - reconnect = TRUE; - } - } else { - /* error? */ - continue; - } - - /* let our parent know that we've handled this arg */ - camel_argv_ignore (args, i); - } - - /* FIXME: what if we are in the process of connecting? */ - if (reconnect && service->status == CAMEL_SERVICE_CONNECTED) { - /* reconnect the service using the new URL */ - if (camel_service_disconnect (service, TRUE, ex)) - camel_service_connect (service, ex); - } - - return CAMEL_OBJECT_CLASS (parent_class)->setv (object, ex, args); -} - -static int -service_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args) -{ - CamelService *service = (CamelService *) object; - CamelURL *url = service->url; - guint32 tag; - int i; - - for (i = 0; i < args->argc; i++) { - tag = args->argv[i].tag; - - /* make sure this is an arg we're supposed to handle */ - if ((tag & CAMEL_ARG_TAG) <= CAMEL_SERVICE_ARG_FIRST || - (tag & CAMEL_ARG_TAG) >= CAMEL_SERVICE_ARG_FIRST + 100) - continue; - - switch (tag) { - case CAMEL_SERVICE_USERNAME: - /* get the username */ - *args->argv[i].ca_str = url->user; - break; - case CAMEL_SERVICE_AUTH: - /* get the auth mechanism */ - *args->argv[i].ca_str = url->authmech; - break; - case CAMEL_SERVICE_HOSTNAME: - /* get the hostname */ - *args->argv[i].ca_str = url->host; - break; - case CAMEL_SERVICE_PORT: - /* get the port */ - *args->argv[i].ca_int = url->port; - break; - case CAMEL_SERVICE_PATH: - /* get the path */ - *args->argv[i].ca_str = url->path; - break; - default: - /* error? */ - break; - } - } - - return CAMEL_OBJECT_CLASS (parent_class)->getv (object, ex, args); -} - -static void -construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, CamelException *ex) -{ - char *url_string; - - if (CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_USER) && - (url->user == NULL || url->user[0] == '\0')) { - url_string = camel_url_to_string (url, CAMEL_URL_HIDE_PASSWORD); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID, - _("URL '%s' needs a username component"), - url_string); - g_free (url_string); - return; - } else if (CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_HOST) && - (url->host == NULL || url->host[0] == '\0')) { - url_string = camel_url_to_string (url, CAMEL_URL_HIDE_PASSWORD); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID, - _("URL '%s' needs a host component"), - url_string); - g_free (url_string); - return; - } else if (CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_PATH) && - (url->path == NULL || url->path[0] == '\0')) { - url_string = camel_url_to_string (url, CAMEL_URL_HIDE_PASSWORD); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID, - _("URL '%s' needs a path component"), - url_string); - g_free (url_string); - return; - } - - service->provider = provider; - service->url = url; - service->session = session; - camel_object_ref (session); - - service->status = CAMEL_SERVICE_DISCONNECTED; -} - -/** - * camel_service_construct: - * @service: the CamelService - * @session: the session for the service - * @provider: the service's provider - * @url: the default URL for the service (may be NULL) - * @ex: a CamelException - * - * Constructs a CamelService initialized with the given parameters. - **/ -void -camel_service_construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex) -{ - g_return_if_fail (CAMEL_IS_SERVICE (service)); - g_return_if_fail (CAMEL_IS_SESSION (session)); - - CSERV_CLASS (service)->construct (service, session, provider, url, ex); -} - - -static gboolean -service_connect (CamelService *service, CamelException *ex) -{ - /* Things like the CamelMboxStore can validly - * not define a connect function. - */ - return TRUE; -} - -/** - * camel_service_connect: - * @service: CamelService object - * @ex: a CamelException - * - * Connect to the service using the parameters it was initialized - * with. - * - * Return value: whether or not the connection succeeded - **/ - -gboolean -camel_service_connect (CamelService *service, CamelException *ex) -{ - gboolean ret = FALSE; - gboolean unreg = FALSE; - - g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE); - g_return_val_if_fail (service->session != NULL, FALSE); - g_return_val_if_fail (service->url != NULL, FALSE); - - CAMEL_SERVICE_LOCK (service, connect_lock); - - if (service->status == CAMEL_SERVICE_CONNECTED) { - CAMEL_SERVICE_UNLOCK (service, connect_lock); - return TRUE; - } - - /* Register a separate operation for connecting, so that - * the offline code can cancel it. - */ - CAMEL_SERVICE_LOCK (service, connect_op_lock); - service->connect_op = camel_operation_registered (); - if (!service->connect_op) { - service->connect_op = camel_operation_new (NULL, NULL); - camel_operation_register (service->connect_op); - unreg = TRUE; - } - CAMEL_SERVICE_UNLOCK (service, connect_op_lock); - - service->status = CAMEL_SERVICE_CONNECTING; - ret = CSERV_CLASS (service)->connect (service, ex); - service->status = ret ? CAMEL_SERVICE_CONNECTED : CAMEL_SERVICE_DISCONNECTED; - - CAMEL_SERVICE_LOCK (service, connect_op_lock); - if (service->connect_op) { - if (unreg) - camel_operation_unregister (service->connect_op); - - camel_operation_unref (service->connect_op); - service->connect_op = NULL; - } - CAMEL_SERVICE_UNLOCK (service, connect_op_lock); - - CAMEL_SERVICE_UNLOCK (service, connect_lock); - - return ret; -} - -static gboolean -service_disconnect (CamelService *service, gboolean clean, CamelException *ex) -{ - /*service->connect_level--;*/ - - /* We let people get away with not having a disconnect - * function -- CamelMboxStore, for example. - */ - - return TRUE; -} - -/** - * camel_service_disconnect: - * @service: CamelService object - * @clean: whether or not to try to disconnect cleanly. - * @ex: a CamelException - * - * Disconnect from the service. If @clean is %FALSE, it should not - * try to do any synchronizing or other cleanup of the connection. - * - * Return value: whether or not the disconnection succeeded without - * errors. (Consult @ex if %FALSE.) - **/ -gboolean -camel_service_disconnect (CamelService *service, gboolean clean, - CamelException *ex) -{ - gboolean res = TRUE; - int unreg = FALSE; - - CAMEL_SERVICE_LOCK (service, connect_lock); - - if (service->status != CAMEL_SERVICE_DISCONNECTED - && service->status != CAMEL_SERVICE_DISCONNECTING) { - CAMEL_SERVICE_LOCK (service, connect_op_lock); - service->connect_op = camel_operation_registered (); - if (!service->connect_op) { - service->connect_op = camel_operation_new (NULL, NULL); - camel_operation_register (service->connect_op); - unreg = TRUE; - } - CAMEL_SERVICE_UNLOCK (service, connect_op_lock); - - service->status = CAMEL_SERVICE_DISCONNECTING; - res = CSERV_CLASS (service)->disconnect (service, clean, ex); - service->status = CAMEL_SERVICE_DISCONNECTED; - - CAMEL_SERVICE_LOCK (service, connect_op_lock); - if (unreg) - camel_operation_unregister (service->connect_op); - - camel_operation_unref (service->connect_op); - service->connect_op = NULL; - CAMEL_SERVICE_UNLOCK (service, connect_op_lock); - } - - CAMEL_SERVICE_UNLOCK (service, connect_lock); - - return res; -} - -static void -cancel_connect (CamelService *service) -{ - camel_operation_cancel (service->connect_op); -} - -/** - * camel_service_cancel_connect: - * @service: a service - * - * If @service is currently attempting to connect to or disconnect - * from a server, this causes it to stop and fail. Otherwise it is a - * no-op. - **/ -void -camel_service_cancel_connect (CamelService *service) -{ - CAMEL_SERVICE_LOCK (service, connect_op_lock); - if (service->connect_op) - CSERV_CLASS (service)->cancel_connect (service); - CAMEL_SERVICE_UNLOCK (service, connect_op_lock); -} - -/** - * camel_service_get_url: - * @service: a service - * - * Returns the URL representing a service. The returned URL must be - * freed when it is no longer needed. For security reasons, this - * routine does not return the password. - * - * Return value: the url name - **/ -char * -camel_service_get_url (CamelService *service) -{ - return camel_url_to_string (service->url, CAMEL_URL_HIDE_PASSWORD); -} - - -static char * -get_name (CamelService *service, gboolean brief) -{ - w(g_warning ("CamelService::get_name not implemented for `%s'", - camel_type_to_name (CAMEL_OBJECT_GET_TYPE (service)))); - return g_strdup ("???"); -} - -/** - * camel_service_get_name: - * @service: the service - * @brief: whether or not to use a briefer form - * - * This gets the name of the service in a "friendly" (suitable for - * humans) form. If @brief is %TRUE, this should be a brief description - * such as for use in the folder tree. If @brief is %FALSE, it should - * be a more complete and mostly unambiguous description. - * - * Return value: the description, which the caller must free. - **/ -char * -camel_service_get_name (CamelService *service, gboolean brief) -{ - g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL); - g_return_val_if_fail (service->url, NULL); - - return CSERV_CLASS (service)->get_name (service, brief); -} - - -static char * -get_path (CamelService *service) -{ - CamelProvider *prov = service->provider; - CamelURL *url = service->url; - GString *gpath; - char *path; - - /* A sort of ad-hoc default implementation that works for our - * current set of services. - */ - - gpath = g_string_new (service->provider->protocol); - if (CAMEL_PROVIDER_ALLOWS (prov, CAMEL_URL_PART_USER)) { - if (CAMEL_PROVIDER_ALLOWS (prov, CAMEL_URL_PART_HOST)) { - g_string_append_printf (gpath, "/%s@%s", - url->user ? url->user : "", - url->host ? url->host : ""); - - if (url->port) - g_string_append_printf (gpath, ":%d", url->port); - } else { - g_string_append_printf (gpath, "/%s%s", url->user ? url->user : "", - CAMEL_PROVIDER_NEEDS (prov, CAMEL_URL_PART_USER) ? "" : "@"); - } - } else if (CAMEL_PROVIDER_ALLOWS (prov, CAMEL_URL_PART_HOST)) { - g_string_append_printf (gpath, "/%s%s", - CAMEL_PROVIDER_NEEDS (prov, CAMEL_URL_PART_HOST) ? "" : "@", - url->host ? url->host : ""); - - if (url->port) - g_string_append_printf (gpath, ":%d", url->port); - } - - if (CAMEL_PROVIDER_NEEDS (prov, CAMEL_URL_PART_PATH)) - g_string_append_printf (gpath, "%s%s", *url->path == '/' ? "" : "/", url->path); - - path = gpath->str; - g_string_free (gpath, FALSE); - - return path; -} - -/** - * camel_service_get_path: - * @service: the service - * - * This gets a valid UNIX relative path describing the service, which - * is guaranteed to be different from the path returned for any - * different service. This path MUST start with the name of the - * provider, followed by a "/", but after that, it is up to the - * provider. - * - * Return value: the path, which the caller must free. - **/ -char * -camel_service_get_path (CamelService *service) -{ - g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL); - g_return_val_if_fail (service->url, NULL); - - return CSERV_CLASS (service)->get_path (service); -} - - -/** - * camel_service_get_session: - * @service: a service - * - * Returns the CamelSession associated with the service. - * - * Return value: the session - **/ -CamelSession * -camel_service_get_session (CamelService *service) -{ - return service->session; -} - -/** - * camel_service_get_provider: - * @service: a service - * - * Returns the CamelProvider associated with the service. - * - * Return value: the provider - **/ -CamelProvider * -camel_service_get_provider (CamelService *service) -{ - return service->provider; -} - -static GList * -query_auth_types (CamelService *service, CamelException *ex) -{ - return NULL; -} - -/** - * camel_service_query_auth_types: - * @service: a CamelService - * @ex: a CamelException - * - * This is used by the mail source wizard to get the list of - * authentication types supported by the protocol, and information - * about them. - * - * Return value: a list of CamelServiceAuthType records. The caller - * must free the list with g_list_free() when it is done with it. - **/ -GList * -camel_service_query_auth_types (CamelService *service, CamelException *ex) -{ - GList *ret; - - /* note that we get the connect lock here, which means the callee - must not call the connect functions itself */ - CAMEL_SERVICE_LOCK (service, connect_lock); - ret = CSERV_CLASS (service)->query_auth_types (service, ex); - CAMEL_SERVICE_UNLOCK (service, connect_lock); - - return ret; -} - -/* URL utility routines */ - -/** - * camel_service_gethost: - * @service: a CamelService - * @ex: a CamelException - * - * This is a convenience function to do a gethostbyname on the host - * for the service's URL. - * - * Return value: a (statically-allocated) hostent. - **/ -struct hostent * -camel_service_gethost (CamelService *service, CamelException *ex) -{ - char *hostname; - - if (service->url->host) - hostname = service->url->host; - else - hostname = "localhost"; - - return camel_gethostbyname (hostname, ex); -} - -#ifdef offsetof -#define STRUCT_OFFSET(type, field) ((gint) offsetof (type, field)) -#else -#define STRUCT_OFFSET(type, field) ((gint) ((gchar*) &((type *) 0)->field)) -#endif - -struct _lookup_msg { - EMsg msg; - unsigned int cancelled:1; - const char *name; - int len; - int type; - int result; - int herr; - struct hostent hostbuf; - int hostbuflen; - char *hostbufmem; -}; - -static void * -get_hostbyname(void *data) -{ - struct _lookup_msg *info = data; - - while ((info->result = e_gethostbyname_r(info->name, &info->hostbuf, info->hostbufmem, info->hostbuflen, &info->herr)) == ERANGE) { - d(printf("gethostbyname fialed?\n")); - pthread_testcancel(); - info->hostbuflen *= 2; - info->hostbufmem = g_realloc(info->hostbufmem, info->hostbuflen); - } - - d(printf("gethostbyname ok?\n")); - - /* If we got cancelled, dont reply, just free it */ - if (info->cancelled) { - g_free(info->hostbufmem); - g_free(info); - } else { - e_msgport_reply((EMsg *)info); - } - - return NULL; -} - -struct hostent * -camel_gethostbyname (const char *name, CamelException *exout) -{ - int fdmax, status, fd, cancel_fd; - struct _lookup_msg *msg; - CamelException ex; - - g_return_val_if_fail(name != NULL, NULL); - - if (camel_operation_cancel_check(NULL)) { - camel_exception_set (exout, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); - return NULL; - } - - camel_exception_init(&ex); - camel_operation_start_transient(NULL, _("Resolving: %s"), name); - - msg = g_malloc0(sizeof(*msg)); - msg->hostbuflen = 1024; - msg->hostbufmem = g_malloc(msg->hostbuflen); - msg->name = name; - msg->result = -1; - - cancel_fd = camel_operation_cancel_fd(NULL); - if (cancel_fd == -1) { - get_hostbyname(msg); - } else { - EMsgPort *reply_port; - pthread_t id; - fd_set rdset; - int err; - - reply_port = msg->msg.reply_port = e_msgport_new(); - fd = e_msgport_fd(msg->msg.reply_port); - if ((err = pthread_create(&id, NULL, get_hostbyname, msg)) == 0) { - d(printf("waiting for name return/cancellation in main process\n")); - do { - FD_ZERO(&rdset); - FD_SET(cancel_fd, &rdset); - FD_SET(fd, &rdset); - fdmax = MAX(fd, cancel_fd) + 1; - status = select(fdmax, &rdset, NULL, 0, NULL); - } while (status == -1 && errno == EINTR); - - if (status == -1 || FD_ISSET(cancel_fd, &rdset)) { - if (status == -1) - camel_exception_setv(&ex, CAMEL_EXCEPTION_SYSTEM, _("Failure in name lookup: %s"), g_strerror(errno)); - else - camel_exception_setv(&ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); - - /* We cancel so if the thread impl is decent it causes immediate exit. - We detach so we dont need to wait for it to exit if it isn't. - We check the reply port incase we had a reply in the mean time, which we free later */ - d(printf("Cancelling lookup thread and leaving it\n")); - msg->cancelled = 1; - pthread_detach(id); - pthread_cancel(id); - msg = (struct _lookup_msg *)e_msgport_get(reply_port); - } else { - struct _lookup_msg *reply = (struct _lookup_msg *)e_msgport_get(reply_port); - - g_assert(reply == msg); - d(printf("waiting for child to exit\n")); - pthread_join(id, NULL); - d(printf("child done\n")); - } - } else { - camel_exception_setv(&ex, CAMEL_EXCEPTION_SYSTEM, _("Host lookup failed: cannot create thread: %s"), g_strerror(err)); - } - e_msgport_destroy(reply_port); - } - - camel_operation_end(NULL); - - if (!camel_exception_is_set(&ex)) { - if (msg->result == 0) - return &msg->hostbuf; - - if (msg->herr == HOST_NOT_FOUND || msg->herr == NO_DATA) - camel_exception_setv (&ex, CAMEL_EXCEPTION_SYSTEM, - _("Host lookup failed: %s: host not found"), name); - else - camel_exception_setv (&ex, CAMEL_EXCEPTION_SYSTEM, - _("Host lookup failed: %s: unknown reason"), name); - } - - if (msg) { - g_free(msg->hostbufmem); - g_free(msg); - } - - camel_exception_xfer(exout, &ex); - - return NULL; -} - -static void * -get_hostbyaddr (void *data) -{ - struct _lookup_msg *info = data; - - while ((info->result = e_gethostbyaddr_r (info->name, info->len, info->type, &info->hostbuf, - info->hostbufmem, info->hostbuflen, &info->herr)) == ERANGE) { - d(printf ("gethostbyaddr fialed?\n")); - pthread_testcancel (); - info->hostbuflen *= 2; - info->hostbufmem = g_realloc (info->hostbufmem, info->hostbuflen); - } - - d(printf ("gethostbyaddr ok?\n")); - - if (info->cancelled) { - g_free(info->hostbufmem); - g_free(info); - } else { - e_msgport_reply((EMsg *)info); - } - - return NULL; -} - - -struct hostent * -camel_gethostbyaddr (const char *addr, int len, int type, CamelException *exout) -{ - int fdmax, status, fd, cancel_fd; - struct _lookup_msg *msg; - CamelException ex; - - g_return_val_if_fail (addr != NULL, NULL); - - if (camel_operation_cancel_check (NULL)) { - camel_exception_set (exout, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); - return NULL; - } - - camel_exception_init(&ex); - camel_operation_start_transient (NULL, _("Resolving address")); - - msg = g_malloc0 (sizeof (struct _lookup_msg)); - msg->hostbuflen = 1024; - msg->hostbufmem = g_malloc (msg->hostbuflen); - msg->name = addr; - msg->len = len; - msg->type = type; - msg->result = -1; - - cancel_fd = camel_operation_cancel_fd (NULL); - if (cancel_fd == -1) { - get_hostbyaddr (msg); - } else { - EMsgPort *reply_port; - pthread_t id; - fd_set rdset; - int err; - - reply_port = msg->msg.reply_port = e_msgport_new (); - fd = e_msgport_fd (msg->msg.reply_port); - if ((err = pthread_create (&id, NULL, get_hostbyaddr, msg)) == 0) { - d(printf("waiting for name return/cancellation in main process\n")); - do { - FD_ZERO(&rdset); - FD_SET(cancel_fd, &rdset); - FD_SET(fd, &rdset); - fdmax = MAX(fd, cancel_fd) + 1; - status = select (fdmax, &rdset, NULL, 0, NULL); - } while (status == -1 && errno == EINTR); - - if (status == -1 || FD_ISSET(cancel_fd, &rdset)) { - if (status == -1) - camel_exception_setv(&ex, CAMEL_EXCEPTION_SYSTEM, _("Failure in name lookup: %s"), g_strerror(errno)); - else - camel_exception_setv(&ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); - - /* We cancel so if the thread impl is decent it causes immediate exit. - We detach so we dont need to wait for it to exit if it isn't. - We check the reply port incase we had a reply in the mean time, which we free later */ - d(printf("Cancelling lookup thread and leaving it\n")); - msg->cancelled = 1; - pthread_detach(id); - pthread_cancel(id); - msg = (struct _lookup_msg *)e_msgport_get(reply_port); - } else { - struct _lookup_msg *reply = (struct _lookup_msg *)e_msgport_get(reply_port); - - g_assert(reply == msg); - d(printf("waiting for child to exit\n")); - pthread_join(id, NULL); - d(printf("child done\n")); - } - } else { - camel_exception_setv(&ex, CAMEL_EXCEPTION_SYSTEM, _("Host lookup failed: cannot create thread: %s"), g_strerror(err)); - } - - - e_msgport_destroy (reply_port); - } - - camel_operation_end (NULL); - - if (!camel_exception_is_set(&ex)) { - if (msg->result == 0) - return &msg->hostbuf; - - if (msg->herr == HOST_NOT_FOUND || msg->herr == NO_DATA) - camel_exception_setv (&ex, CAMEL_EXCEPTION_SYSTEM, - _("Host lookup failed: host not found")); - else - camel_exception_setv (&ex, CAMEL_EXCEPTION_SYSTEM, - _("Host lookup failed: unknown reason")); - } - - if (msg) { - g_free(msg->hostbufmem); - g_free(msg); - } - - camel_exception_xfer(exout, &ex); - - return NULL; -} - -void camel_free_host(struct hostent *h) -{ - struct _lookup_msg *msg; - - g_return_if_fail(h != NULL); - - /* yeah this looks ugly but it is safe. we passed out a reference to inside our structure, this maps it - to the base structure, so we can free everything right without having to keep track of it separately */ - msg = (struct _lookup_msg *)(((char *)h) - STRUCT_OFFSET(struct _lookup_msg, hostbuf)); - - g_free(msg->hostbufmem); - g_free(msg); -} diff --git a/camel/camel-service.h b/camel/camel-service.h deleted file mode 100644 index 587749e242..0000000000 --- a/camel/camel-service.h +++ /dev/null @@ -1,155 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-service.h : Abstract class for an email service */ - -/* - * - * Author : - * Bertrand Guiheneuf - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_SERVICE_H -#define CAMEL_SERVICE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include -#include -#include -#include - -#define CAMEL_SERVICE_TYPE (camel_service_get_type ()) -#define CAMEL_SERVICE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SERVICE_TYPE, CamelService)) -#define CAMEL_SERVICE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SERVICE_TYPE, CamelServiceClass)) -#define CAMEL_IS_SERVICE(o) (CAMEL_CHECK_TYPE((o), CAMEL_SERVICE_TYPE)) - -enum { - CAMEL_SERVICE_ARG_FIRST = CAMEL_ARG_FIRST + 100, - CAMEL_SERVICE_ARG_USERNAME, - CAMEL_SERVICE_ARG_AUTH, - CAMEL_SERVICE_ARG_HOSTNAME, - CAMEL_SERVICE_ARG_PORT, - CAMEL_SERVICE_ARG_PATH, -}; - -#define CAMEL_SERVICE_USERNAME (CAMEL_SERVICE_ARG_USERNAME | CAMEL_ARG_STR) -#define CAMEL_SERVICE_AUTH (CAMEL_SERVICE_ARG_AUTH | CAMEL_ARG_STR) -#define CAMEL_SERVICE_HOSTNAME (CAMEL_SERVICE_ARG_HOSTNAME | CAMEL_ARG_STR) -#define CAMEL_SERVICE_PORT (CAMEL_SERVICE_ARG_PORT | CAMEL_ARG_INT) -#define CAMEL_SERVICE_PATH (CAMEL_SERVICE_ARG_PATH | CAMEL_ARG_STR) - -typedef enum { - CAMEL_SERVICE_DISCONNECTED, - CAMEL_SERVICE_CONNECTING, - CAMEL_SERVICE_CONNECTED, - CAMEL_SERVICE_DISCONNECTING -} CamelServiceConnectionStatus; - -struct _CamelService { - CamelObject parent_object; - struct _CamelServicePrivate *priv; - - CamelSession *session; - CamelProvider *provider; - CamelServiceConnectionStatus status; - CamelOperation *connect_op; - CamelURL *url; -}; - - -typedef struct { - CamelObjectClass parent_class; - - void (*construct) (CamelService *service, - CamelSession *session, - CamelProvider *provider, - CamelURL *url, - CamelException *ex); - - gboolean (*connect) (CamelService *service, - CamelException *ex); - gboolean (*disconnect) (CamelService *service, - gboolean clean, - CamelException *ex); - void (*cancel_connect) (CamelService *service); - - GList * (*query_auth_types) (CamelService *service, - CamelException *ex); - - char * (*get_name) (CamelService *service, - gboolean brief); - char * (*get_path) (CamelService *service); - -} CamelServiceClass; - - -/* query_auth_types returns a GList of these */ -typedef struct { - char *name; /* user-friendly name */ - char *description; - char *authproto; - - gboolean need_password; /* needs a password to authenticate */ -} CamelServiceAuthType; - - -/* public methods */ -void camel_service_construct (CamelService *service, - CamelSession *session, - CamelProvider *provider, - CamelURL *url, - CamelException *ex); -gboolean camel_service_connect (CamelService *service, - CamelException *ex); -gboolean camel_service_disconnect (CamelService *service, - gboolean clean, - CamelException *ex); -void camel_service_cancel_connect (CamelService *service); -char * camel_service_get_url (CamelService *service); -char * camel_service_get_name (CamelService *service, - gboolean brief); -char * camel_service_get_path (CamelService *service); -CamelSession * camel_service_get_session (CamelService *service); -CamelProvider * camel_service_get_provider (CamelService *service); -GList * camel_service_query_auth_types (CamelService *service, - CamelException *ex); - -/* convenience functions */ -struct hostent * camel_service_gethost (CamelService *service, - CamelException *ex); - -/* cancellable dns lookup */ -struct hostent * camel_gethostbyname (const char *name, CamelException *ex); -struct hostent * camel_gethostbyaddr (const char *addr, int len, int type, CamelException *ex); -void camel_free_host (struct hostent *h); - -/* Standard Camel function */ -CamelType camel_service_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SERVICE_H */ - diff --git a/camel/camel-session.c b/camel/camel-session.c deleted file mode 100644 index fc31530768..0000000000 --- a/camel/camel-session.c +++ /dev/null @@ -1,901 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-session.c : Abstract class for an email session */ - -/* - * Authors: - * Dan Winship - * Jeffrey Stedfast - * Bertrand Guiheneuf - * - * Copyright 1999 - 2003 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "camel-session.h" -#include "camel-store.h" -#include "camel-transport.h" -#include "camel-exception.h" -#include "camel-file-utils.h" -#include "camel-string-utils.h" -#include "camel-url.h" -#include "camel-vee-store.h" - -#include "camel-private.h" - -#define d(x) - -#define CS_CLASS(so) CAMEL_SESSION_CLASS (CAMEL_OBJECT_GET_CLASS (so)) - -static void register_provider (CamelSession *session, CamelProvider *provider); -static GList *list_providers (CamelSession *session, gboolean load); -static CamelProvider *get_provider (CamelSession *session, - const char *url_string, - CamelException *ex); - -static CamelService *get_service (CamelSession *session, - const char *url_string, - CamelProviderType type, - CamelException *ex); -static char *get_storage_path (CamelSession *session, - CamelService *service, - CamelException *ex); - -static void *session_thread_msg_new(CamelSession *session, CamelSessionThreadOps *ops, unsigned int size); -static void session_thread_msg_free(CamelSession *session, CamelSessionThreadMsg *msg); -static int session_thread_queue(CamelSession *session, CamelSessionThreadMsg *msg, int flags); -static void session_thread_wait(CamelSession *session, int id); -static void session_thread_status(CamelSession *session, CamelSessionThreadMsg *msg, const char *text, int pc); - -/* The vfolder provider is always available */ -static CamelProvider vee_provider = { - "vfolder", - N_("Virtual folder email provider"), - - N_("For reading mail as a query of another set of folders"), - - "vfolder", - - CAMEL_PROVIDER_IS_STORAGE, - - CAMEL_URL_NEED_PATH, /* url_flags */ - - /* ... */ -}; - -static void -camel_session_init (CamelSession *session) -{ - session->online = TRUE; - session->modules = camel_provider_init (); - session->providers = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); - session->priv = g_malloc0(sizeof(*session->priv)); - - session->priv->lock = g_mutex_new(); - session->priv->thread_lock = g_mutex_new(); - session->priv->thread_id = 1; - session->priv->thread_active = g_hash_table_new(NULL, NULL); - session->priv->thread_queue = NULL; -} - -#if 0 -/* NOTE: this code ruins all chance of ever having more than 1 session object */ -static gboolean -camel_session_destroy_provider (gpointer key, gpointer value, gpointer user_data) -{ - CamelProvider *prov = (CamelProvider *)value; - int i; - - for (i = 0; i < CAMEL_NUM_PROVIDER_TYPES; i++) { - if (prov->service_cache[i]) - camel_object_bag_destroy (prov->service_cache[i]); - } - return TRUE; -} -#endif - -static void -camel_session_finalise (CamelObject *o) -{ - CamelSession *session = (CamelSession *)o; - - g_hash_table_destroy(session->priv->thread_active); - if (session->priv->thread_queue) - e_thread_destroy(session->priv->thread_queue); - - g_free(session->storage_path); - /*g_hash_table_foreach_remove (session->providers, camel_session_destroy_provider, NULL);*/ - g_hash_table_destroy (session->providers); - - g_mutex_free(session->priv->lock); - g_mutex_free(session->priv->thread_lock); - - g_free(session->priv); -} - -static void -camel_session_class_init (CamelSessionClass *camel_session_class) -{ - /* virtual method definition */ - camel_session_class->register_provider = register_provider; - camel_session_class->list_providers = list_providers; - camel_session_class->get_provider = get_provider; - camel_session_class->get_service = get_service; - camel_session_class->get_storage_path = get_storage_path; - - camel_session_class->thread_msg_new = session_thread_msg_new; - camel_session_class->thread_msg_free = session_thread_msg_free; - camel_session_class->thread_queue = session_thread_queue; - camel_session_class->thread_wait = session_thread_wait; - camel_session_class->thread_status = session_thread_status; - - vee_provider.object_types[CAMEL_PROVIDER_STORE] = camel_vee_store_get_type (); - vee_provider.url_hash = camel_url_hash; - vee_provider.url_equal = camel_url_equal; -} - -CamelType -camel_session_get_type (void) -{ - static CamelType camel_session_type = CAMEL_INVALID_TYPE; - - if (camel_session_type == CAMEL_INVALID_TYPE) { - camel_session_type = camel_type_register ( - camel_object_get_type (), "CamelSession", - sizeof (CamelSession), - sizeof (CamelSessionClass), - (CamelObjectClassInitFunc) camel_session_class_init, - NULL, - (CamelObjectInitFunc) camel_session_init, - (CamelObjectFinalizeFunc) camel_session_finalise); - } - - return camel_session_type; -} - -/** - * camel_session_construct: - * @session: a session object to construct - * @storage_path: path to a directory the session can use for - * persistent storage. (This directory must already exist.) - * - * Constructs @session. - **/ -void -camel_session_construct (CamelSession *session, const char *storage_path) -{ - session->storage_path = g_strdup (storage_path); - camel_session_register_provider(session, &vee_provider); -} - - -static void -register_provider (CamelSession *session, CamelProvider *provider) -{ - int i; - CamelProviderConfEntry *conf; - GList *l; - - for (i = 0; i < CAMEL_NUM_PROVIDER_TYPES; i++) { - if (provider->object_types[i]) - provider->service_cache[i] = camel_object_bag_new (provider->url_hash, provider->url_equal, - (CamelCopyFunc)camel_url_copy, (GFreeFunc)camel_url_free); - } - - /* Translate all strings here */ - -#define P_(string) dgettext (provider->translation_domain, string) - - provider->name = P_(provider->name); - provider->description = P_(provider->description); - conf = provider->extra_conf; - if (conf) { - for (i=0;conf[i].type != CAMEL_PROVIDER_CONF_END;i++) { - if (conf[i].text) - conf[i].text = P_(conf[i].text); - } - } - l = provider->authtypes; - while (l) { - CamelServiceAuthType *auth = l->data; - - auth->name = P_(auth->name); - auth->description = P_(auth->description); - l = l->next; - } - - g_hash_table_insert (session->providers, provider->protocol, provider); -} - -/** - * camel_session_register_provider: - * @session: a session object - * @protocol: the protocol the provider provides for - * @provider: provider object - * - * Registers a protocol to provider mapping for the session. - * - * Assumes the session lock has already been obtained, - * which is the case for automatically loaded provider modules. - **/ -void -camel_session_register_provider (CamelSession *session, - CamelProvider *provider) -{ - g_return_if_fail (CAMEL_IS_SESSION (session)); - g_return_if_fail (provider != NULL); - - CS_CLASS (session)->register_provider (session, provider); -} - - -static void -ensure_loaded (gpointer key, gpointer value, gpointer user_data) -{ - CamelSession *session = user_data; - char *name = key; - char *path = value; - - if (!g_hash_table_lookup (session->providers, name)) { - CamelException ex; - - camel_exception_init (&ex); - camel_provider_load (session, path, &ex); - camel_exception_clear (&ex); - } -} - -static gint -provider_compare (gconstpointer a, gconstpointer b) -{ - const CamelProvider *cpa = (const CamelProvider *)a; - const CamelProvider *cpb = (const CamelProvider *)b; - - return strcmp (cpa->name, cpb->name); -} - -static void -add_to_list (gpointer key, gpointer value, gpointer user_data) -{ - GList **list = user_data; - CamelProvider *prov = value; - - *list = g_list_insert_sorted (*list, prov, provider_compare); -} - -static GList * -list_providers (CamelSession *session, gboolean load) -{ - GList *list = NULL; - - if (load) - g_hash_table_foreach (session->modules, ensure_loaded, session); - - g_hash_table_foreach (session->providers, add_to_list, &list); - return list; -} - -/** - * camel_session_list_providers: - * @session: the session - * @load: whether or not to load in providers that are not already loaded - * - * This returns a list of available providers in this session. If @load - * is %TRUE, it will first load in all available providers that haven't - * yet been loaded. - * - * Return value: a GList of providers, which the caller must free. - **/ -GList * -camel_session_list_providers (CamelSession *session, gboolean load) -{ - GList *list; - - g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL); - - CAMEL_SESSION_LOCK (session, lock); - list = CS_CLASS (session)->list_providers (session, load); - CAMEL_SESSION_UNLOCK (session, lock); - - return list; -} - - -static CamelProvider * -get_provider (CamelSession *session, const char *url_string, CamelException *ex) -{ - CamelProvider *provider; - char *protocol; - - protocol = g_strndup (url_string, strcspn (url_string, ":")); - - provider = g_hash_table_lookup (session->providers, protocol); - if (!provider) { - /* See if there's one we can load. */ - char *path; - - path = g_hash_table_lookup (session->modules, protocol); - if (path) { - camel_provider_load (session, path, ex); - if (camel_exception_is_set (ex)) { - g_free (protocol); - return NULL; - } - } - provider = g_hash_table_lookup (session->providers, protocol); - } - - if (!provider) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID, - _("No provider available for protocol `%s'"), - protocol); - } - g_free (protocol); - - return provider; -} - -/** - * camel_session_get_provider: - * @session: the session - * @url_string: the URL for the service whose provider you want - * @ex: a CamelException - * - * This returns the CamelProvider that would be used to handle - * @url_string, loading it in from disk if necessary. - * - * Return value: the provider, or %NULL, in which case @ex will be set. - **/ -CamelProvider * -camel_session_get_provider (CamelSession *session, const char *url_string, - CamelException *ex) -{ - CamelProvider *provider; - - CAMEL_SESSION_LOCK (session, lock); - provider = CS_CLASS (session)->get_provider (session, url_string, ex); - CAMEL_SESSION_UNLOCK (session, lock); - - return provider; -} - -static CamelService * -get_service (CamelSession *session, const char *url_string, - CamelProviderType type, CamelException *ex) -{ - CamelURL *url; - CamelProvider *provider; - CamelService *service; - CamelException internal_ex; - - url = camel_url_new (url_string, ex); - if (!url) - return NULL; - - /* We need to look up the provider so we can then lookup - the service in the provider's cache */ - provider = CS_CLASS (session)->get_provider (session, url->protocol, ex); - if (provider && !provider->object_types[type]) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID, - _("No provider available for protocol `%s'"), - url->protocol); - provider = NULL; - } - - if (!provider) { - camel_url_free (url); - return NULL; - } - - /* If the provider doesn't use paths but the URL contains one, - * ignore it. - */ - if (url->path && !CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_PATH)) - camel_url_set_path (url, NULL); - - /* Now look up the service in the provider's cache */ - service = camel_object_bag_reserve(provider->service_cache[type], url); - if (service != NULL) { - camel_url_free (url); - return service; - } - - service = (CamelService *)camel_object_new (provider->object_types[type]); - camel_exception_init (&internal_ex); - camel_service_construct (service, session, provider, url, &internal_ex); - if (camel_exception_is_set (&internal_ex)) { - camel_exception_xfer (ex, &internal_ex); - camel_object_unref (service); - service = NULL; - camel_object_bag_abort(provider->service_cache[type], url); - } else { - camel_object_bag_add(provider->service_cache[type], url, service); - } - - return service; -} - -/** - * camel_session_get_service: - * @session: the CamelSession - * @url_string: a Camel URL describing the service to get - * @type: the provider type (%CAMEL_PROVIDER_STORE or - * %CAMEL_PROVIDER_TRANSPORT) to get, since some URLs may be able - * to specify either type. - * @ex: a CamelException - * - * This resolves a CamelURL into a CamelService, including loading the - * provider library for that service if it has not already been loaded. - * - * Services are cached, and asking for "the same" @url_string multiple - * times will return the same CamelService (with its reference count - * incremented by one each time). What constitutes "the same" URL - * depends in part on the provider. - * - * Return value: the requested CamelService, or %NULL - **/ -CamelService * -camel_session_get_service (CamelSession *session, const char *url_string, - CamelProviderType type, CamelException *ex) -{ - CamelService *service; - - g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL); - g_return_val_if_fail (url_string != NULL, NULL); - - CAMEL_SESSION_LOCK (session, lock); - service = CS_CLASS (session)->get_service (session, url_string, type, ex); - CAMEL_SESSION_UNLOCK (session, lock); - - return service; -} - -/** - * camel_session_get_service_connected: - * @session: the CamelSession - * @url_string: a Camel URL describing the service to get - * @type: the provider type - * @ex: a CamelException - * - * This works like camel_session_get_service(), but also ensures that - * the returned service will have been successfully connected (via - * camel_service_connect().) - * - * Return value: the requested CamelService, or %NULL - **/ -CamelService * -camel_session_get_service_connected (CamelSession *session, - const char *url_string, - CamelProviderType type, - CamelException *ex) -{ - CamelService *svc; - - svc = camel_session_get_service (session, url_string, type, ex); - if (svc == NULL) - return NULL; - - if (svc->status != CAMEL_SERVICE_CONNECTED) { - if (camel_service_connect (svc, ex) == FALSE) { - camel_object_unref (svc); - return NULL; - } - } - - return svc; -} - - -static char * -get_storage_path (CamelSession *session, CamelService *service, CamelException *ex) -{ - char *path, *p; - - p = camel_service_get_path (service); - path = g_strdup_printf ("%s/%s", session->storage_path, p); - g_free (p); - - if (access (path, F_OK) == 0) - return path; - - if (camel_mkdir (path, S_IRWXU) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create directory %s:\n%s"), - path, g_strerror (errno)); - g_free (path); - return NULL; - } - - return path; -} - -/** - * camel_session_get_storage_path: - * @session: session object - * @service: a CamelService - * @ex: a CamelException - * - * This returns the path to a directory which the service can use for - * its own purposes. Data stored there will remain between Evolution - * sessions. No code outside of that service should ever touch the - * files in this directory. If the directory does not exist, it will - * be created. - * - * Return value: the path (which the caller must free), or %NULL if - * an error occurs. - **/ -char * -camel_session_get_storage_path (CamelSession *session, CamelService *service, - CamelException *ex) -{ - g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL); - g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL); - - return CS_CLASS (session)->get_storage_path (session, service, ex); -} - - -/** - * camel_session_get_password: - * @session: session object - * @prompt: prompt to provide to user - * @reprompt: TRUE if the prompt should force a reprompt - * @secret: whether or not the data is secret (eg, a password, as opposed - * to a smartcard response) - * @service: the service this query is being made by - * @item: an identifier, unique within this service, for the information - * @ex: a CamelException - * - * This function is used by a CamelService to ask the application and - * the user for a password or other authentication data. - * - * @service and @item together uniquely identify the piece of data the - * caller is concerned with. - * - * @prompt is a question to ask the user (if the application doesn't - * already have the answer cached). If @secret is set, the user's - * input will not be echoed back. The authenticator should set @ex - * to %CAMEL_EXCEPTION_USER_CANCEL if the user did not provide the - * information. The caller must g_free() the information returned when - * it is done with it. - * - * Return value: the authentication information or %NULL. - **/ -char * -camel_session_get_password (CamelSession *session, const char *prompt, - gboolean reprompt, gboolean secret, - CamelService *service, const char *item, - CamelException *ex) -{ - g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL); - g_return_val_if_fail (prompt != NULL, NULL); - g_return_val_if_fail (item != NULL, NULL); - - return CS_CLASS (session)->get_password (session, prompt, reprompt, secret, service, item, ex); -} - - -/** - * camel_session_forget_password: - * @session: session object - * @service: the service rejecting the password - * @item: an identifier, unique within this service, for the information - * @ex: a CamelException - * - * This function is used by a CamelService to tell the application - * that the authentication information it provided via - * camel_session_get_password was rejected by the service. If the - * application was caching this information, it should stop, - * and if the service asks for it again, it should ask the user. - * - * @service and @item identify the rejected authentication information, - * as with camel_session_get_password. - **/ -void -camel_session_forget_password (CamelSession *session, CamelService *service, - const char *item, CamelException *ex) -{ - g_return_if_fail (CAMEL_IS_SESSION (session)); - g_return_if_fail (item != NULL); - - CS_CLASS (session)->forget_password (session, service, item, ex); -} - - -/** - * camel_session_alert_user: - * @session: session object - * @type: the type of alert (info, warning, or error) - * @prompt: the message for the user - * @cancel: whether or not to provide a "Cancel" option in addition to - * an "OK" option. - * - * Presents the given @prompt to the user, in the style indicated by - * @type. If @cancel is %TRUE, the user will be able to accept or - * cancel. Otherwise, the message is purely informational. - * - * Return value: %TRUE if the user accepts, %FALSE if they cancel. - */ -gboolean -camel_session_alert_user (CamelSession *session, CamelSessionAlertType type, - const char *prompt, gboolean cancel) -{ - g_return_val_if_fail (CAMEL_IS_SESSION (session), FALSE); - g_return_val_if_fail (prompt != NULL, FALSE); - - return CS_CLASS (session)->alert_user (session, type, prompt, cancel); -} - - -/** - * camel_session_is_online: - * @session: the session. - * - * Return value: whether or not @session is online. - **/ -gboolean -camel_session_is_online (CamelSession *session) -{ - return session->online; -} - - -/** - * camel_session_set_online: - * @session: the session - * @online: whether or not the session should be online - * - * Sets the online status of @session to @online. - **/ -void -camel_session_set_online (CamelSession *session, gboolean online) -{ - session->online = online; -} - - -/** - * camel_session_get_filter_driver: - * @session: the session - * @type: the type of filter (eg, "incoming") - * @ex: a CamelException - * - * Return value: a filter driver, loaded with applicable rules - **/ -CamelFilterDriver * -camel_session_get_filter_driver (CamelSession *session, - const char *type, - CamelException *ex) -{ - return CS_CLASS (session)->get_filter_driver (session, type, ex); -} - -static void -cs_thread_status(CamelOperation *op, const char *what, int pc, void *data) -{ - CamelSessionThreadMsg *m = data; - - CS_CLASS(m->session)->thread_status(m->session, m, what, pc); -} - -static void *session_thread_msg_new(CamelSession *session, CamelSessionThreadOps *ops, unsigned int size) -{ - CamelSessionThreadMsg *m; - - g_assert(size >= sizeof(*m)); - - m = g_malloc0(size); - m->ops = ops; - m->session = session; - camel_object_ref(session); - m->op = camel_operation_new(cs_thread_status, m); - camel_exception_init(&m->ex); - CAMEL_SESSION_LOCK(session, thread_lock); - m->id = session->priv->thread_id++; - g_hash_table_insert(session->priv->thread_active, GINT_TO_POINTER(m->id), m); - CAMEL_SESSION_UNLOCK(session, thread_lock); - - return m; -} - -static void session_thread_msg_free(CamelSession *session, CamelSessionThreadMsg *msg) -{ - g_assert(msg->ops != NULL); - - d(printf("free message %p session %p\n", msg, session)); - - CAMEL_SESSION_LOCK(session, thread_lock); - g_hash_table_remove(session->priv->thread_active, GINT_TO_POINTER(msg->id)); - CAMEL_SESSION_UNLOCK(session, thread_lock); - - d(printf("free msg, ops->free = %p\n", msg->ops->free)); - - if (msg->ops->free) - msg->ops->free(session, msg); - if (msg->op) - camel_operation_unref(msg->op); - camel_exception_clear(&msg->ex); - camel_object_unref(msg->session); - g_free(msg); -} - -static void session_thread_destroy(EThread *thread, CamelSessionThreadMsg *msg, CamelSession *session) -{ - d(printf("destroy message %p session %p\n", msg, session)); - camel_session_thread_msg_free(session, msg); -} - -static void session_thread_received(EThread *thread, CamelSessionThreadMsg *msg, CamelSession *session) -{ - d(printf("receive message %p session %p\n", msg, session)); - if (msg->ops->receive) { - CamelOperation *oldop; - - oldop = camel_operation_register(msg->op); - msg->ops->receive(session, msg); - camel_operation_register(oldop); - } -} - -static int session_thread_queue(CamelSession *session, CamelSessionThreadMsg *msg, int flags) -{ - int id; - - CAMEL_SESSION_LOCK(session, thread_lock); - if (session->priv->thread_queue == NULL) { - session->priv->thread_queue = e_thread_new(E_THREAD_QUEUE); - e_thread_set_msg_destroy(session->priv->thread_queue, (EThreadFunc)session_thread_destroy, session); - e_thread_set_msg_received(session->priv->thread_queue, (EThreadFunc)session_thread_received, session); - } - CAMEL_SESSION_UNLOCK(session, thread_lock); - - id = msg->id; - e_thread_put(session->priv->thread_queue, &msg->msg); - - return id; -} - -static void session_thread_wait(CamelSession *session, int id) -{ - int wait; - - /* we just busy wait, only other alternative is to setup a reply port? */ - do { - CAMEL_SESSION_LOCK(session, thread_lock); - wait = g_hash_table_lookup(session->priv->thread_active, GINT_TO_POINTER(id)) != NULL; - CAMEL_SESSION_UNLOCK(session, thread_lock); - if (wait) { - usleep(20000); - } - } while (wait); -} - -static void session_thread_status(CamelSession *session, CamelSessionThreadMsg *msg, const char *text, int pc) -{ -} - -/** - * camel_session_thread_msg_new: - * @session: - * @ops: - * @size: - * - * Create a new thread message, using ops as the receive/reply/free - * ops, of @size bytes. - * - * @ops points to the operations used to recieve/process and finally - * free the message. - **/ -void *camel_session_thread_msg_new(CamelSession *session, CamelSessionThreadOps *ops, unsigned int size) -{ - g_assert(CAMEL_IS_SESSION(session)); - g_assert(ops != NULL); - g_assert(size >= sizeof(CamelSessionThreadMsg)); - - return CS_CLASS (session)->thread_msg_new(session, ops, size); -} - -/** - * camel_session_thread_msg_free: - * @session: - * @msg: - * - * Free a @msg. Note that the message must have been allocated using - * msg_new, and must nto have been submitted to any queue function. - **/ -void camel_session_thread_msg_free(CamelSession *session, CamelSessionThreadMsg *msg) -{ - g_assert(CAMEL_IS_SESSION(session)); - g_assert(msg != NULL); - g_assert(msg->ops != NULL); - - CS_CLASS (session)->thread_msg_free(session, msg); -} - -/** - * camel_session_thread_queue: - * @session: - * @msg: - * @flags: queue type flags, currently 0. - * - * Queue a thread message in another thread for processing. - * The operation should be (but needn't) run in a queued manner - * with other operations queued in this manner. - * - * Return value: The id of the operation queued. - **/ -int camel_session_thread_queue(CamelSession *session, CamelSessionThreadMsg *msg, int flags) -{ - g_assert(CAMEL_IS_SESSION(session)); - g_assert(msg != NULL); - - return CS_CLASS (session)->thread_queue(session, msg, flags); -} - -/** - * camel_session_thread_wait: - * @session: - * @id: - * - * Wait on an operation to complete (by id). - **/ -void camel_session_thread_wait(CamelSession *session, int id) -{ - g_assert(CAMEL_IS_SESSION(session)); - - if (id == -1) - return; - - CS_CLASS (session)->thread_wait(session, id); -} - -/** - * camel_session_check_junk: - * @session: - * - * Do we have to check incoming messages to be junk? - **/ -gboolean -camel_session_check_junk (CamelSession *session) -{ - g_assert(CAMEL_IS_SESSION(session)); - - return session->check_junk; -} - -/** - * camel_session_set_check_junk: - * @session: - * @check_junk: - * - * Set check_junk flag, if set, incoming mail will be checked for being junk. - **/ -void -camel_session_set_check_junk (CamelSession *session, gboolean check_junk) -{ - g_assert(CAMEL_IS_SESSION(session)); - - session->check_junk = check_junk; -} diff --git a/camel/camel-session.h b/camel/camel-session.h deleted file mode 100644 index e99d31a334..0000000000 --- a/camel/camel-session.h +++ /dev/null @@ -1,217 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-session.h : Abstract class for an email session */ - -/* - * - * Author : - * Bertrand Guiheneuf - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_SESSION_H -#define CAMEL_SESSION_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include -#include - -#include - -#define CAMEL_SESSION_TYPE (camel_session_get_type ()) -#define CAMEL_SESSION(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SESSION_TYPE, CamelSession)) -#define CAMEL_SESSION_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SESSION_TYPE, CamelSessionClass)) -#define CAMEL_IS_SESSION(o) (CAMEL_CHECK_TYPE((o), CAMEL_SESSION_TYPE)) - - -typedef gboolean (*CamelTimeoutCallback) (gpointer data); -typedef enum { - CAMEL_SESSION_ALERT_INFO, - CAMEL_SESSION_ALERT_WARNING, - CAMEL_SESSION_ALERT_ERROR -} CamelSessionAlertType; - -struct _CamelSession -{ - CamelObject parent_object; - struct _CamelSessionPrivate *priv; - - char *storage_path; - GHashTable *providers, *modules; - gboolean online; - - CamelJunkPlugin *junk_plugin; - gboolean check_junk; -}; - -#ifdef ENABLE_THREADS -typedef struct _CamelSessionThreadOps CamelSessionThreadOps; -typedef struct _CamelSessionThreadMsg CamelSessionThreadMsg; -#endif - -typedef struct { - CamelObjectClass parent_class; - - void (*register_provider) (CamelSession *session, - CamelProvider *provider); - GList * (*list_providers) (CamelSession *session, - gboolean load); - CamelProvider * (*get_provider) (CamelSession *session, - const char *url_string, - CamelException *ex); - - CamelService * (*get_service) (CamelSession *session, - const char *url_string, - CamelProviderType type, - CamelException *ex); - char * (*get_storage_path) (CamelSession *session, - CamelService *service, - CamelException *ex); - - char * (*get_password) (CamelSession *session, - const char *prompt, - gboolean reprompt, - gboolean secret, - CamelService *service, - const char *item, - CamelException *ex); - void (*forget_password) (CamelSession *session, - CamelService *service, - const char *item, - CamelException *ex); - gboolean (*alert_user) (CamelSession *session, - CamelSessionAlertType type, - const char *prompt, - gboolean cancel); - - CamelFilterDriver * (*get_filter_driver) (CamelSession *session, - const char *type, - CamelException *ex); -#ifdef ENABLE_THREADS - /* mechanism for creating and maintaining multiple threads of control */ - void *(*thread_msg_new)(CamelSession *session, CamelSessionThreadOps *ops, unsigned int size); - void (*thread_msg_free)(CamelSession *session, CamelSessionThreadMsg *msg); - int (*thread_queue)(CamelSession *session, CamelSessionThreadMsg *msg, int flags); - void (*thread_wait)(CamelSession *session, int id); - void (*thread_status)(CamelSession *session, CamelSessionThreadMsg *msg, const char *text, int pc); -#endif - -} CamelSessionClass; - - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_session_get_type (void); - - -void camel_session_construct (CamelSession *session, - const char *storage_path); - -void camel_session_register_provider (CamelSession *session, - CamelProvider *provider); -GList * camel_session_list_providers (CamelSession *session, - gboolean load); - -CamelProvider * camel_session_get_provider (CamelSession *session, - const char *url_string, - CamelException *ex); - -CamelService * camel_session_get_service (CamelSession *session, - const char *url_string, - CamelProviderType type, - CamelException *ex); -CamelService * camel_session_get_service_connected (CamelSession *session, - const char *url_string, - CamelProviderType type, - CamelException *ex); - -#define camel_session_get_store(session, url_string, ex) \ - ((CamelStore *) camel_session_get_service_connected (session, url_string, CAMEL_PROVIDER_STORE, ex)) -#define camel_session_get_transport(session, url_string, ex) \ - ((CamelTransport *) camel_session_get_service_connected (session, url_string, CAMEL_PROVIDER_TRANSPORT, ex)) - -char * camel_session_get_storage_path (CamelSession *session, - CamelService *service, - CamelException *ex); - -char * camel_session_get_password (CamelSession *session, - const char *prompt, - gboolean reprompt, - gboolean secret, - CamelService *service, - const char *item, - CamelException *ex); -void camel_session_forget_password (CamelSession *session, - CamelService *service, - const char *item, - CamelException *ex); -gboolean camel_session_alert_user (CamelSession *session, - CamelSessionAlertType type, - const char *prompt, - gboolean cancel); - -gboolean camel_session_is_online (CamelSession *session); -void camel_session_set_online (CamelSession *session, - gboolean online); - -CamelFilterDriver *camel_session_get_filter_driver (CamelSession *session, - const char *type, - CamelException *ex); - -gboolean camel_session_check_junk (CamelSession *session); -void camel_session_set_check_junk (CamelSession *session, gboolean check_junk); - -#ifdef ENABLE_THREADS -struct _CamelSessionThreadOps { - void (*receive)(CamelSession *session, struct _CamelSessionThreadMsg *m); - void (*free)(CamelSession *session, struct _CamelSessionThreadMsg *m); -}; - -struct _CamelSessionThreadMsg { - EMsg msg; - - int id; - - CamelException ex; - CamelSessionThreadOps *ops; - struct _CamelOperation *op; - CamelSession *session; - - void *data; /* free for implementation to define, not used by camel, do not use in client code */ - /* user fields follow */ -}; - -void *camel_session_thread_msg_new(CamelSession *session, CamelSessionThreadOps *ops, unsigned int size); -void camel_session_thread_msg_free(CamelSession *session, CamelSessionThreadMsg *msg); -int camel_session_thread_queue(CamelSession *session, CamelSessionThreadMsg *msg, int flags); -void camel_session_thread_wait(CamelSession *session, int id); - -#endif - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SESSION_H */ diff --git a/camel/camel-smime-context.c b/camel/camel-smime-context.c deleted file mode 100644 index dd7ed68b3f..0000000000 --- a/camel/camel-smime-context.c +++ /dev/null @@ -1,1061 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * Michael Zucchi - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1994-2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Copyright 2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "nss.h" -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "camel-smime-context.h" -#include "camel-operation.h" - -#define d(x) - -struct _CamelSMIMEContextPrivate { - CERTCertDBHandle *certdb; - - char *encrypt_key; - camel_smime_sign_t sign_mode; - - unsigned int send_encrypt_key_prefs:1; -}; - -static CamelCipherContextClass *parent_class = NULL; - -/* used for decode content callback, for streaming decode */ -static void -sm_write_stream(void *arg, const char *buf, unsigned long len) -{ - camel_stream_write((CamelStream *)arg, buf, len); -} - -static PK11SymKey * -sm_decrypt_key(void *arg, SECAlgorithmID *algid) -{ - printf("Decrypt key called\n"); - return (PK11SymKey *)arg; -} - -static char * -sm_get_passwd(PK11SlotInfo *info, PRBool retry, void *arg) -{ - CamelSMIMEContext *context = arg; - char *pass, *nsspass = NULL; - char *prompt; - CamelException *ex; - - printf("get passwd called '%s'\n", PK11_GetTokenName(info)); - - ex = camel_exception_new(); - prompt = g_strdup_printf(_("Enter security pass-phrase for `%s'"), PK11_GetTokenName(info)); - pass = camel_session_get_password(((CamelCipherContext *)context)->session, prompt, FALSE, TRUE, NULL, PK11_GetTokenName(info), ex); - camel_exception_free(ex); - g_free(prompt); - if (pass) { - nsspass = PORT_Strdup(pass); - g_free(pass); - } - - return nsspass; -} - -/** - * camel_smime_context_new: - * @session: session - * - * Creates a new sm cipher context object. - * - * Returns a new sm cipher context object. - **/ -CamelCipherContext * -camel_smime_context_new(CamelSession *session) -{ - CamelCipherContext *cipher; - CamelSMIMEContext *ctx; - - g_return_val_if_fail(CAMEL_IS_SESSION(session), NULL); - - ctx =(CamelSMIMEContext *) camel_object_new(camel_smime_context_get_type()); - - cipher =(CamelCipherContext *) ctx; - cipher->session = session; - camel_object_ref(session); - - return cipher; -} - -void -camel_smime_context_set_encrypt_key(CamelSMIMEContext *context, gboolean use, const char *key) -{ - context->priv->send_encrypt_key_prefs = use; - g_free(context->priv->encrypt_key); - context->priv->encrypt_key = g_strdup(key); -} - -/* set signing mode, clearsigned multipart/signed or enveloped */ -void -camel_smime_context_set_sign_mode(CamelSMIMEContext *context, camel_smime_sign_t type) -{ - context->priv->sign_mode = type; -} - -/* TODO: This is suboptimal, but the only other solution is to pass around NSSCMSMessages */ -guint32 -camel_smime_context_describe_part(CamelSMIMEContext *context, CamelMimePart *part) -{ - guint32 flags = 0; - CamelContentType *ct; - const char *tmp; - - ct = camel_mime_part_get_content_type(part); - - if (camel_content_type_is(ct, "multipart", "signed")) { - tmp = camel_content_type_param(ct, "protocol"); - if (tmp && g_ascii_strcasecmp(tmp, ((CamelCipherContext *)context)->sign_protocol)) - flags = CAMEL_SMIME_SIGNED; - } else if (camel_content_type_is(ct, "application", "x-pkcs7-mime")) { - CamelStreamMem *istream; - NSSCMSMessage *cmsg; - NSSCMSDecoderContext *dec; - - /* FIXME: stream this to the decoder incrementally */ - istream = (CamelStreamMem *)camel_stream_mem_new(); - camel_data_wrapper_decode_to_stream(camel_medium_get_content_object((CamelMedium *)part), (CamelStream *)istream); - camel_stream_reset((CamelStream *)istream); - - dec = NSS_CMSDecoder_Start(NULL, - NULL, NULL, - sm_get_passwd, context, /* password callback */ - NULL, NULL); /* decrypt key callback */ - - NSS_CMSDecoder_Update(dec, istream->buffer->data, istream->buffer->len); - camel_object_unref(istream); - - cmsg = NSS_CMSDecoder_Finish(dec); - if (cmsg) { - if (NSS_CMSMessage_IsSigned(cmsg)) { - printf("message is signed\n"); - flags |= CAMEL_SMIME_SIGNED; - } - - if (NSS_CMSMessage_IsEncrypted(cmsg)) { - printf("message is encrypted\n"); - flags |= CAMEL_SMIME_ENCRYPTED; - } -#if 0 - if (NSS_CMSMessage_ContainsCertsOrCrls(cmsg)) { - printf("message contains certs or crls\n"); - flags |= CAMEL_SMIME_CERTS; - } -#endif - NSS_CMSMessage_Destroy(cmsg); - } else { - printf("Message could not be parsed\n"); - } - } - - return flags; -} - -static const char * -sm_hash_to_id(CamelCipherContext *context, CamelCipherHash hash) -{ - switch(hash) { - case CAMEL_CIPHER_HASH_MD5: - return "md5"; - case CAMEL_CIPHER_HASH_SHA1: - case CAMEL_CIPHER_HASH_DEFAULT: - return "sha1"; - default: - return NULL; - } -} - -static CamelCipherHash -sm_id_to_hash(CamelCipherContext *context, const char *id) -{ - if (id) { - if (!strcmp(id, "md5")) - return CAMEL_CIPHER_HASH_MD5; - else if (!strcmp(id, "sha1")) - return CAMEL_CIPHER_HASH_SHA1; - } - - return CAMEL_CIPHER_HASH_DEFAULT; -} - -static NSSCMSMessage * -sm_signing_cmsmessage(CamelSMIMEContext *context, const char *nick, SECOidTag hash, int detached, CamelException *ex) -{ - struct _CamelSMIMEContextPrivate *p = context->priv; - NSSCMSMessage *cmsg = NULL; - NSSCMSContentInfo *cinfo; - NSSCMSSignedData *sigd; - NSSCMSSignerInfo *signerinfo; - CERTCertificate *cert= NULL, *ekpcert = NULL; - - if ((cert = CERT_FindUserCertByUsage(p->certdb, - (char *)nick, - certUsageEmailSigner, - PR_FALSE, - NULL)) == NULL) { - camel_exception_setv(ex, 1, "Can't find certificate for '%s'", nick); - return NULL; - } - - cmsg = NSS_CMSMessage_Create(NULL); /* create a message on its own pool */ - if (cmsg == NULL) { - camel_exception_setv(ex, 1, "Can't create CMS message"); - goto fail; - } - - if ((sigd = NSS_CMSSignedData_Create(cmsg)) == NULL) { - camel_exception_setv(ex, 1, "Can't create CMS signedData"); - goto fail; - } - - cinfo = NSS_CMSMessage_GetContentInfo(cmsg); - if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd) != SECSuccess) { - camel_exception_setv(ex, 1, "Can't attach CMS signedData"); - goto fail; - } - - /* if !detatched, the contentinfo will alloc a data item for us */ - cinfo = NSS_CMSSignedData_GetContentInfo(sigd); - if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, detached) != SECSuccess) { - camel_exception_setv(ex, 1, "Can't attach CMS data"); - goto fail; - } - - signerinfo = NSS_CMSSignerInfo_Create(cmsg, cert, hash); - if (signerinfo == NULL) { - camel_exception_setv(ex, 1, "Can't create CMS SignerInfo"); - goto fail; - } - - /* we want the cert chain included for this one */ - if (NSS_CMSSignerInfo_IncludeCerts(signerinfo, NSSCMSCM_CertChain, certUsageEmailSigner) != SECSuccess) { - camel_exception_setv(ex, 1, "Can't find cert chain"); - goto fail; - } - - /* SMIME RFC says signing time should always be added */ - if (NSS_CMSSignerInfo_AddSigningTime(signerinfo, PR_Now()) != SECSuccess) { - camel_exception_setv(ex, 1, "Can't add CMS SigningTime"); - goto fail; - } - -#if 0 - /* this can but needn't be added. not sure what general usage is */ - if (NSS_CMSSignerInfo_AddSMIMECaps(signerinfo) != SECSuccess) { - fprintf(stderr, "ERROR: cannot add SMIMECaps attribute.\n"); - goto loser; - } -#endif - - /* Check if we need to send along our return encrypt cert, rfc2633 2.5.3 */ - if (p->send_encrypt_key_prefs) { - CERTCertificate *enccert = NULL; - - if (p->encrypt_key) { - /* encrypt key has its own nick */ - if ((ekpcert = CERT_FindUserCertByUsage( - p->certdb, - p->encrypt_key, - certUsageEmailRecipient, PR_FALSE, NULL)) == NULL) { - camel_exception_setv(ex, 1, "encryption cert for '%s' does not exist", p->encrypt_key); - goto fail; - } - enccert = ekpcert; - } else if (CERT_CheckCertUsage(cert, certUsageEmailRecipient) == SECSuccess) { - /* encrypt key is signing key */ - enccert = cert; - } else { - /* encrypt key uses same nick */ - if ((ekpcert = CERT_FindUserCertByUsage( - p->certdb, (char *)nick, - certUsageEmailRecipient, PR_FALSE, NULL)) == NULL) { - camel_exception_setv(ex, 1, "encryption cert for '%s' does not exist", nick); - goto fail; - } - enccert = ekpcert; - } - - if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, enccert, p->certdb) != SECSuccess) { - camel_exception_setv(ex, 1, "can't add SMIMEEncKeyPrefs attribute"); - goto fail; - } - - if (NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs(signerinfo, enccert, p->certdb) != SECSuccess) { - camel_exception_setv(ex, 1, "can't add MS SMIMEEncKeyPrefs attribute"); - goto fail; - } - - if (ekpcert != NULL && NSS_CMSSignedData_AddCertificate(sigd, ekpcert) != SECSuccess) { - camel_exception_setv(ex, 1, "can't add add encryption certificate"); - goto fail; - } - } - - if (NSS_CMSSignedData_AddSignerInfo(sigd, signerinfo) != SECSuccess) { - camel_exception_setv(ex, 1, "can't add CMS SignerInfo"); - goto fail; - } - - if (ekpcert) - CERT_DestroyCertificate(ekpcert); - - if (cert) - CERT_DestroyCertificate(cert); - - return cmsg; -fail: - if (ekpcert) - CERT_DestroyCertificate(ekpcert); - - if (cert) - CERT_DestroyCertificate(cert); - - NSS_CMSMessage_Destroy(cmsg); - - return NULL; -} - -static int -sm_sign(CamelCipherContext *context, const char *userid, CamelCipherHash hash, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex) -{ - int res = -1; - NSSCMSMessage *cmsg; - CamelStream *ostream, *istream; - SECOidTag sechash; - NSSCMSEncoderContext *enc; - CamelDataWrapper *dw; - CamelContentType *ct; - - switch (hash) { - case CAMEL_CIPHER_HASH_SHA1: - case CAMEL_CIPHER_HASH_DEFAULT: - default: - sechash = SEC_OID_SHA1; - break; - case CAMEL_CIPHER_HASH_MD5: - sechash = SEC_OID_MD5; - break; - } - - cmsg = sm_signing_cmsmessage((CamelSMIMEContext *)context, userid, sechash, - ((CamelSMIMEContext *)context)->priv->sign_mode == CAMEL_SMIME_SIGN_CLEARSIGN, ex); - if (cmsg == NULL) - return -1; - - ostream = camel_stream_mem_new(); - - /* FIXME: stream this, we stream output at least */ - istream = camel_stream_mem_new(); - if (camel_cipher_canonical_to_stream(ipart, - CAMEL_MIME_FILTER_CANON_STRIP - |CAMEL_MIME_FILTER_CANON_CRLF - |CAMEL_MIME_FILTER_CANON_FROM, istream) == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not generate signing data: %s"), g_strerror(errno)); - goto fail; - } - - enc = NSS_CMSEncoder_Start(cmsg, - sm_write_stream, ostream, /* DER output callback */ - NULL, NULL, /* destination storage */ - sm_get_passwd, context, /* password callback */ - NULL, NULL, /* decrypt key callback */ - NULL, NULL ); /* detached digests */ - if (!enc) { - camel_exception_setv(ex, 1, "Cannot create encoder context"); - goto fail; - } - - if (NSS_CMSEncoder_Update(enc, ((CamelStreamMem *)istream)->buffer->data, ((CamelStreamMem *)istream)->buffer->len) != SECSuccess) { - NSS_CMSEncoder_Cancel(enc); - camel_exception_setv(ex, 1, "Failed to add data to CMS encoder"); - goto fail; - } - - if (NSS_CMSEncoder_Finish(enc) != SECSuccess) { - camel_exception_setv(ex, 1, "Failed to encode data"); - goto fail; - } - - res = 0; - - dw = camel_data_wrapper_new(); - camel_stream_reset(ostream); - camel_data_wrapper_construct_from_stream(dw, ostream); - dw->encoding = CAMEL_TRANSFER_ENCODING_BINARY; - - if (((CamelSMIMEContext *)context)->priv->sign_mode == CAMEL_SMIME_SIGN_CLEARSIGN) { - CamelMultipartSigned *mps; - CamelMimePart *sigpart; - - sigpart = camel_mime_part_new(); - ct = camel_content_type_new("application", "x-pkcs7-signature"); - camel_content_type_set_param(ct, "name", "smime.p7s"); - camel_data_wrapper_set_mime_type_field(dw, ct); - camel_content_type_unref(ct); - - camel_medium_set_content_object((CamelMedium *)sigpart, dw); - - camel_mime_part_set_filename(sigpart, "smime.p7s"); - camel_mime_part_set_disposition(sigpart, "attachment"); - camel_mime_part_set_encoding(sigpart, CAMEL_TRANSFER_ENCODING_BASE64); - - mps = camel_multipart_signed_new(); - ct = camel_content_type_new("multipart", "signed"); - camel_content_type_set_param(ct, "micalg", camel_cipher_hash_to_id(context, hash)); - camel_content_type_set_param(ct, "protocol", context->sign_protocol); - camel_data_wrapper_set_mime_type_field((CamelDataWrapper *)mps, ct); - camel_content_type_unref(ct); - camel_multipart_set_boundary((CamelMultipart *)mps, NULL); - - mps->signature = sigpart; - mps->contentraw = istream; - camel_stream_reset(istream); - camel_object_ref(istream); - - camel_medium_set_content_object((CamelMedium *)opart, (CamelDataWrapper *)mps); - } else { - ct = camel_content_type_new("application", "x-pkcs7-mime"); - camel_content_type_set_param(ct, "name", "smime.p7m"); - camel_content_type_set_param(ct, "smime-type", "signed-data"); - camel_data_wrapper_set_mime_type_field(dw, ct); - camel_content_type_unref(ct); - - camel_medium_set_content_object((CamelMedium *)opart, dw); - - camel_mime_part_set_filename(opart, "smime.p7m"); - camel_mime_part_set_description(opart, "S/MIME Signed Message"); - camel_mime_part_set_disposition(opart, "attachment"); - camel_mime_part_set_encoding(opart, CAMEL_TRANSFER_ENCODING_BASE64); - } - - camel_object_unref(dw); -fail: - camel_object_unref(ostream); - camel_object_unref(istream); - - return res; -} - -static const char * -sm_status_description(NSSCMSVerificationStatus status) -{ - /* could use this but then we can't control i18n? */ - /*NSS_CMSUtil_VerificationStatusToString(status));*/ - - switch(status) { - case NSSCMSVS_Unverified: - default: - return _("Unverified"); - case NSSCMSVS_GoodSignature: - return _("Good signature"); - case NSSCMSVS_BadSignature: - return _("Bad signature"); - case NSSCMSVS_DigestMismatch: - return _("Content tampered with or altered in transit"); - case NSSCMSVS_SigningCertNotFound: - return _("Signing certificate not found"); - case NSSCMSVS_SigningCertNotTrusted: - return _("Signing certificate not trusted"); - case NSSCMSVS_SignatureAlgorithmUnknown: - return _("Signature algorithm unknown"); - case NSSCMSVS_SignatureAlgorithmUnsupported: - return _("Siganture algorithm unsupported"); - case NSSCMSVS_MalformedSignature: - return _("Malformed signature"); - case NSSCMSVS_ProcessingError: - return _("Processing error"); - } -} - -static CamelCipherValidity * -sm_verify_cmsg(CamelCipherContext *context, NSSCMSMessage *cmsg, CamelStream *extstream, CamelException *ex) -{ - struct _CamelSMIMEContextPrivate *p = ((CamelSMIMEContext *)context)->priv; - NSSCMSSignedData *sigd = NULL; - NSSCMSEnvelopedData *envd; - NSSCMSEncryptedData *encd; - SECAlgorithmID **digestalgs; - NSSCMSDigestContext *digcx; - int count, i, nsigners, j; - SECItem **digests; - PLArenaPool *poolp = NULL; - CamelStreamMem *mem; - NSSCMSVerificationStatus status; - CamelCipherValidity *valid; - GString *description; - - description = g_string_new(""); - valid = camel_cipher_validity_new(); - camel_cipher_validity_set_valid(valid, TRUE); - status = NSSCMSVS_Unverified; - - /* NB: this probably needs to go into a decoding routine that can be used for processing - enveloped data too */ - count = NSS_CMSMessage_ContentLevelCount(cmsg); - for (i = 0; i < count; i++) { - NSSCMSContentInfo *cinfo = NSS_CMSMessage_ContentLevel(cmsg, i); - SECOidTag typetag = NSS_CMSContentInfo_GetContentTypeTag(cinfo); - - switch (typetag) { - case SEC_OID_PKCS7_SIGNED_DATA: - sigd = (NSSCMSSignedData *)NSS_CMSContentInfo_GetContent(cinfo); - if (sigd == NULL) { - camel_exception_setv(ex, 1, "No signedData in signature"); - goto fail; - } - - /* need to build digests of the content */ - if (!NSS_CMSSignedData_HasDigests(sigd)) { - if (extstream == NULL) { - camel_exception_setv(ex, 1, "Digests missing from enveloped data"); - goto fail; - } - - if ((poolp = PORT_NewArena(1024)) == NULL) { - camel_exception_setv(ex, 1, "out of memory"); - goto fail; - } - - digestalgs = NSS_CMSSignedData_GetDigestAlgs(sigd); - - digcx = NSS_CMSDigestContext_StartMultiple(digestalgs); - if (digcx == NULL) { - camel_exception_setv(ex, 1, "Cannot calculate digests"); - goto fail; - } - - mem = (CamelStreamMem *)camel_stream_mem_new(); - camel_stream_write_to_stream(extstream, (CamelStream *)mem); - NSS_CMSDigestContext_Update(digcx, mem->buffer->data, mem->buffer->len); - camel_object_unref(mem); - - if (NSS_CMSDigestContext_FinishMultiple(digcx, poolp, &digests) != SECSuccess) { - camel_exception_setv(ex, 1, "Cannot calculate digests"); - goto fail; - } - - if (NSS_CMSSignedData_SetDigests(sigd, digestalgs, digests) != SECSuccess) { - camel_exception_setv(ex, 1, "Cannot set message digests"); - goto fail; - } - - PORT_FreeArena(poolp, PR_FALSE); - poolp = NULL; - } - - /* import the certificates */ - if (NSS_CMSSignedData_ImportCerts(sigd, p->certdb, certUsageEmailSigner, PR_FALSE) != SECSuccess) { - camel_exception_setv(ex, 1, "cert import failed"); - goto fail; - } - - /* check for certs-only message */ - nsigners = NSS_CMSSignedData_SignerInfoCount(sigd); - if (nsigners == 0) { - /* ?? Should we check other usages? */ - NSS_CMSSignedData_ImportCerts(sigd, p->certdb, certUsageEmailSigner, PR_TRUE); - if (NSS_CMSSignedData_VerifyCertsOnly(sigd, p->certdb, certUsageEmailSigner) != SECSuccess) { - g_string_printf(description, "Certficate only message, cannot verify certificates"); - } else { - status = NSSCMSVS_GoodSignature; - g_string_printf(description, "Certficate only message, certificates imported and verified"); - } - } else { - if (!NSS_CMSSignedData_HasDigests(sigd)) { - camel_exception_setv(ex, 1, "Can't find signature digests"); - goto fail; - } - - for (j = 0; j < nsigners; j++) { - NSSCMSSignerInfo *si; - char *cn, *em; - - si = NSS_CMSSignedData_GetSignerInfo(sigd, j); - NSS_CMSSignedData_VerifySignerInfo(sigd, j, p->certdb, certUsageEmailSigner); - - status = NSS_CMSSignerInfo_GetVerificationStatus(si); - - cn = NSS_CMSSignerInfo_GetSignerCommonName(si); - em = NSS_CMSSignerInfo_GetSignerEmailAddress(si); - - g_string_append_printf(description, _("Signer: %s <%s>: %s\n"), - cn?cn:"", em?em:"", - sm_status_description(status)); - - if (cn) - PORT_Free(cn); - if (em) - PORT_Free(em); - - if (status != NSSCMSVS_GoodSignature) - camel_cipher_validity_set_valid(valid, FALSE); - } - } - break; - case SEC_OID_PKCS7_ENVELOPED_DATA: - envd = (NSSCMSEnvelopedData *)NSS_CMSContentInfo_GetContent(cinfo); - break; - case SEC_OID_PKCS7_ENCRYPTED_DATA: - encd = (NSSCMSEncryptedData *)NSS_CMSContentInfo_GetContent(cinfo); - break; - case SEC_OID_PKCS7_DATA: - break; - default: - break; - } - } - - camel_cipher_validity_set_valid(valid, status == NSSCMSVS_GoodSignature); - camel_cipher_validity_set_description(valid, description->str); - g_string_free(description, TRUE); - - return valid; - -fail: - camel_cipher_validity_free(valid); - g_string_free(description, TRUE); - - return NULL; -} - -static CamelCipherValidity * -sm_verify(CamelCipherContext *context, CamelMimePart *ipart, CamelException *ex) -{ - NSSCMSDecoderContext *dec; - NSSCMSMessage *cmsg; - CamelStreamMem *mem; - CamelStream *constream; - CamelCipherValidity *valid = NULL; - CamelContentType *ct; - const char *tmp; - CamelMimePart *sigpart; - CamelDataWrapper *dw; - - dw = camel_medium_get_content_object((CamelMedium *)ipart); - ct = dw->mime_type; - - /* FIXME: we should stream this to the decoder */ - mem = (CamelStreamMem *)camel_stream_mem_new(); - - if (camel_content_type_is(ct, "multipart", "signed")) { - CamelMultipart *mps = (CamelMultipart *)dw; - - tmp = camel_content_type_param(ct, "protocol"); - if (!CAMEL_IS_MULTIPART_SIGNED(mps) - || tmp == NULL - || g_ascii_strcasecmp(tmp, context->sign_protocol) != 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot verify message signature: Incorrect message format")); - goto fail; - } - - constream = camel_multipart_signed_get_content_stream((CamelMultipartSigned *)mps, ex); - if (constream == NULL) - goto fail; - - sigpart = camel_multipart_get_part(mps, CAMEL_MULTIPART_SIGNED_SIGNATURE); - if (sigpart == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot verify message signature: Incorrect message format")); - goto fail; - } - } else if (camel_content_type_is(ct, "application", "x-pkcs7-mime")) { - sigpart = ipart; - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot verify message signature: Incorrect message format")); - goto fail; - } - - dec = NSS_CMSDecoder_Start(NULL, - NULL, NULL, /* content callback */ - sm_get_passwd, context, /* password callback */ - NULL, NULL); /* decrypt key callback */ - - camel_data_wrapper_decode_to_stream(camel_medium_get_content_object((CamelMedium *)sigpart), (CamelStream *)mem); - (void)NSS_CMSDecoder_Update(dec, mem->buffer->data, mem->buffer->len); - cmsg = NSS_CMSDecoder_Finish(dec); - if (cmsg == NULL) { - camel_exception_setv(ex, 1, "Decoder failed"); - goto fail; - } - - valid = sm_verify_cmsg(context, cmsg, constream, ex); - - NSS_CMSMessage_Destroy(cmsg); -fail: - camel_object_unref(mem); - if (constream) - camel_object_unref(constream); - - return valid; -} - -static int -sm_encrypt(CamelCipherContext *context, const char *userid, GPtrArray *recipients, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex) -{ - struct _CamelSMIMEContextPrivate *p = ((CamelSMIMEContext *)context)->priv; - /*NSSCMSRecipientInfo **recipient_infos;*/ - CERTCertificate **recipient_certs = NULL; - NSSCMSContentInfo *cinfo; - PK11SymKey *bulkkey = NULL; - SECOidTag bulkalgtag; - int bulkkeysize, i; - CK_MECHANISM_TYPE type; - PK11SlotInfo *slot; - PLArenaPool *poolp; - NSSCMSMessage *cmsg = NULL; - NSSCMSEnvelopedData *envd; - NSSCMSEncoderContext *enc = NULL; - CamelStreamMem *mem; - CamelStream *ostream = NULL; - CamelDataWrapper *dw; - CamelContentType *ct; - - poolp = PORT_NewArena(1024); - if (poolp == NULL) { - camel_exception_setv(ex, 1, "Out of memory"); - return -1; - } - - /* Lookup all recipients certs, for later working */ - recipient_certs = (CERTCertificate **)PORT_ArenaZAlloc(poolp, sizeof(*recipient_certs[0])*(recipients->len + 1)); - if (recipient_certs == NULL) { - camel_exception_setv(ex, 1, "Out of memory"); - goto fail; - } - - for (i=0;ilen;i++) { - recipient_certs[i] = CERT_FindCertByNicknameOrEmailAddr(p->certdb, recipients->pdata[i]); - if (recipient_certs[i] == NULL) { - camel_exception_setv(ex, 1, "Can't find certificate for `%s'", recipients->pdata[i]); - goto fail; - } - } - - /* Find a common algorithm, probably 3DES anyway ... */ - if (NSS_SMIMEUtil_FindBulkAlgForRecipients(recipient_certs, &bulkalgtag, &bulkkeysize) != SECSuccess) { - camel_exception_setv(ex, 1, "Can't find common bulk encryption algorithm"); - goto fail; - } - - /* Generate a new bulk key based on the common algorithm - expensive */ - type = PK11_AlgtagToMechanism(bulkalgtag); - slot = PK11_GetBestSlot(type, context); - if (slot == NULL) { - /* PORT_GetError(); ?? */ - camel_exception_setv(ex, 1, "Can't allocate slot for encryption bulk key"); - goto fail; - } - - bulkkey = PK11_KeyGen(slot, type, NULL, bulkkeysize/8, context); - PK11_FreeSlot(slot); - - /* Now we can start building the message */ - /* msg->envelopedData->data */ - cmsg = NSS_CMSMessage_Create(NULL); - if (cmsg == NULL) { - camel_exception_setv(ex, 1, "Can't create CMS Message"); - goto fail; - } - - envd = NSS_CMSEnvelopedData_Create(cmsg, bulkalgtag, bulkkeysize); - if (envd == NULL) { - camel_exception_setv(ex, 1, "Can't create CMS EnvelopedData"); - goto fail; - } - - cinfo = NSS_CMSMessage_GetContentInfo(cmsg); - if (NSS_CMSContentInfo_SetContent_EnvelopedData(cmsg, cinfo, envd) != SECSuccess) { - camel_exception_setv(ex, 1, "Can't attach CMS EnvelopedData"); - goto fail; - } - - cinfo = NSS_CMSEnvelopedData_GetContentInfo(envd); - if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, PR_FALSE) != SECSuccess) { - camel_exception_setv(ex, 1, "Can't attach CMS data object"); - goto fail; - } - - /* add recipient certs */ - for (i=0;recipient_certs[i];i++) { - NSSCMSRecipientInfo *ri = NSS_CMSRecipientInfo_Create(cmsg, recipient_certs[i]); - - if (ri == NULL) { - camel_exception_setv(ex, 1, "Can't create CMS RecipientInfo"); - goto fail; - } - - if (NSS_CMSEnvelopedData_AddRecipient(envd, ri) != SECSuccess) { - camel_exception_setv(ex, 1, "Can't add CMS RecipientInfo"); - goto fail; - } - } - - /* dump it out */ - ostream = camel_stream_mem_new(); - enc = NSS_CMSEncoder_Start(cmsg, - sm_write_stream, ostream, - NULL, NULL, - sm_get_passwd, context, - sm_decrypt_key, bulkkey, - NULL, NULL); - if (enc == NULL) { - camel_exception_setv(ex, 1, "Can't create encoder context"); - goto fail; - } - - /* FIXME: Stream the input */ - /* FIXME: Canonicalise the input? */ - mem = (CamelStreamMem *)camel_stream_mem_new(); - camel_data_wrapper_write_to_stream((CamelDataWrapper *)ipart, (CamelStream *)mem); - if (NSS_CMSEncoder_Update(enc, mem->buffer->data, mem->buffer->len) != SECSuccess) { - NSS_CMSEncoder_Cancel(enc); - camel_object_unref(mem); - camel_exception_setv(ex, 1, "Failed to add data to encoder"); - goto fail; - } - camel_object_unref(mem); - - if (NSS_CMSEncoder_Finish(enc) != SECSuccess) { - camel_exception_setv(ex, 1, "Failed to encode data"); - goto fail; - } - - PK11_FreeSymKey(bulkkey); - NSS_CMSMessage_Destroy(cmsg); - for (i=0;recipient_certs[i];i++) - CERT_DestroyCertificate(recipient_certs[i]); - PORT_FreeArena(poolp, PR_FALSE); - - dw = camel_data_wrapper_new(); - camel_data_wrapper_construct_from_stream(dw, ostream); - camel_object_unref(ostream); - dw->encoding = CAMEL_TRANSFER_ENCODING_BINARY; - - ct = camel_content_type_new("application", "x-pkcs7-mime"); - camel_content_type_set_param(ct, "name", "smime.p7m"); - camel_content_type_set_param(ct, "smime-type", "enveloped-data"); - camel_data_wrapper_set_mime_type_field(dw, ct); - camel_content_type_unref(ct); - - camel_medium_set_content_object((CamelMedium *)opart, dw); - camel_object_unref(dw); - - camel_mime_part_set_disposition(opart, "attachment"); - camel_mime_part_set_filename(opart, "smime.p7m"); - camel_mime_part_set_description(opart, "S/MIME Encrypted Message"); - camel_mime_part_set_encoding(opart, CAMEL_TRANSFER_ENCODING_BASE64); - - return 0; - -fail: - if (ostream) - camel_object_unref(ostream); - if (cmsg) - NSS_CMSMessage_Destroy(cmsg); - if (bulkkey) - PK11_FreeSymKey(bulkkey); - - if (recipient_certs) { - for (i=0;recipient_certs[i];i++) - CERT_DestroyCertificate(recipient_certs[i]); - } - - PORT_FreeArena(poolp, PR_FALSE); - - return -1; -} - -static CamelCipherValidity * -sm_decrypt(CamelCipherContext *context, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex) -{ - NSSCMSDecoderContext *dec; - NSSCMSMessage *cmsg; - CamelStreamMem *istream; - CamelStream *ostream; - CamelCipherValidity *valid = NULL; - - /* FIXME: This assumes the content is only encrypted. Perhaps its ok for - this api to do this ... */ - - ostream = camel_stream_mem_new(); - - /* FIXME: stream this to the decoder incrementally */ - istream = (CamelStreamMem *)camel_stream_mem_new(); - camel_data_wrapper_decode_to_stream(camel_medium_get_content_object((CamelMedium *)ipart), (CamelStream *)istream); - camel_stream_reset((CamelStream *)istream); - - dec = NSS_CMSDecoder_Start(NULL, - sm_write_stream, ostream, /* content callback */ - sm_get_passwd, context, /* password callback */ - NULL, NULL); /* decrypt key callback */ - - if (NSS_CMSDecoder_Update(dec, istream->buffer->data, istream->buffer->len) != SECSuccess) { - printf("decoder update failed\n"); - } - camel_object_unref(istream); - - cmsg = NSS_CMSDecoder_Finish(dec); - if (cmsg == NULL) { - camel_exception_setv(ex, 1, "Decoder failed, error %d", PORT_GetError()); - goto fail; - } - -#if 0 - /* not sure if we really care about this? */ - if (!NSS_CMSMessage_IsEncrypted(cmsg)) { - camel_exception_setv(ex, 1, "S/MIME Decrypt: No encrypted content found"); - NSS_CMSMessage_Destroy(cmsg); - goto fail; - } -#endif - - camel_stream_reset(ostream); - camel_data_wrapper_construct_from_stream((CamelDataWrapper *)opart, ostream); - - if (NSS_CMSMessage_IsSigned(cmsg)) { - valid = sm_verify_cmsg(context, cmsg, NULL, ex); - } else { - valid = camel_cipher_validity_new(); - valid->encrypt.description = g_strdup(_("Encrypted content")); - valid->encrypt.status = CAMEL_CIPHER_VALIDITY_ENCRYPT_ENCRYPTED; - } - - NSS_CMSMessage_Destroy(cmsg); -fail: - camel_object_unref(ostream); - - return valid; -} - -static int -sm_import_keys(CamelCipherContext *context, CamelStream *istream, CamelException *ex) -{ - camel_exception_setv(ex, 1, "import keys: unimplemented"); - - return -1; -} - -static int -sm_export_keys(CamelCipherContext *context, GPtrArray *keys, CamelStream *ostream, CamelException *ex) -{ - camel_exception_setv(ex, 1, "export keys: unimplemented"); - - return -1; -} - -/* ********************************************************************** */ - -static void -camel_smime_context_class_init(CamelSMIMEContextClass *klass) -{ - CamelCipherContextClass *cipher_class = CAMEL_CIPHER_CONTEXT_CLASS(klass); - - parent_class = CAMEL_CIPHER_CONTEXT_CLASS(camel_type_get_global_classfuncs(camel_cipher_context_get_type())); - - cipher_class->hash_to_id = sm_hash_to_id; - cipher_class->id_to_hash = sm_id_to_hash; - cipher_class->sign = sm_sign; - cipher_class->verify = sm_verify; - cipher_class->encrypt = sm_encrypt; - cipher_class->decrypt = sm_decrypt; - cipher_class->import_keys = sm_import_keys; - cipher_class->export_keys = sm_export_keys; -} - -static void -camel_smime_context_init(CamelSMIMEContext *context) -{ - CamelCipherContext *cipher =(CamelCipherContext *) context; - - cipher->sign_protocol = "application/x-pkcs7-signature"; - cipher->encrypt_protocol = "application/x-pkcs7-mime"; - cipher->key_protocol = "application/x-pkcs7-signature"; - - context->priv = g_malloc0(sizeof(*context->priv)); - context->priv->certdb = CERT_GetDefaultCertDB(); - context->priv->sign_mode = CAMEL_SMIME_SIGN_CLEARSIGN; -} - -static void -camel_smime_context_finalise(CamelObject *object) -{ - CamelSMIMEContext *context = (CamelSMIMEContext *)object; - - /* FIXME: do we have to free the certdb? */ - - g_free(context->priv); -} - -CamelType -camel_smime_context_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_cipher_context_get_type(), - "CamelSMIMEContext", - sizeof(CamelSMIMEContext), - sizeof(CamelSMIMEContextClass), - (CamelObjectClassInitFunc) camel_smime_context_class_init, - NULL, - (CamelObjectInitFunc) camel_smime_context_init, - (CamelObjectFinalizeFunc) camel_smime_context_finalise); - } - - return type; -} diff --git a/camel/camel-smime-context.h b/camel/camel-smime-context.h deleted file mode 100644 index 19f0e8464b..0000000000 --- a/camel/camel-smime-context.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * Michael Zucchi - * - * Copyright 2002,2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __CAMEL_SMIME_CONTEXT_H__ -#define __CAMEL_SMIME_CONTEXT_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#define CAMEL_SMIME_CONTEXT_TYPE (camel_smime_context_get_type()) -#define CAMEL_SMIME_CONTEXT(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SMIME_CONTEXT_TYPE, CamelSMIMEContext)) -#define CAMEL_SMIME_CONTEXT_CLASS(k)(CAMEL_CHECK_CLASS_CAST((k), CAMEL_SMIME_CONTEXT_TYPE, CamelSMIMEContextClass)) -#define CAMEL_IS_SMIME_CONTEXT(o) (CAMEL_CHECK_TYPE((o), CAMEL_SMIME_CONTEXT_TYPE)) - -typedef enum _camel_smime_sign_t { - CAMEL_SMIME_SIGN_CLEARSIGN, - CAMEL_SMIME_SIGN_ENVELOPED -} camel_smime_sign_t; - -typedef enum _camel_smime_describe_t { - CAMEL_SMIME_SIGNED = 1<<0, - CAMEL_SMIME_ENCRYPTED = 1<<1, - CAMEL_SMIME_CERTS = 1<<2, - CAMEL_SMIME_CRLS = 1<<3, -} camel_smime_describe_t; - -typedef struct _CamelSMIMEContext CamelSMIMEContext; -typedef struct _CamelSMIMEContextClass CamelSMIMEContextClass; - -struct _CamelSMIMEContext { - CamelCipherContext cipher; - - struct _CamelSMIMEContextPrivate *priv; -}; - -struct _CamelSMIMEContextClass { - CamelCipherContextClass cipher_class; -}; - -CamelType camel_smime_context_get_type(void); - -CamelCipherContext *camel_smime_context_new(CamelSession *session); - -/* nick to use for SMIMEEncKeyPrefs attribute for signed data */ -void camel_smime_context_set_encrypt_key(CamelSMIMEContext *context, gboolean use, const char *key); -/* set signing mode, clearsigned multipart/signed or enveloped */ -void camel_smime_context_set_sign_mode(CamelSMIMEContext *context, camel_smime_sign_t type); - -guint32 camel_smime_context_describe_part(CamelSMIMEContext *, struct _CamelMimePart *); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_SMIME_CONTEXT_H__ */ diff --git a/camel/camel-store-summary.c b/camel/camel-store-summary.c deleted file mode 100644 index 86e42fc98c..0000000000 --- a/camel/camel-store-summary.c +++ /dev/null @@ -1,928 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2001-2003 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "camel-store-summary.h" - -#include "camel-file-utils.h" - -#include "e-util/md5-utils.h" -#include "e-util/e-memory.h" - -#include "camel-private.h" -#include "camel-url.h" - -#define d(x) -#define io(x) /* io debug */ - -/* possible versions, for versioning changes */ -#define CAMEL_STORE_SUMMARY_VERSION_0 (1) - -/* current version */ -#define CAMEL_STORE_SUMMARY_VERSION (1) - -#define _PRIVATE(o) (((CamelStoreSummary *)(o))->priv) - -static int summary_header_load(CamelStoreSummary *, FILE *); -static int summary_header_save(CamelStoreSummary *, FILE *); - -static CamelStoreInfo * store_info_new(CamelStoreSummary *, const char *); -static CamelStoreInfo * store_info_load(CamelStoreSummary *, FILE *); -static int store_info_save(CamelStoreSummary *, FILE *, CamelStoreInfo *); -static void store_info_free(CamelStoreSummary *, CamelStoreInfo *); - -static const char *store_info_string(CamelStoreSummary *, const CamelStoreInfo *, int); -static void store_info_set_string(CamelStoreSummary *, CamelStoreInfo *, int, const char *); - -static void camel_store_summary_class_init (CamelStoreSummaryClass *klass); -static void camel_store_summary_init (CamelStoreSummary *obj); -static void camel_store_summary_finalise (CamelObject *obj); - -static CamelObjectClass *camel_store_summary_parent; - -static void -camel_store_summary_class_init (CamelStoreSummaryClass *klass) -{ - camel_store_summary_parent = camel_type_get_global_classfuncs (camel_object_get_type ()); - - klass->summary_header_load = summary_header_load; - klass->summary_header_save = summary_header_save; - - klass->store_info_new = store_info_new; - klass->store_info_load = store_info_load; - klass->store_info_save = store_info_save; - klass->store_info_free = store_info_free; - - klass->store_info_string = store_info_string; - klass->store_info_set_string = store_info_set_string; -} - -static void -camel_store_summary_init (CamelStoreSummary *s) -{ - struct _CamelStoreSummaryPrivate *p; - - p = _PRIVATE(s) = g_malloc0(sizeof(*p)); - - s->store_info_size = sizeof(CamelStoreInfo); - - s->store_info_chunks = NULL; - - s->version = CAMEL_STORE_SUMMARY_VERSION; - s->flags = 0; - s->count = 0; - s->time = 0; - - s->folders = g_ptr_array_new(); - s->folders_path = g_hash_table_new(g_str_hash, g_str_equal); - - p->summary_lock = g_mutex_new(); - p->io_lock = g_mutex_new(); - p->alloc_lock = g_mutex_new(); - p->ref_lock = g_mutex_new(); -} - -static void -camel_store_summary_finalise (CamelObject *obj) -{ - struct _CamelStoreSummaryPrivate *p; - CamelStoreSummary *s = (CamelStoreSummary *)obj; - - p = _PRIVATE(obj); - - camel_store_summary_clear(s); - g_ptr_array_free(s->folders, TRUE); - g_hash_table_destroy(s->folders_path); - - g_free(s->summary_path); - - if (s->store_info_chunks) - e_memchunk_destroy(s->store_info_chunks); - - g_mutex_free(p->summary_lock); - g_mutex_free(p->io_lock); - g_mutex_free(p->alloc_lock); - g_mutex_free(p->ref_lock); - - g_free(p); -} - -CamelType -camel_store_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_object_get_type (), "CamelStoreSummary", - sizeof (CamelStoreSummary), - sizeof (CamelStoreSummaryClass), - (CamelObjectClassInitFunc) camel_store_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_store_summary_init, - (CamelObjectFinalizeFunc) camel_store_summary_finalise); - } - - return type; -} - -/** - * camel_store_summary_new: - * - * Create a new CamelStoreSummary object. - * - * Return value: A new CamelStoreSummary widget. - **/ -CamelStoreSummary * -camel_store_summary_new (void) -{ - CamelStoreSummary *new = CAMEL_STORE_SUMMARY ( camel_object_new (camel_store_summary_get_type ())); return new; -} - -/** - * camel_store_summary_set_filename: - * @s: - * @name: - * - * Set the filename where the summary will be loaded to/saved from. - **/ -void camel_store_summary_set_filename(CamelStoreSummary *s, const char *name) -{ - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - - g_free(s->summary_path); - s->summary_path = g_strdup(name); - - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); -} - -void camel_store_summary_set_uri_base(CamelStoreSummary *s, CamelURL *base) -{ - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - - if (s->uri_base) - camel_url_free(s->uri_base); - s->uri_base = camel_url_new_with_base(base, ""); - - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); -} - -/** - * camel_store_summary_count: - * @s: - * - * Get the number of summary items stored in this summary. - * - * Return value: The number of items int he summary. - **/ -int -camel_store_summary_count(CamelStoreSummary *s) -{ - return s->folders->len; -} - -/** - * camel_store_summary_index: - * @s: - * @i: - * - * Retrieve a summary item by index number. - * - * A referenced to the summary item is returned, which may be - * ref'd or free'd as appropriate. - * - * Return value: The summary item, or NULL if the index @i is out - * of range. - * It must be freed using camel_store_summary_info_free(). - **/ -CamelStoreInfo * -camel_store_summary_index(CamelStoreSummary *s, int i) -{ - CamelStoreInfo *info = NULL; - - CAMEL_STORE_SUMMARY_LOCK(s, ref_lock); - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - - if (ifolders->len) - info = g_ptr_array_index(s->folders, i); - - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - - if (info) - info->refcount++; - - CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock); - - return info; -} - -/** - * camel_store_summary_index: - * @s: - * @i: - * - * Obtain a copy of the summary array. This is done atomically, - * so cannot contain empty entries. - * - * It must be freed using camel_store_summary_array_free(). - **/ -GPtrArray * -camel_store_summary_array(CamelStoreSummary *s) -{ - CamelStoreInfo *info; - GPtrArray *res = g_ptr_array_new(); - int i; - - CAMEL_STORE_SUMMARY_LOCK(s, ref_lock); - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - - g_ptr_array_set_size(res, s->folders->len); - for (i=0;ifolders->len;i++) { - info = res->pdata[i] = g_ptr_array_index(s->folders, i); - info->refcount++; - } - - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock); - - return res; -} - -/** - * camel_store_summary_array_free: - * @s: - * @array: - * - * Free the folder summary array. - **/ -void -camel_store_summary_array_free(CamelStoreSummary *s, GPtrArray *array) -{ - int i; - - for (i=0;ilen;i++) - camel_store_summary_info_free(s, array->pdata[i]); - - g_ptr_array_free(array, TRUE); -} - -/** - * camel_store_summary_path: - * @s: - * @path: - * - * Retrieve a summary item by path name. - * - * A referenced to the summary item is returned, which may be - * ref'd or free'd as appropriate. - * - * Return value: The summary item, or NULL if the @path name - * is not available. - * It must be freed using camel_store_summary_info_free(). - **/ -CamelStoreInfo * -camel_store_summary_path(CamelStoreSummary *s, const char *path) -{ - CamelStoreInfo *info; - - CAMEL_STORE_SUMMARY_LOCK(s, ref_lock); - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - - info = g_hash_table_lookup(s->folders_path, path); - - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - - if (info) - info->refcount++; - - CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock); - - return info; -} - -int -camel_store_summary_load(CamelStoreSummary *s) -{ - FILE *in; - int i; - CamelStoreInfo *mi; - - g_assert(s->summary_path); - - in = fopen(s->summary_path, "r"); - if (in == NULL) - return -1; - - CAMEL_STORE_SUMMARY_LOCK(s, io_lock); - if ( ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s, in) == -1) - goto error; - - /* now read in each message ... */ - for (i=0;icount;i++) { - mi = ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->store_info_load(s, in); - - if (mi == NULL) - goto error; - - camel_store_summary_add(s, mi); - } - - CAMEL_STORE_SUMMARY_UNLOCK(s, io_lock); - - if (fclose (in) != 0) - return -1; - - s->flags &= ~CAMEL_STORE_SUMMARY_DIRTY; - - return 0; - -error: - i = ferror (in); - g_warning ("Cannot load summary file: %s", strerror (ferror (in))); - CAMEL_STORE_SUMMARY_UNLOCK(s, io_lock); - fclose (in); - s->flags |= ~CAMEL_STORE_SUMMARY_DIRTY; - errno = i; - - return -1; -} - -/** - * camel_store_summary_save: - * @s: - * - * Writes the summary to disk. The summary is only written if changes - * have occured. - * - * Return value: Returns -1 on error. - **/ -int -camel_store_summary_save(CamelStoreSummary *s) -{ - FILE *out; - int fd; - int i; - guint32 count; - CamelStoreInfo *mi; - - g_assert(s->summary_path); - - io(printf("** saving summary\n")); - - if ((s->flags & CAMEL_STORE_SUMMARY_DIRTY) == 0) { - io(printf("** summary clean no save\n")); - return 0; - } - - fd = open(s->summary_path, O_RDWR|O_CREAT|O_TRUNC, 0600); - if (fd == -1) { - io(printf("** open error: %s\n", strerror (errno))); - return -1; - } - out = fdopen(fd, "w"); - if ( out == NULL ) { - i = errno; - printf("** fdopen error: %s\n", strerror (errno)); - close(fd); - errno = i; - return -1; - } - - io(printf("saving header\n")); - - CAMEL_STORE_SUMMARY_LOCK(s, io_lock); - - if ( ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_save(s, out) == -1) { - i = errno; - fclose(out); - CAMEL_STORE_SUMMARY_UNLOCK(s, io_lock); - errno = i; - return -1; - } - - /* now write out each message ... */ - - /* FIXME: Locking? */ - - count = s->folders->len; - for (i=0;ifolders->pdata[i]; - ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->store_info_save(s, out, mi); - } - - CAMEL_STORE_SUMMARY_UNLOCK(s, io_lock); - - if (fflush (out) != 0 || fsync (fileno (out)) == -1) { - i = errno; - fclose (out); - errno = i; - return -1; - } - - if (fclose (out) != 0) - return -1; - - s->flags &= ~CAMEL_STORE_SUMMARY_DIRTY; - return 0; -} - -/** - * camel_store_summary_header_load: - * @s: Summary object. - * - * Only load the header information from the summary, - * keep the rest on disk. This should only be done on - * a fresh summary object. - * - * Return value: -1 on error. - **/ -int camel_store_summary_header_load(CamelStoreSummary *s) -{ - FILE *in; - int ret; - - g_assert(s->summary_path); - - in = fopen(s->summary_path, "r"); - if (in == NULL) - return -1; - - CAMEL_STORE_SUMMARY_LOCK(s, io_lock); - ret = ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s, in); - CAMEL_STORE_SUMMARY_UNLOCK(s, io_lock); - - fclose(in); - s->flags &= ~CAMEL_STORE_SUMMARY_DIRTY; - return ret; -} - -/** - * camel_store_summary_add: - * @s: - * @info: - * - * Adds a new @info record to the summary. If @info->uid is NULL, then a new - * uid is automatically re-assigned by calling :next_uid_string(). - * - * The @info record should have been generated by calling one of the - * info_new_*() functions, as it will be free'd based on the summary - * class. And MUST NOT be allocated directly using malloc. - **/ -void camel_store_summary_add(CamelStoreSummary *s, CamelStoreInfo *info) -{ - if (info == NULL) - return; - - if (camel_store_info_path(s, info) == NULL) { - g_warning("Trying to add a folder info with missing required path name\n"); - return; - } - - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - - g_ptr_array_add(s->folders, info); - g_hash_table_insert(s->folders_path, (char *)camel_store_info_path(s, info), info); - s->flags |= CAMEL_STORE_SUMMARY_DIRTY; - - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); -} - -/** - * camel_store_summary_add_from_path: - * @s: - * @h: - * - * Build a new info record based on the name, and add it to the summary. - * - * Return value: The newly added record. - **/ -CamelStoreInfo *camel_store_summary_add_from_path(CamelStoreSummary *s, const char *path) -{ - CamelStoreInfo *info; - - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - - info = g_hash_table_lookup(s->folders_path, path); - if (info != NULL) { - g_warning("Trying to add folder '%s' to summary that already has it", path); - info = NULL; - } else { - info = camel_store_summary_info_new_from_path(s, path); - g_ptr_array_add(s->folders, info); - g_hash_table_insert(s->folders_path, (char *)camel_store_info_path(s, info), info); - s->flags |= CAMEL_STORE_SUMMARY_DIRTY; - } - - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - - return info; -} - -/** - * camel_store_summary_info_new_from_path: - * @s: - * @h: - * - * Create a new info record from a name. - * - * Return value: Guess? This info record MUST be freed using - * camel_store_summary_info_free(), camel_store_info_free() will not work. - **/ -CamelStoreInfo *camel_store_summary_info_new_from_path(CamelStoreSummary *s, const char *f) -{ - return ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s))) -> store_info_new(s, f); -} - -/** - * camel_store_summary_info_free: - * @s: - * @mi: - * - * Unref and potentially free the message info @mi, and all associated memory. - **/ -void camel_store_summary_info_free(CamelStoreSummary *s, CamelStoreInfo *mi) -{ - g_assert(mi); - g_assert(s); - - CAMEL_STORE_SUMMARY_LOCK(s, ref_lock); - - g_assert(mi->refcount >= 1); - - mi->refcount--; - if (mi->refcount > 0) { - CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock); - return; - } - - CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock); - - ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->store_info_free(s, mi); -} - -/** - * camel_store_summary_info_ref: - * @s: - * @mi: - * - * Add an extra reference to @mi. - **/ -void camel_store_summary_info_ref(CamelStoreSummary *s, CamelStoreInfo *mi) -{ - g_assert(mi); - g_assert(s); - - CAMEL_STORE_SUMMARY_LOCK(s, ref_lock); - g_assert(mi->refcount >= 1); - mi->refcount++; - CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock); -} - -/** - * camel_store_summary_touch: - * @s: - * - * Mark the summary as changed, so that a save will save it. - **/ -void -camel_store_summary_touch(CamelStoreSummary *s) -{ - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - s->flags |= CAMEL_STORE_SUMMARY_DIRTY; - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); -} - -/** - * camel_store_summary_clear: - * @s: - * - * Empty the summary contents. - **/ -void -camel_store_summary_clear(CamelStoreSummary *s) -{ - int i; - - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - if (camel_store_summary_count(s) == 0) { - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - return; - } - - for (i=0;ifolders->len;i++) - camel_store_summary_info_free(s, s->folders->pdata[i]); - - g_ptr_array_set_size(s->folders, 0); - g_hash_table_destroy(s->folders_path); - s->folders_path = g_hash_table_new(g_str_hash, g_str_equal); - s->flags |= CAMEL_STORE_SUMMARY_DIRTY; - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); -} - -/** - * camel_store_summary_remove: - * @s: - * @info: - * - * Remove a specific @info record from the summary. - **/ -void camel_store_summary_remove(CamelStoreSummary *s, CamelStoreInfo *info) -{ - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - g_hash_table_remove(s->folders_path, camel_store_info_path(s, info)); - g_ptr_array_remove(s->folders, info); - s->flags |= CAMEL_STORE_SUMMARY_DIRTY; - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - - camel_store_summary_info_free(s, info); -} - -/** - * camel_store_summary_remove_uid: - * @s: - * @path: - * - * Remove a specific info record from the summary, by @path. - **/ -void camel_store_summary_remove_path(CamelStoreSummary *s, const char *path) -{ - CamelStoreInfo *oldinfo; - char *oldpath; - - CAMEL_STORE_SUMMARY_LOCK(s, ref_lock); - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - if (g_hash_table_lookup_extended(s->folders_path, path, (void *)&oldpath, (void *)&oldinfo)) { - /* make sure it doesn't vanish while we're removing it */ - oldinfo->refcount++; - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock); - camel_store_summary_remove(s, oldinfo); - camel_store_summary_info_free(s, oldinfo); - } else { - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock); - } -} - -/** - * camel_store_summary_remove_index: - * @s: - * @index: - * - * Remove a specific info record from the summary, by index. - **/ -void camel_store_summary_remove_index(CamelStoreSummary *s, int index) -{ - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - if (index < s->folders->len) { - CamelStoreInfo *info = s->folders->pdata[index]; - - g_hash_table_remove(s->folders_path, camel_store_info_path(s, info)); - g_ptr_array_remove_index(s->folders, index); - s->flags |= CAMEL_STORE_SUMMARY_DIRTY; - - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - camel_store_summary_info_free(s, info); - } else { - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - } -} - -static int -summary_header_load(CamelStoreSummary *s, FILE *in) -{ - gint32 version, flags, count; - time_t time; - - fseek(in, 0, SEEK_SET); - - io(printf("Loading header\n")); - - if (camel_file_util_decode_fixed_int32(in, &version) == -1 - || camel_file_util_decode_fixed_int32(in, &flags) == -1 - || camel_file_util_decode_time_t(in, &time) == -1 - || camel_file_util_decode_fixed_int32(in, &count) == -1) { - return -1; - } - - s->flags = flags; - s->time = time; - s->count = count; - s->version = version; - - if (version < CAMEL_STORE_SUMMARY_VERSION_0) { - g_warning("Store summary header version too low"); - return -1; - } - - return 0; -} - -static int -summary_header_save(CamelStoreSummary *s, FILE *out) -{ - fseek(out, 0, SEEK_SET); - - io(printf("Savining header\n")); - - /* always write latest version */ - camel_file_util_encode_fixed_int32(out, CAMEL_STORE_SUMMARY_VERSION); - camel_file_util_encode_fixed_int32(out, s->flags); - camel_file_util_encode_time_t(out, s->time); - return camel_file_util_encode_fixed_int32(out, camel_store_summary_count(s)); -} - -/** - * camel_store_summary_info_new: - * @s: - * - * Allocate a new camel message info, suitable for adding - * to this summary. - * - * Return value: - **/ -CamelStoreInfo * -camel_store_summary_info_new(CamelStoreSummary *s) -{ - CamelStoreInfo *mi; - - CAMEL_STORE_SUMMARY_LOCK(s, alloc_lock); - if (s->store_info_chunks == NULL) - s->store_info_chunks = e_memchunk_new(32, s->store_info_size); - mi = e_memchunk_alloc0(s->store_info_chunks); - CAMEL_STORE_SUMMARY_UNLOCK(s, alloc_lock); - mi->refcount = 1; - return mi; -} - -const char *camel_store_info_string(CamelStoreSummary *s, const CamelStoreInfo *mi, int type) -{ - return ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->store_info_string(s, mi, type); -} - -void camel_store_info_set_string(CamelStoreSummary *s, CamelStoreInfo *mi, int type, const char *value) -{ - ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->store_info_set_string(s, mi, type, value); -} - -static CamelStoreInfo * -store_info_new(CamelStoreSummary *s, const char *f) -{ - CamelStoreInfo *mi; - - mi = camel_store_summary_info_new(s); - - mi->path = g_strdup(f); - mi->unread = CAMEL_STORE_INFO_FOLDER_UNKNOWN; - mi->total = CAMEL_STORE_INFO_FOLDER_UNKNOWN; - - return mi; -} - -static CamelStoreInfo * -store_info_load(CamelStoreSummary *s, FILE *in) -{ - CamelStoreInfo *mi; - - mi = camel_store_summary_info_new(s); - - io(printf("Loading folder info\n")); - - camel_file_util_decode_string(in, &mi->path); - camel_file_util_decode_uint32(in, &mi->flags); - camel_file_util_decode_uint32(in, &mi->unread); - camel_file_util_decode_uint32(in, &mi->total); - - if (!ferror(in)) - return mi; - - camel_store_summary_info_free(s, mi); - - return NULL; -} - -static int -store_info_save(CamelStoreSummary *s, FILE *out, CamelStoreInfo *mi) -{ - io(printf("Saving folder info\n")); - - camel_file_util_encode_string(out, camel_store_info_path(s, mi)); - camel_file_util_encode_uint32(out, mi->flags); - camel_file_util_encode_uint32(out, mi->unread); - camel_file_util_encode_uint32(out, mi->total); - - return ferror(out); -} - -static void -store_info_free(CamelStoreSummary *s, CamelStoreInfo *mi) -{ - g_free(mi->path); - g_free(mi->uri); - e_memchunk_free(s->store_info_chunks, mi); -} - -static const char * -store_info_string(CamelStoreSummary *s, const CamelStoreInfo *mi, int type) -{ - const char *p; - - /* FIXME: Locks? */ - - g_assert (mi != NULL); - - switch (type) { - case CAMEL_STORE_INFO_PATH: - return mi->path; - case CAMEL_STORE_INFO_NAME: - p = strrchr(mi->path, '/'); - if (p) - return p+1; - else - return mi->path; - case CAMEL_STORE_INFO_URI: - if (mi->uri == NULL) { - CamelURL *uri; - - uri = camel_url_new_with_base(s->uri_base, mi->path); - ((CamelStoreInfo *)mi)->uri = camel_url_to_string(uri, 0); - camel_url_free(uri); - } - return mi->uri; - } - - return ""; -} - -static void -store_info_set_string (CamelStoreSummary *s, CamelStoreInfo *mi, int type, const char *str) -{ - const char *p; - char *v; - int len; - - g_assert (mi != NULL); - - switch(type) { - case CAMEL_STORE_INFO_PATH: - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - g_hash_table_remove(s->folders_path, (char *)camel_store_info_path(s, mi)); - g_free(mi->path); - g_free(mi->uri); - mi->path = g_strdup(str); - g_hash_table_insert(s->folders_path, (char *)camel_store_info_path(s, mi), mi); - s->flags |= CAMEL_STORE_SUMMARY_DIRTY; - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - break; - case CAMEL_STORE_INFO_NAME: - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - g_hash_table_remove(s->folders_path, (char *)camel_store_info_path(s, mi)); - p = strrchr(mi->path, '/'); - if (p) { - len = p-mi->path+1; - v = g_malloc(len+strlen(str)+1); - memcpy(v, mi->path, len); - strcpy(v+len, str); - } else { - v = g_strdup(str); - } - g_free(mi->path); - mi->path = v; - g_hash_table_insert(s->folders_path, (char *)camel_store_info_path(s, mi), mi); - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - break; - case CAMEL_STORE_INFO_URI: - g_warning("Cannot set store info uri, aborting"); - abort(); - break; - } -} diff --git a/camel/camel-store-summary.h b/camel/camel-store-summary.h deleted file mode 100644 index dbcd6119b7..0000000000 --- a/camel/camel-store-summary.h +++ /dev/null @@ -1,176 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_STORE_SUMMARY_H -#define _CAMEL_STORE_SUMMARY_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#include - -#include -#include -#include - -#define CAMEL_STORE_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_store_summary_get_type (), CamelStoreSummary) -#define CAMEL_STORE_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_store_summary_get_type (), CamelStoreSummaryClass) -#define CAMEL_IS_STORE_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_store_summary_get_type ()) - -typedef struct _CamelStoreSummary CamelStoreSummary; -typedef struct _CamelStoreSummaryClass CamelStoreSummaryClass; - -typedef struct _CamelStoreInfo CamelStoreInfo; - -enum _CamelStoreInfoFlags { - CAMEL_STORE_INFO_FOLDER_NOSELECT, - CAMEL_STORE_INFO_FOLDER_READONLY, - CAMEL_STORE_INFO_FOLDER_SUBSCRIBED, - CAMEL_STORE_INFO_FOLDER_FLAGGED, -}; - -#define CAMEL_STORE_INFO_FOLDER_UNKNOWN (~0) - -enum { - CAMEL_STORE_INFO_PATH = 0, - CAMEL_STORE_INFO_NAME, - CAMEL_STORE_INFO_URI, - CAMEL_STORE_INFO_LAST, -}; - -struct _CamelStoreInfo { - guint32 refcount; - char *uri; - char *path; - guint32 flags; - guint32 unread; - guint32 total; -}; - -enum _CamelStoreSummaryFlags { - CAMEL_STORE_SUMMARY_DIRTY = 1<<0, - CAMEL_STORE_SUMMARY_FRAGMENT = 1<<1, /* path name is stored in fragment rather than path */ -}; - -struct _CamelStoreSummary { - CamelObject parent; - - struct _CamelStoreSummaryPrivate *priv; - - /* header info */ - guint32 version; /* version of base part of file */ - guint32 flags; /* flags */ - guint32 count; /* how many were saved/loaded */ - time_t time; /* timestamp for this summary (for implementors to use) */ - struct _CamelURL *uri_base; /* url of base part of summary */ - - /* sizes of memory objects */ - guint32 store_info_size; - - /* memory allocators (setup automatically) */ - struct _EMemChunk *store_info_chunks; - - char *summary_path; - - GPtrArray *folders; /* CamelStoreInfo's */ - GHashTable *folders_path; /* CamelStoreInfo's by path name */ -}; - -struct _CamelStoreSummaryClass { - CamelObjectClass parent_class; - - /* load/save the global info */ - int (*summary_header_load)(CamelStoreSummary *, FILE *); - int (*summary_header_save)(CamelStoreSummary *, FILE *); - - /* create/save/load an individual message info */ - CamelStoreInfo * (*store_info_new)(CamelStoreSummary *, const char *path); - CamelStoreInfo * (*store_info_load)(CamelStoreSummary *, FILE *); - int (*store_info_save)(CamelStoreSummary *, FILE *, CamelStoreInfo *); - void (*store_info_free)(CamelStoreSummary *, CamelStoreInfo *); - - /* virtualise access methods */ - const char *(*store_info_string)(CamelStoreSummary *, const CamelStoreInfo *, int); - void (*store_info_set_string)(CamelStoreSummary *, CamelStoreInfo *, int, const char *); -}; - -CamelType camel_store_summary_get_type (void); -CamelStoreSummary *camel_store_summary_new (void); - -void camel_store_summary_set_filename(CamelStoreSummary *, const char *); -void camel_store_summary_set_uri_base(CamelStoreSummary *s, CamelURL *base); - -/* load/save the summary in its entirety */ -int camel_store_summary_load(CamelStoreSummary *); -int camel_store_summary_save(CamelStoreSummary *); - -/* only load the header */ -int camel_store_summary_header_load(CamelStoreSummary *); - -/* set the dirty bit on the summary */ -void camel_store_summary_touch(CamelStoreSummary *s); - -/* add a new raw summary item */ -void camel_store_summary_add(CamelStoreSummary *, CamelStoreInfo *info); - -/* build/add raw summary items */ -CamelStoreInfo *camel_store_summary_add_from_path(CamelStoreSummary *, const char *); - -/* Just build raw summary items */ -CamelStoreInfo *camel_store_summary_info_new(CamelStoreSummary *s); -CamelStoreInfo *camel_store_summary_info_new_from_path(CamelStoreSummary *s, const char *); - -void camel_store_summary_info_ref(CamelStoreSummary *, CamelStoreInfo *); -void camel_store_summary_info_free(CamelStoreSummary *, CamelStoreInfo *); - -/* removes a summary item */ -void camel_store_summary_remove(CamelStoreSummary *s, CamelStoreInfo *info); -void camel_store_summary_remove_path(CamelStoreSummary *s, const char *path); -void camel_store_summary_remove_index(CamelStoreSummary *s, int); - -/* remove all items */ -void camel_store_summary_clear(CamelStoreSummary *s); - -/* lookup functions */ -int camel_store_summary_count(CamelStoreSummary *); -CamelStoreInfo *camel_store_summary_index(CamelStoreSummary *, int); -CamelStoreInfo *camel_store_summary_path(CamelStoreSummary *, const char *uid); -GPtrArray *camel_store_summary_array(CamelStoreSummary *s); -void camel_store_summary_array_free(CamelStoreSummary *s, GPtrArray *array); - -const char *camel_store_info_string(CamelStoreSummary *, const CamelStoreInfo *, int type); -void camel_store_info_set_string(CamelStoreSummary *, CamelStoreInfo *, int type, const char *value); - -/* helper macro's */ -#define camel_store_info_path(s, i) (camel_store_info_string((CamelStoreSummary *)s, (const CamelStoreInfo *)i, CAMEL_STORE_INFO_PATH)) -#define camel_store_info_uri(s, i) (camel_store_info_string((CamelStoreSummary *)s, (const CamelStoreInfo *)i, CAMEL_STORE_INFO_URI)) -#define camel_store_info_name(s, i) (camel_store_info_string((CamelStoreSummary *)s, (const CamelStoreInfo *)i, CAMEL_STORE_INFO_NAME)) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_STORE_SUMMARY_H */ diff --git a/camel/camel-store.c b/camel/camel-store.c deleted file mode 100644 index 8d576d4583..0000000000 --- a/camel/camel-store.c +++ /dev/null @@ -1,1228 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-store.c : Abstract class for an email store */ - -/* - * Authors: - * Bertrand Guiheneuf - * Dan Winship - * - * Copyright 1999-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "camel-session.h" -#include "camel-store.h" -#include "camel-folder.h" -#include "camel-vtrash-folder.h" -#include "camel-exception.h" -#include "camel-private.h" - -#define d(x) -#define w(x) - -static CamelServiceClass *parent_class = NULL; - -/* Returns the class for a CamelStore */ -#define CS_CLASS(so) ((CamelStoreClass *)((CamelObject *)(so))->klass) - -static CamelFolder *get_folder (CamelStore *store, const char *folder_name, - guint32 flags, CamelException *ex); -static CamelFolder *get_inbox (CamelStore *store, CamelException *ex); - -static void init_trash (CamelStore *store); -static CamelFolder *get_trash (CamelStore *store, CamelException *ex); - -static void init_junk (CamelStore *store); -static CamelFolder *get_junk (CamelStore *store, CamelException *ex); - -static CamelFolderInfo *create_folder (CamelStore *store, - const char *parent_name, - const char *folder_name, - CamelException *ex); -static void delete_folder (CamelStore *store, const char *folder_name, - CamelException *ex); -static void rename_folder (CamelStore *store, const char *old_name, - const char *new_name, CamelException *ex); - -static void store_sync (CamelStore *store, CamelException *ex); -static CamelFolderInfo *get_folder_info (CamelStore *store, const char *top, - guint32 flags, CamelException *ex); -static void free_folder_info (CamelStore *store, CamelFolderInfo *tree); - -static gboolean folder_subscribed (CamelStore *store, const char *folder_name); -static void subscribe_folder (CamelStore *store, const char *folder_name, CamelException *ex); -static void unsubscribe_folder (CamelStore *store, const char *folder_name, CamelException *ex); - -static void noop (CamelStore *store, CamelException *ex); - -static void construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex); - -static int store_setv (CamelObject *object, CamelException *ex, CamelArgV *args); -static int store_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args); - -static void -camel_store_class_init (CamelStoreClass *camel_store_class) -{ - CamelObjectClass *camel_object_class = CAMEL_OBJECT_CLASS (camel_store_class); - CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_store_class); - - parent_class = CAMEL_SERVICE_CLASS (camel_type_get_global_classfuncs (camel_service_get_type ())); - - /* virtual method definition */ - camel_store_class->hash_folder_name = g_str_hash; - camel_store_class->compare_folder_name = g_str_equal; - camel_store_class->get_folder = get_folder; - camel_store_class->get_inbox = get_inbox; - camel_store_class->init_trash = init_trash; - camel_store_class->get_trash = get_trash; - camel_store_class->init_junk = init_junk; - camel_store_class->get_junk = get_junk; - camel_store_class->create_folder = create_folder; - camel_store_class->delete_folder = delete_folder; - camel_store_class->rename_folder = rename_folder; - camel_store_class->sync = store_sync; - camel_store_class->get_folder_info = get_folder_info; - camel_store_class->free_folder_info = free_folder_info; - camel_store_class->folder_subscribed = folder_subscribed; - camel_store_class->subscribe_folder = subscribe_folder; - camel_store_class->unsubscribe_folder = unsubscribe_folder; - camel_store_class->noop = noop; - - /* virtual method overload */ - camel_service_class->construct = construct; - - camel_object_class->setv = store_setv; - camel_object_class->getv = store_getv; - - camel_object_class_add_event(camel_object_class, "folder_created", NULL); - camel_object_class_add_event(camel_object_class, "folder_deleted", NULL); - camel_object_class_add_event(camel_object_class, "folder_renamed", NULL); - camel_object_class_add_event(camel_object_class, "folder_subscribed", NULL); - camel_object_class_add_event(camel_object_class, "folder_unsubscribed", NULL); -} - -static void -camel_store_init (void *o) -{ - CamelStore *store = o; - CamelStoreClass *store_class = (CamelStoreClass *)CAMEL_OBJECT_GET_CLASS (o); - - if (store_class->hash_folder_name) { - store->folders = camel_object_bag_new(store_class->hash_folder_name, - store_class->compare_folder_name, - (CamelCopyFunc)g_strdup, g_free); - } else - store->folders = NULL; - - /* set vtrash and vjunk on by default */ - store->flags = CAMEL_STORE_VTRASH | CAMEL_STORE_VJUNK; - - store->dir_sep = '/'; - - store->priv = g_malloc0 (sizeof (*store->priv)); - store->priv->folder_lock = e_mutex_new (E_MUTEX_REC); -} - -static void -camel_store_finalize (CamelObject *object) -{ - CamelStore *store = CAMEL_STORE (object); - - if (store->folders) - camel_object_bag_destroy(store->folders); - - e_mutex_destroy (store->priv->folder_lock); - - g_free (store->priv); -} - - -CamelType -camel_store_get_type (void) -{ - static CamelType camel_store_type = CAMEL_INVALID_TYPE; - - if (camel_store_type == CAMEL_INVALID_TYPE) { - camel_store_type = camel_type_register (CAMEL_SERVICE_TYPE, "CamelStore", - sizeof (CamelStore), - sizeof (CamelStoreClass), - (CamelObjectClassInitFunc) camel_store_class_init, - NULL, - (CamelObjectInitFunc) camel_store_init, - (CamelObjectFinalizeFunc) camel_store_finalize ); - } - - return camel_store_type; -} - -static int -store_setv (CamelObject *object, CamelException *ex, CamelArgV *args) -{ - /* CamelStore doesn't currently have anything to set */ - return CAMEL_OBJECT_CLASS (parent_class)->setv (object, ex, args); -} - -static int -store_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args) -{ - /* CamelStore doesn't currently have anything to get */ - return CAMEL_OBJECT_CLASS (parent_class)->getv (object, ex, args); -} - -static void -construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex) -{ - CamelStore *store = CAMEL_STORE(service); - - parent_class->construct(service, session, provider, url, ex); - if (camel_exception_is_set (ex)) - return; - - if (camel_url_get_param(url, "filter")) - store->flags |= CAMEL_STORE_FILTER_INBOX; -} - -static CamelFolder * -get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) -{ - w(g_warning ("CamelStore::get_folder not implemented for `%s'", - camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store)))); - - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_INVALID, - _("Cannot get folder: Invalid operation on this store")); - - return NULL; -} - -/** - * camel_store_get_folder: Return the folder corresponding to a path. - * @store: a CamelStore - * @folder_name: name of the folder to get - * @flags: folder flags (create, save body index, etc) - * @ex: a CamelException - * - * Return value: the folder corresponding to the path @folder_name. - **/ -CamelFolder * -camel_store_get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) -{ - CamelFolder *folder = NULL; - - g_return_val_if_fail (folder_name != NULL, NULL); - - CAMEL_STORE_LOCK(store, folder_lock); - - if (store->folders) - /* Try cache first. */ - folder = camel_object_bag_reserve(store->folders, folder_name); - - if (!folder) { - folder = CS_CLASS (store)->get_folder (store, folder_name, flags, ex); - if (folder) { - /* Add the folder to the vTrash/vJunk folder if this store implements it */ - if (store->vtrash) - camel_vee_folder_add_folder (CAMEL_VEE_FOLDER (store->vtrash), folder); - if (store->vjunk) - camel_vee_folder_add_folder (CAMEL_VEE_FOLDER (store->vjunk), folder); - - if (store->folders) - camel_object_bag_add(store->folders, folder_name, folder); - } else { - if (store->folders) - camel_object_bag_abort(store->folders, folder_name); - } - } - - CAMEL_STORE_UNLOCK(store, folder_lock); - return folder; -} - -static CamelFolderInfo * -create_folder (CamelStore *store, const char *parent_name, - const char *folder_name, CamelException *ex) -{ - w(g_warning ("CamelStore::create_folder not implemented for `%s'", - camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store)))); - - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_INVALID, - _("Cannot create folder: Invalid operation on this store")); - - return NULL; -} - -/** - * camel_store_create_folder: - * @store: a CamelStore - * @parent_name: name of the new folder's parent, or %NULL - * @folder_name: name of the folder to create - * @ex: a CamelException - * - * Creates a new folder as a child of an existing folder. - * @parent_name can be %NULL to create a new top-level folder. - * - * Return value: info about the created folder, which the caller must - * free with camel_store_free_folder_info(). - **/ -CamelFolderInfo * -camel_store_create_folder (CamelStore *store, const char *parent_name, - const char *folder_name, CamelException *ex) -{ - CamelFolderInfo *fi; - - CAMEL_STORE_LOCK(store, folder_lock); - fi = CS_CLASS (store)->create_folder (store, parent_name, folder_name, ex); - CAMEL_STORE_UNLOCK(store, folder_lock); - - return fi; -} - - -static void -delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) -{ - w(g_warning ("CamelStore::delete_folder not implemented for `%s'", - camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store)))); -} - -/** - * camel_store_delete_folder: Delete the folder corresponding to a path. - * @store: a CamelStore - * @folder_name: name of the folder to delete - * @ex: a CamelException - * - * Deletes the named folder. The folder must be empty. - **/ -void -camel_store_delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) -{ - CamelFolder *folder = NULL; - - CAMEL_STORE_LOCK(store, folder_lock); - - /* NB: Note similarity of this code to unsubscribe_folder */ - - /* if we deleted a folder, force it out of the cache, and also out of the vtrash/vjunk if setup */ - if (store->folders) { - folder = camel_object_bag_get(store->folders, folder_name); - if (folder) { - if (store->vtrash) - camel_vee_folder_remove_folder((CamelVeeFolder *)store->vtrash, folder); - if (store->vjunk) - camel_vee_folder_remove_folder((CamelVeeFolder *)store->vjunk, folder); - camel_folder_delete (folder); - } - } - - CS_CLASS (store)->delete_folder (store, folder_name, ex); - - if (folder) { - if (store->folders) - camel_object_bag_remove (store->folders, folder); - - camel_object_unref (folder); - } - - CAMEL_STORE_UNLOCK(store, folder_lock); -} - -static void -rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex) -{ - w(g_warning ("CamelStore::rename_folder not implemented for `%s'", - camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store)))); -} - -/** - * camel_store_rename_folder: - * @store: a CamelStore - * @old_name: the current name of the folder - * @new_name: the new name of the folder - * @ex: a CamelException - * - * Rename a named folder to a new name. - **/ -void -camel_store_rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex) -{ - CamelFolder *folder; - int i, oldlen, namelen; - GPtrArray *folders; - - d(printf("store rename folder %s '%s' '%s'\n", ((CamelService *)store)->url->protocol, old_name, new_name)); - - if (strcmp(old_name, new_name) == 0) - return; - - oldlen = strlen(old_name); - - CAMEL_STORE_LOCK(store, folder_lock); - - /* If the folder is open (or any subfolders of the open folder) - We need to rename them atomically with renaming the actual folder path */ - if (store->folders) { - folders = camel_object_bag_list(store->folders); - for (i=0;ilen;i++) { - folder = folders->pdata[i]; - namelen = strlen(folder->full_name); - if ((namelen == oldlen && - strcmp(folder->full_name, old_name) == 0) - || ((namelen > oldlen) - && strncmp(folder->full_name, old_name, oldlen) == 0 - && folder->full_name[oldlen] == store->dir_sep)) { - d(printf("Found subfolder of '%s' == '%s'\n", old_name, folder->full_name)); - CAMEL_FOLDER_LOCK(folder, lock); - } else { - g_ptr_array_remove_index_fast(folders, i); - i--; - camel_object_unref(folder); - } - } - } - - /* Now try the real rename (will emit renamed event) */ - CS_CLASS (store)->rename_folder (store, old_name, new_name, ex); - - /* If it worked, update all open folders/unlock them */ - if (!camel_exception_is_set(ex)) { - guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE; - CamelRenameInfo reninfo; - - for (i=0;ilen;i++) { - char *new; - - folder = folders->pdata[i]; - - new = g_strdup_printf("%s%s", new_name, folder->full_name+strlen(old_name)); - camel_object_bag_remove(store->folders, folder); - camel_object_bag_add(store->folders, new, folder); - camel_folder_rename(folder, new); - - CAMEL_FOLDER_UNLOCK(folder, lock); - camel_object_unref(folder); - } - - /* Emit changed signal */ - if (store->flags & CAMEL_STORE_SUBSCRIPTIONS) - flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; - - reninfo.old_base = (char *)old_name; - reninfo.new = ((CamelStoreClass *)((CamelObject *)store)->klass)->get_folder_info(store, new_name, flags, ex); - if (reninfo.new != NULL) { - camel_object_trigger_event (store, "folder_renamed", &reninfo); - ((CamelStoreClass *)((CamelObject *)store)->klass)->free_folder_info(store, reninfo.new); - } - } else { - /* Failed, just unlock our folders for re-use */ - for (i=0;ilen;i++) { - folder = folders->pdata[i]; - CAMEL_FOLDER_UNLOCK(folder, lock); - camel_object_unref(folder); - } - } - - CAMEL_STORE_UNLOCK(store, folder_lock); - - g_ptr_array_free(folders, TRUE); -} - - -static CamelFolder * -get_inbox (CamelStore *store, CamelException *ex) -{ - /* Default: assume the inbox's name is "inbox" - * and open with default flags. - */ - return CS_CLASS (store)->get_folder (store, "inbox", 0, ex); -} - -/** - * camel_store_get_inbox: - * @store: a CamelStore - * @ex: a CamelException - * - * Return value: the folder in the store into which new mail is - * delivered, or %NULL if no such folder exists. - **/ -CamelFolder * -camel_store_get_inbox (CamelStore *store, CamelException *ex) -{ - CamelFolder *folder; - - CAMEL_STORE_LOCK(store, folder_lock); - folder = CS_CLASS (store)->get_inbox (store, ex); - CAMEL_STORE_UNLOCK(store, folder_lock); - - return folder; -} - -static void -trash_finalize (CamelObject *trash, gpointer event_data, gpointer user_data) -{ - CamelStore *store = CAMEL_STORE (user_data); - - store->vtrash = NULL; -} - -static void -junk_finalize (CamelObject *junk, gpointer event_data, gpointer user_data) -{ - CamelStore *store = CAMEL_STORE (user_data); - - store->vjunk = NULL; -} - -/* FIXME: derive vjunk folder object from vee_folder */ -#include "camel-vee-store.h" -static CamelFolder * -camel_vjunk_folder_new (CamelStore *parent_store, const char *name) -{ - CamelFolder *vjunk; - - vjunk = (CamelFolder *)camel_object_new (camel_vee_folder_get_type ()); - vjunk->folder_flags |= CAMEL_FOLDER_IS_JUNK; - camel_vee_folder_construct (CAMEL_VEE_FOLDER (vjunk), parent_store, name, - CAMEL_STORE_FOLDER_PRIVATE | CAMEL_STORE_FOLDER_CREATE | CAMEL_STORE_VEE_FOLDER_AUTO); - camel_vee_folder_set_expression((CamelVeeFolder *)vjunk, "(match-all (system-flag \"Junk\"))"); - - return vjunk; -} - -static void -init_trash_or_junk (CamelStore *store, CamelFolder *folder, void (*finalize) (CamelObject *o, gpointer event_data, gpointer user_data)) -{ - if (folder) { - /* FIXME: this should probably use the object bag or another one ? ... */ - /* attach to the finalise event of the vtrash/vjunk */ - camel_object_hook_event (folder, "finalize", finalize, store); - - /* add all the pre-opened folders to the vtrash/vjunk */ - if (store->folders) { - GPtrArray *folders = camel_object_bag_list(store->folders); - int i; - - for (i=0;ilen;i++) { - camel_vee_folder_add_folder (CAMEL_VEE_FOLDER (folder), (CamelFolder *)folders->pdata[i]); - camel_object_unref(folders->pdata[i]); - } - g_ptr_array_free(folders, TRUE); - } - } -} - -static void -init_trash (CamelStore *store) -{ - if ((store->flags & CAMEL_STORE_VTRASH) == 0) - return; - - store->vtrash = camel_vtrash_folder_new (store, CAMEL_VTRASH_NAME); - init_trash_or_junk (store, store->vtrash, trash_finalize); -} - -static void -init_junk (CamelStore *store) -{ - if ((store->flags & CAMEL_STORE_VJUNK) == 0) - return; - - store->vjunk = camel_vjunk_folder_new (store, CAMEL_VJUNK_NAME); - init_trash_or_junk (store, store->vjunk, junk_finalize); -} - -static CamelFolder * -get_trash (CamelStore *store, CamelException *ex) -{ - if (store->vtrash) { - camel_object_ref (store->vtrash); - return store->vtrash; - } else { - CS_CLASS (store)->init_trash (store); - if (store->vtrash) { - /* We don't ref here because we don't want the - store to own a ref on the trash folder */ - /*camel_object_ref (store->vtrash);*/ - return store->vtrash; - } else { - w(g_warning ("This store does not support vTrash.")); - return NULL; - } - } -} - -static CamelFolder * -get_junk (CamelStore *store, CamelException *ex) -{ - if (store->vjunk) { - camel_object_ref (CAMEL_OBJECT (store->vjunk)); - return store->vjunk; - } else { - CS_CLASS (store)->init_junk (store); - if (store->vjunk) { - /* We don't ref here because we don't want the - store to own a ref on the junk folder */ - /*camel_object_ref (CAMEL_OBJECT (store->vjunk));*/ - return store->vjunk; - } else { - w(g_warning ("This store does not support vJunk.")); - return NULL; - } - } -} - -/** - * camel_store_get_trash: - * @store: a CamelStore - * @ex: a CamelException - * - * Return value: the folder in the store into which trash is - * delivered, or %NULL if no such folder exists. - **/ -CamelFolder * -camel_store_get_trash (CamelStore *store, CamelException *ex) -{ - CamelFolder *folder; - - if ((store->flags & CAMEL_STORE_VTRASH) == 0) - return NULL; - - CAMEL_STORE_LOCK(store, folder_lock); - folder = CS_CLASS (store)->get_trash (store, ex); - CAMEL_STORE_UNLOCK(store, folder_lock); - - return folder; -} - -/** - * camel_store_get_junk: - * @store: a CamelStore - * @ex: a CamelException - * - * Return value: the folder in the store into which junk is - * delivered, or %NULL if no such folder exists. - **/ -CamelFolder * -camel_store_get_junk (CamelStore *store, CamelException *ex) -{ - CamelFolder *folder; - - if ((store->flags & CAMEL_STORE_VJUNK) == 0) - return NULL; - - CAMEL_STORE_LOCK(store, folder_lock); - folder = CS_CLASS (store)->get_junk (store, ex); - CAMEL_STORE_UNLOCK(store, folder_lock); - - return folder; -} - -static void -store_sync (CamelStore *store, CamelException *ex) -{ - if (store->folders) { - GPtrArray *folders; - CamelFolder *folder; - CamelException x; - int i; - - camel_exception_init(&x); - folders = camel_object_bag_list(store->folders); - for (i=0;ilen;i++) { - folder = folders->pdata[i]; - if (!camel_exception_is_set(&x)) - camel_folder_sync(folder, FALSE, &x); - camel_object_unref(folder); - } - camel_exception_xfer(ex, &x); - g_ptr_array_free(folders, TRUE); - } -} - -/** - * camel_store_sync: - * @store: a CamelStore - * @ex: a CamelException - * - * Syncs any changes that have been made to the store object and its - * folders with the real store. - **/ -void -camel_store_sync (CamelStore *store, CamelException *ex) -{ - g_return_if_fail (CAMEL_IS_STORE (store)); - - CS_CLASS (store)->sync (store, ex); -} - - -static CamelFolderInfo * -get_folder_info (CamelStore *store, const char *top, - guint32 flags, CamelException *ex) -{ - w(g_warning ("CamelStore::get_folder_info not implemented for `%s'", - camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store)))); - - return NULL; -} - -static void -add_special_info (CamelStore *store, CamelFolderInfo *info, const char *name, const char *full_name, - const char *url_base, gboolean unread_count) -{ - CamelFolderInfo *fi, *vinfo, *parent; - char *uri, *path; - CamelURL *url; - - g_return_if_fail (info != NULL); - - parent = NULL; - for (fi = info; fi; fi = fi->sibling) { - if (!strcmp (fi->name, name)) - break; - parent = fi; - } - - /* create our vTrash/vJunk URL */ - url = camel_url_new (info->url, NULL); - if (((CamelService *) store)->provider->url_flags & CAMEL_URL_FRAGMENT_IS_PATH) { - camel_url_set_fragment (url, name); - } else { - path = g_strdup_printf ("/%s", name); - camel_url_set_path (url, path); - g_free (path); - } - - uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_url_free (url); - - if (fi) { - /* We're going to replace the physical Trash/Junk folder with our vTrash/vJunk folder */ - vinfo = fi; - g_free (vinfo->full_name); - g_free (vinfo->name); - g_free (vinfo->url); - g_free (vinfo->path); - } else { - /* There wasn't a Trash/Junk folder so create a new folder entry */ - vinfo = g_new0 (CamelFolderInfo, 1); - - g_assert(parent != NULL); - - vinfo->flags |= CAMEL_FOLDER_NOINFERIORS | CAMEL_FOLDER_SUBSCRIBED; - - /* link it into the right spot */ - vinfo->sibling = parent->sibling; - parent->sibling = vinfo; - } - - /* Fill in the new fields */ - vinfo->full_name = g_strdup (full_name); - vinfo->name = g_strdup (vinfo->full_name); - vinfo->url = g_strdup_printf ("%s:%s", url_base, uri); - if (!unread_count) - vinfo->unread_message_count = -1; - vinfo->path = g_strdup_printf ("/%s", vinfo->name); - g_free (uri); -} - -/** - * camel_store_get_folder_info: - * @store: a CamelStore - * @top: the name of the folder to start from - * @flags: various CAMEL_STORE_FOLDER_INFO_* flags to control behavior - * @ex: a CamelException - * - * This fetches information about the folder structure of @store, - * starting with @top, and returns a tree of CamelFolderInfo - * structures. If @flags includes %CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, - * only subscribed folders will be listed. (This flag can only be used - * for stores that support subscriptions.) If @flags includes - * %CAMEL_STORE_FOLDER_INFO_RECURSIVE, the returned tree will include - * all levels of hierarchy below @top. If not, it will only include - * the immediate subfolders of @top. If @flags includes - * %CAMEL_STORE_FOLDER_INFO_FAST, the unread_message_count fields of - * some or all of the structures may be set to -1, if the store cannot - * determine that information quickly. - * - * Return value: a CamelFolderInfo tree, which must be freed with - * camel_store_free_folder_info. - **/ -CamelFolderInfo * -camel_store_get_folder_info (CamelStore *store, const char *top, - guint32 flags, CamelException *ex) -{ - CamelFolderInfo *info; - - g_return_val_if_fail (CAMEL_IS_STORE (store), NULL); - g_return_val_if_fail ((store->flags & CAMEL_STORE_SUBSCRIPTIONS) || - !(flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED), - NULL); - - CAMEL_STORE_LOCK(store, folder_lock); - info = CS_CLASS (store)->get_folder_info (store, top, flags, ex); - CAMEL_STORE_UNLOCK(store, folder_lock); - - if (info && (top == NULL || *top == '\0')) { - if (info->url && (store->flags & CAMEL_STORE_VTRASH)) - add_special_info (store, info, CAMEL_VTRASH_NAME, _("Trash"), "vtrash", FALSE); - if (info->url && (store->flags & CAMEL_STORE_VJUNK)) - add_special_info (store, info, CAMEL_VJUNK_NAME, _("Junk"), "vjunk", TRUE); - } - - return info; -} - - -static void -free_folder_info (CamelStore *store, CamelFolderInfo *fi) -{ - w(g_warning ("CamelStore::free_folder_info not implemented for `%s'", - camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store)))); -} - -/** - * camel_store_free_folder_info: - * @store: a CamelStore - * @tree: the tree returned by camel_store_get_folder_info() - * - * Frees the data returned by camel_store_get_folder_info(). - **/ -void -camel_store_free_folder_info (CamelStore *store, CamelFolderInfo *fi) -{ - g_return_if_fail (CAMEL_IS_STORE (store)); - - CS_CLASS (store)->free_folder_info (store, fi); -} - -/** - * camel_store_free_folder_info_full: - * @store: a CamelStore - * @tree: the tree returned by camel_store_get_folder_info() - * - * An implementation for CamelStore::free_folder_info. Frees all - * of the data. - **/ -void -camel_store_free_folder_info_full (CamelStore *store, CamelFolderInfo *fi) -{ - camel_folder_info_free (fi); -} - -/** - * camel_store_free_folder_info_nop: - * @store: a CamelStore - * @tree: the tree returned by camel_store_get_folder_info() - * - * An implementation for CamelStore::free_folder_info. Does nothing. - **/ -void -camel_store_free_folder_info_nop (CamelStore *store, CamelFolderInfo *fi) -{ - ; -} - - -/** - * camel_folder_info_free: - * @fi: the CamelFolderInfo - * - * Frees @fi. - **/ -void -camel_folder_info_free (CamelFolderInfo *fi) -{ - if (fi) { - camel_folder_info_free (fi->sibling); - camel_folder_info_free (fi->child); - g_free (fi->name); - g_free (fi->full_name); - g_free (fi->path); - g_free (fi->url); - g_free (fi); - } -} - - -/** - * camel_folder_info_build_path: - * @fi: folder info - * @separator: directory separator - * - * Sets the folder info path based on the folder's full name and - * directory separator. - **/ -void -camel_folder_info_build_path (CamelFolderInfo *fi, char separator) -{ - const char *full_name; - char *p; - - full_name = fi->full_name; - while (*full_name == separator) - full_name++; - - fi->path = g_strdup_printf ("/%s", full_name); - if (separator != '/') { - for (p = fi->path; *p; p++) { - if (*p == separator) - *p = '/'; - } - } -} - -static int -folder_info_cmp (const void *ap, const void *bp) -{ - const CamelFolderInfo *a = ((CamelFolderInfo **)ap)[0]; - const CamelFolderInfo *b = ((CamelFolderInfo **)bp)[0]; - - return strcmp (a->full_name, b->full_name); -} - -static void -free_name(void *key, void *data, void *user) -{ - g_free(key); -} - -/** - * camel_folder_info_build: - * @folders: an array of CamelFolderInfo - * @namespace: an ignorable prefix on the folder names - * @separator: the hieararchy separator character - * @short_names: %TRUE if the (short) name of a folder is the part after - * the last @separator in the full name. %FALSE if it is the full name. - * - * This takes an array of folders and attaches them together according - * to the hierarchy described by their full_names and @separator. If - * @namespace is non-%NULL, then it will be ignored as a full_name - * prefix, for purposes of comparison. If necessary, - * camel_folder_info_build will create additional CamelFolderInfo with - * %NULL urls to fill in gaps in the tree. The value of @short_names - * is used in constructing the names of these intermediate folders. - * - * Return value: the top level of the tree of linked folder info. - **/ -CamelFolderInfo * -camel_folder_info_build (GPtrArray *folders, const char *namespace, - char separator, gboolean short_names) -{ - CamelFolderInfo *fi, *pfi, *top = NULL, *tail = NULL; - GHashTable *hash; - char *name, *p, *pname; - int i, nlen; - - if (!namespace) - namespace = ""; - nlen = strlen (namespace); - - qsort (folders->pdata, folders->len, sizeof (folders->pdata[0]), folder_info_cmp); - - /* Hash the folders. */ - hash = g_hash_table_new (g_str_hash, g_str_equal); - for (i = 0; i < folders->len; i++) { - fi = folders->pdata[i]; - if (!strncmp (namespace, fi->full_name, nlen)) - name = fi->full_name + nlen; - else - name = fi->full_name; - if (*name == separator) - name++; - g_hash_table_insert (hash, g_strdup(name), fi); - } - - /* Now find parents. */ - for (i = 0; i < folders->len; i++) { - fi = folders->pdata[i]; - if (!strncmp (namespace, fi->full_name, nlen)) - name = fi->full_name + nlen; - else - name = fi->full_name; - if (*name == separator) - name++; - - /* set the path if it isn't already set */ - if (!fi->path) - camel_folder_info_build_path (fi, separator); - - p = strrchr (name, separator); - if (p) { - pname = g_strndup (name, p - name); - pfi = g_hash_table_lookup (hash, pname); - if (pfi) { - g_free (pname); - } else { - /* we are missing a folder in the heirarchy so - create a fake folder node */ - CamelURL *url; - char *sep; - - pfi = g_new0 (CamelFolderInfo, 1); - if (short_names) { - pfi->name = strrchr (pname, separator); - if (pfi->name) - pfi->name = g_strdup (pfi->name + 1); - else - pfi->name = g_strdup (pname); - } else - pfi->name = g_strdup (pname); - - /* FIXME: url's with fragments should have the fragment truncated, not path */ - url = camel_url_new (fi->url, NULL); - sep = strrchr (url->path, separator); - if (sep) - *sep = '\0'; - else - d(g_warning ("huh, no \"%c\" in \"%s\"?", separator, fi->url)); - - pfi->full_name = g_strdup(url->path+1); - - /* since this is a "fake" folder node, it is not selectable */ - camel_url_set_param (url, "noselect", "yes"); - pfi->url = camel_url_to_string (url, 0); - camel_url_free (url); - - g_hash_table_insert (hash, pname, pfi); - g_ptr_array_add (folders, pfi); - } - tail = pfi->child; - if (tail == NULL) { - pfi->child = fi; - } else { - while (tail->sibling) - tail = tail->sibling; - tail->sibling = fi; - } - fi->parent = pfi; - } else if (!top) - top = fi; - } - g_hash_table_foreach(hash, free_name, NULL); - g_hash_table_destroy (hash); - - /* Link together the top-level folders */ - tail = top; - for (i = 0; i < folders->len; i++) { - fi = folders->pdata[i]; - if (fi->parent || fi == top) - continue; - if (tail == NULL) { - tail = fi; - top = fi; - } else { - tail->sibling = fi; - tail = fi; - } - } - - return top; -} - -static CamelFolderInfo *folder_info_clone_rec(CamelFolderInfo *fi, CamelFolderInfo *parent) -{ - CamelFolderInfo *info; - - info = g_malloc(sizeof(*info)); - info->parent = parent; - info->url = g_strdup(fi->url); - info->name = g_strdup(fi->name); - info->full_name = g_strdup(fi->full_name); - info->path = g_strdup(fi->path); - info->unread_message_count = fi->unread_message_count; - - if (fi->sibling) - info->sibling = folder_info_clone_rec(fi->sibling, parent); - else - info->sibling = NULL; - - if (fi->child) - info->child = folder_info_clone_rec(fi->child, info); - else - info->child = NULL; - - return info; -} - -CamelFolderInfo * -camel_folder_info_clone(CamelFolderInfo *fi) -{ - if (fi == NULL) - return NULL; - - return folder_info_clone_rec(fi, NULL); -} - -gboolean -camel_store_supports_subscriptions (CamelStore *store) -{ - return (store->flags & CAMEL_STORE_SUBSCRIPTIONS); -} - - -static gboolean -folder_subscribed (CamelStore *store, const char *folder_name) -{ - w(g_warning ("CamelStore::folder_subscribed not implemented for `%s'", - camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store)))); - - return FALSE; -} - -/** - * camel_store_folder_subscribed: Tell whether or not a folder has been subscribed to. - * @store: a CamelStore - * @folder_name: the folder on which we're querying subscribed status. - * Return value: TRUE if folder is subscribed, FALSE if not. - **/ -gboolean -camel_store_folder_subscribed (CamelStore *store, - const char *folder_name) -{ - gboolean ret; - - g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE); - g_return_val_if_fail (store->flags & CAMEL_STORE_SUBSCRIPTIONS, FALSE); - - CAMEL_STORE_LOCK(store, folder_lock); - - ret = CS_CLASS (store)->folder_subscribed (store, folder_name); - - CAMEL_STORE_UNLOCK(store, folder_lock); - - return ret; -} - -static void -subscribe_folder (CamelStore *store, const char *folder_name, CamelException *ex) -{ - w(g_warning ("CamelStore::subscribe_folder not implemented for `%s'", - camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store)))); -} - -/** - * camel_store_subscribe_folder: marks a folder as subscribed. - * @store: a CamelStore - * @folder_name: the folder to subscribe to. - **/ -void -camel_store_subscribe_folder (CamelStore *store, - const char *folder_name, - CamelException *ex) -{ - g_return_if_fail (CAMEL_IS_STORE (store)); - g_return_if_fail (store->flags & CAMEL_STORE_SUBSCRIPTIONS); - - CAMEL_STORE_LOCK(store, folder_lock); - - CS_CLASS (store)->subscribe_folder (store, folder_name, ex); - - CAMEL_STORE_UNLOCK(store, folder_lock); -} - -static void -unsubscribe_folder (CamelStore *store, const char *folder_name, CamelException *ex) -{ - w(g_warning ("CamelStore::unsubscribe_folder not implemented for `%s'", - camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store)))); -} - - -/** - * camel_store_unsubscribe_folder: marks a folder as unsubscribed. - * @store: a CamelStore - * @folder_name: the folder to unsubscribe from. - **/ -void -camel_store_unsubscribe_folder (CamelStore *store, - const char *folder_name, - CamelException *ex) -{ - CamelFolder *folder = NULL; - - g_return_if_fail (CAMEL_IS_STORE (store)); - g_return_if_fail (store->flags & CAMEL_STORE_SUBSCRIPTIONS); - - CAMEL_STORE_LOCK(store, folder_lock); - - /* NB: Note similarity of this code to delete_folder */ - - /* if we deleted a folder, force it out of the cache, and also out of the vtrash/vjunk if setup */ - if (store->folders) { - folder = camel_object_bag_get(store->folders, folder_name); - if (folder) { - if (store->vtrash) - camel_vee_folder_remove_folder((CamelVeeFolder *)store->vtrash, folder); - if (store->vjunk) - camel_vee_folder_remove_folder((CamelVeeFolder *)store->vjunk, folder); - camel_folder_delete (folder); - } - } - - CS_CLASS (store)->unsubscribe_folder (store, folder_name, ex); - - if (folder) { - if (store->folders) - camel_object_bag_remove(store->folders, folder); - - camel_object_unref(folder); - } - - CAMEL_STORE_UNLOCK(store, folder_lock); -} - - -static void -noop (CamelStore *store, CamelException *ex) -{ - /* no-op */ - ; -} - - -/** - * camel_store_noop: - * @store: CamelStore - * @ex: exception - * - * Pings @store so that its connection doesn't timeout. - **/ -void -camel_store_noop (CamelStore *store, CamelException *ex) -{ - CS_CLASS (store)->noop (store, ex); -} - - -/* Return true if these uri's refer to the same object */ -gboolean -camel_store_uri_cmp(CamelStore *store, const char *uria, const char *urib) -{ - g_assert(CAMEL_IS_STORE(store)); - - return CS_CLASS(store)->compare_folder_name(uria, urib); -} diff --git a/camel/camel-store.h b/camel/camel-store.h deleted file mode 100644 index 2b65751aac..0000000000 --- a/camel/camel-store.h +++ /dev/null @@ -1,242 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-store.h : Abstract class for an email store */ - -/* - * - * Authors: Bertrand Guiheneuf - * Michael Zucchi - * Jeffrey Stedfast - * - * Copyright 1999, 2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_STORE_H -#define CAMEL_STORE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* for mode_t */ -#include - -#include -#include - -enum { - CAMEL_STORE_ARG_FIRST = CAMEL_SERVICE_ARG_FIRST + 100, -}; - -typedef struct _CamelFolderInfo { - struct _CamelFolderInfo *parent, - *sibling, - *child; - char *url; - char *name; - char *full_name; - char *path; - int unread_message_count; - guint32 flags; -} CamelFolderInfo; - -/* Note: these are abstractions (duh), its upto the provider to make them make sense */ - -/* a folder which can't contain messages */ -#define CAMEL_FOLDER_NOSELECT (1<<0) -/* a folder which cannot have children */ -#define CAMEL_FOLDER_NOINFERIORS (1<<1) -/* a folder which has children (not yet fully implemented) */ -#define CAMEL_FOLDER_CHILDREN (1<<2) -/* a folder which is subscribed */ -#define CAMEL_FOLDER_SUBSCRIBED (1<<3) - -/* Structure of rename event's event_data */ -typedef struct _CamelRenameInfo { - char *old_base; - struct _CamelFolderInfo *new; -} CamelRenameInfo; - -#define CAMEL_STORE_TYPE (camel_store_get_type ()) -#define CAMEL_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_STORE_TYPE, CamelStore)) -#define CAMEL_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_STORE_TYPE, CamelStoreClass)) -#define CAMEL_IS_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_STORE_TYPE)) - - -/* Flags for store flags */ -#define CAMEL_STORE_SUBSCRIPTIONS (1 << 0) -#define CAMEL_STORE_VTRASH (1 << 1) -#define CAMEL_STORE_FILTER_INBOX (1 << 2) -#define CAMEL_STORE_VJUNK (1 << 3) - -struct _CamelStore -{ - CamelService parent_object; - struct _CamelStorePrivate *priv; - - CamelFolder *vtrash; - CamelFolder *vjunk; - - CamelObjectBag *folders; - - int flags; - - /* FIXME: This is a temporary measure until IMAP namespaces are properly implemented, - after that, all external folder api's will assume a dir separator of '/' */ - /* This is always a copy of IMAP_STORE()->dir_sep, or '/' */ - char dir_sep; -}; - - -/* open mode for folder */ -#define CAMEL_STORE_FOLDER_CREATE (1<<0) -#define CAMEL_STORE_FOLDER_BODY_INDEX (1<<1) -#define CAMEL_STORE_FOLDER_PRIVATE (1<<2) /* a private folder, that shouldn't show up in unmatched/folder info's, etc */ - -#define CAMEL_STORE_FOLDER_INFO_FAST (1 << 0) -#define CAMEL_STORE_FOLDER_INFO_RECURSIVE (1 << 1) -#define CAMEL_STORE_FOLDER_INFO_SUBSCRIBED (1 << 2) - -typedef struct { - CamelServiceClass parent_class; - - GHashFunc hash_folder_name; - GCompareFunc compare_folder_name; - - CamelFolder * (*get_folder) (CamelStore *store, - const char *folder_name, - guint32 flags, - CamelException *ex); - CamelFolder * (*get_inbox) (CamelStore *store, - CamelException *ex); - - void (*init_trash) (CamelStore *store); - CamelFolder * (*get_trash) (CamelStore *store, - CamelException *ex); - void (*init_junk) (CamelStore *store); - CamelFolder * (*get_junk) (CamelStore *store, - CamelException *ex); - - CamelFolderInfo *(*create_folder) (CamelStore *store, - const char *parent_name, - const char *folder_name, - CamelException *ex); - void (*delete_folder) (CamelStore *store, - const char *folder_name, - CamelException *ex); - void (*rename_folder) (CamelStore *store, - const char *old_name, - const char *new_name, - CamelException *ex); - - void (*sync) (CamelStore *store, - CamelException *ex); - - CamelFolderInfo *(*get_folder_info) (CamelStore *store, - const char *top, - guint32 flags, - CamelException *ex); - void (*free_folder_info) (CamelStore *store, - CamelFolderInfo *fi); - - gboolean (*folder_subscribed) (CamelStore *store, - const char *folder_name); - void (*subscribe_folder) (CamelStore *store, - const char *folder_name, - CamelException *ex); - void (*unsubscribe_folder) (CamelStore *store, - const char *folder_name, - CamelException *ex); - void (*noop) (CamelStore *store, - CamelException *ex); -} CamelStoreClass; - - -/* Standard Camel function */ -CamelType camel_store_get_type (void); - -/* public methods */ -CamelFolder * camel_store_get_folder (CamelStore *store, - const char *folder_name, - guint32 flags, - CamelException *ex); -CamelFolder * camel_store_get_inbox (CamelStore *store, - CamelException *ex); -CamelFolder * camel_store_get_trash (CamelStore *store, - CamelException *ex); -CamelFolder * camel_store_get_junk (CamelStore *store, - CamelException *ex); - -CamelFolderInfo *camel_store_create_folder (CamelStore *store, - const char *parent_name, - const char *folder_name, - CamelException *ex); -void camel_store_delete_folder (CamelStore *store, - const char *folder_name, - CamelException *ex); -void camel_store_rename_folder (CamelStore *store, - const char *old_name, - const char *new_name, - CamelException *ex); - -void camel_store_sync (CamelStore *store, - CamelException *ex); - -CamelFolderInfo *camel_store_get_folder_info (CamelStore *store, - const char *top, - guint32 flags, - CamelException *ex); -void camel_store_free_folder_info (CamelStore *store, - CamelFolderInfo *fi); - -void camel_store_free_folder_info_full (CamelStore *store, - CamelFolderInfo *fi); -void camel_store_free_folder_info_nop (CamelStore *store, - CamelFolderInfo *fi); - -void camel_folder_info_free (CamelFolderInfo *fi); -void camel_folder_info_build_path (CamelFolderInfo *fi, - char separator); -CamelFolderInfo *camel_folder_info_build (GPtrArray *folders, - const char *namespace, - char separator, - gboolean short_names); -CamelFolderInfo *camel_folder_info_clone (CamelFolderInfo *fi); - -gboolean camel_store_supports_subscriptions (CamelStore *store); - -gboolean camel_store_folder_subscribed (CamelStore *store, - const char *folder_name); -void camel_store_subscribe_folder (CamelStore *store, - const char *folder_name, - CamelException *ex); -void camel_store_unsubscribe_folder (CamelStore *store, - const char *folder_name, - CamelException *ex); - -void camel_store_noop (CamelStore *store, - CamelException *ex); - -gboolean camel_store_uri_cmp (CamelStore *store, const char *uria, const char *urib); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_STORE_H */ diff --git a/camel/camel-stream-buffer.c b/camel/camel-stream-buffer.c deleted file mode 100644 index 8051441ae7..0000000000 --- a/camel/camel-stream-buffer.c +++ /dev/null @@ -1,471 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ - -/* camel-stream-buffer.c : Buffer any other other stream - * - * Authors: Michael Zucchi - * - * Copyright 1999-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include "camel-stream-buffer.h" - -static CamelStreamClass *parent_class = NULL; - -enum { - BUF_USER = 1<<0, /* user-supplied buffer, do not free */ -}; - -#define BUF_SIZE 1024 - -static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n); -static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n); -static int stream_flush (CamelStream *stream); -static int stream_close (CamelStream *stream); -static gboolean stream_eos (CamelStream *stream); - -static void init_vbuf(CamelStreamBuffer *sbf, CamelStream *s, CamelStreamBufferMode mode, char *buf, guint32 size); -static void init(CamelStreamBuffer *sbuf, CamelStream *s, CamelStreamBufferMode mode); - -static void -camel_stream_buffer_class_init (CamelStreamBufferClass *camel_stream_buffer_class) -{ - CamelStreamClass *camel_stream_class = CAMEL_STREAM_CLASS (camel_stream_buffer_class); - - parent_class = CAMEL_STREAM_CLASS (camel_type_get_global_classfuncs (camel_stream_get_type ())); - - /* virtual method definition */ - camel_stream_buffer_class->init = init; - camel_stream_buffer_class->init_vbuf = init_vbuf; - - /* virtual method overload */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->flush = stream_flush; - camel_stream_class->close = stream_close; - camel_stream_class->eos = stream_eos; -} - -static void -camel_stream_buffer_init (gpointer object, gpointer klass) -{ - CamelStreamBuffer *sbf = CAMEL_STREAM_BUFFER (object); - - sbf->flags = 0; - sbf->size = BUF_SIZE; - sbf->buf = g_malloc(BUF_SIZE); - sbf->ptr = sbf->buf; - sbf->end = sbf->buf; - sbf->mode = CAMEL_STREAM_BUFFER_READ | CAMEL_STREAM_BUFFER_BUFFER; - sbf->stream = 0; - sbf->linesize = 80; - sbf->linebuf = g_malloc(sbf->linesize); -} - -static void -camel_stream_buffer_finalize (CamelObject *object) -{ - CamelStreamBuffer *sbf = CAMEL_STREAM_BUFFER (object); - - if (!(sbf->flags & BUF_USER)) { - g_free(sbf->buf); - } - if (sbf->stream) - camel_object_unref (sbf->stream); - - g_free(sbf->linebuf); -} - - -CamelType -camel_stream_buffer_get_type (void) -{ - static CamelType camel_stream_buffer_type = CAMEL_INVALID_TYPE; - - if (camel_stream_buffer_type == CAMEL_INVALID_TYPE) { - camel_stream_buffer_type = camel_type_register (camel_stream_get_type (), "CamelStreamBuffer", - sizeof (CamelStreamBuffer), - sizeof (CamelStreamBufferClass), - (CamelObjectClassInitFunc) camel_stream_buffer_class_init, - NULL, - (CamelObjectInitFunc) camel_stream_buffer_init, - (CamelObjectFinalizeFunc) camel_stream_buffer_finalize); - } - - return camel_stream_buffer_type; -} - - -static void -set_vbuf(CamelStreamBuffer *sbf, char *buf, CamelStreamBufferMode mode, int size) -{ - if (sbf->buf && !(sbf->flags & BUF_USER)) { - g_free(sbf->buf); - } - if (buf) { - sbf->buf = buf; - sbf->flags |= BUF_USER; - } else { - sbf->buf = g_malloc(size); - sbf->flags &= ~BUF_USER; - } - sbf->size = size; - sbf->mode = mode; -} - -static void -init_vbuf(CamelStreamBuffer *sbf, CamelStream *s, CamelStreamBufferMode mode, char *buf, guint32 size) -{ - set_vbuf(sbf, buf, mode, size); - if (sbf->stream) - camel_object_unref (sbf->stream); - sbf->stream = s; - camel_object_ref (sbf->stream); -} - -static void -init(CamelStreamBuffer *sbuf, CamelStream *s, CamelStreamBufferMode mode) -{ - init_vbuf(sbuf, s, mode, NULL, BUF_SIZE); -} - - -/** - * camel_stream_buffer_new: - * @stream: Existing stream to buffer. - * @mode: Operational mode of buffered stream. - * - * Create a new buffered stream of another stream. A default - * buffer size (1024 bytes), automatically managed will be used - * for buffering. - * - * See camel_stream_buffer_new_with_vbuf() for details on the - * @mode parameter. - * - * Return value: A newly created buffered stream. - **/ -CamelStream * -camel_stream_buffer_new (CamelStream *stream, CamelStreamBufferMode mode) -{ - CamelStreamBuffer *sbf; - - sbf = CAMEL_STREAM_BUFFER (camel_object_new (camel_stream_buffer_get_type ())); - CAMEL_STREAM_BUFFER_CLASS (CAMEL_OBJECT_GET_CLASS(sbf))->init (sbf, stream, mode); - - return CAMEL_STREAM (sbf); -} - -/** - * camel_stream_buffer_new_with_vbuf: - * @stream: An existing stream to buffer. - * @mode: Mode to buffer in. - * @buf: Memory to use for buffering. - * @size: Size of buffer to use. - * - * Create a new stream which buffers another stream, @stream. - * - * The following values are available for @mode: - * - * CAMEL_STREAM_BUFFER_BUFFER, Buffer the input/output in blocks. - * CAMEL_STREAM_BUFFER_NEWLINE, Buffer on newlines (for output). - * CAMEL_STREAM_BUFFER_NONE, Perform no buffering. - * - * Note that currently this is ignored and CAMEL_STREAM_BUFFER_BUFFER - * is always used. - * - * In addition, one of the following mode options should be or'd - * together with the buffering mode: - * - * CAMEL_STREAM_BUFFER_WRITE, Buffer in write mode. - * CAMEL_STREAM_BUFFER_READ, Buffer in read mode. - * - * Buffering can only be done in one direction for any - * buffer instance. - * - * If @buf is non-NULL, then use the memory pointed to - * (for upto @size bytes) as the buffer for all buffering - * operations. It is upto the application to free this buffer. - * If @buf is NULL, then allocate and manage @size bytes - * for all buffering. - * - * Return value: A new stream with buffering applied. - **/ -CamelStream *camel_stream_buffer_new_with_vbuf (CamelStream *stream, CamelStreamBufferMode mode, char *buf, guint32 size) -{ - CamelStreamBuffer *sbf; - sbf = CAMEL_STREAM_BUFFER (camel_object_new (camel_stream_buffer_get_type ())); - CAMEL_STREAM_BUFFER_CLASS (CAMEL_OBJECT_GET_CLASS(sbf))->init_vbuf (sbf, stream, mode, buf, size); - - return CAMEL_STREAM (sbf); -} - -static ssize_t -stream_read (CamelStream *stream, char *buffer, size_t n) -{ - CamelStreamBuffer *sbf = CAMEL_STREAM_BUFFER (stream); - ssize_t bytes_read = 1; - ssize_t bytes_left; - char *bptr = buffer; - - g_return_val_if_fail( (sbf->mode & CAMEL_STREAM_BUFFER_MODE) == CAMEL_STREAM_BUFFER_READ, 0); - - while (n && bytes_read > 0) { - bytes_left = sbf->end - sbf->ptr; - if (bytes_left < n) { - if (bytes_left > 0) { - memcpy(bptr, sbf->ptr, bytes_left); - n -= bytes_left; - bptr += bytes_left; - sbf->ptr += bytes_left; - } - /* if we are reading a lot, then read directly to the destination buffer */ - if (n >= sbf->size/3) { - bytes_read = camel_stream_read(sbf->stream, bptr, n); - if (bytes_read>0) { - n -= bytes_read; - bptr += bytes_read; - } - } else { - bytes_read = camel_stream_read(sbf->stream, sbf->buf, sbf->size); - if (bytes_read>0) { - size_t bytes_used = bytes_read > n ? n : bytes_read; - sbf->ptr = sbf->buf; - sbf->end = sbf->buf+bytes_read; - memcpy(bptr, sbf->ptr, bytes_used); - sbf->ptr += bytes_used; - bptr += bytes_used; - n -= bytes_used; - } - } - } else { - memcpy(bptr, sbf->ptr, n); - sbf->ptr += n; - bptr += n; - n = 0; - } - } - - return (ssize_t)(bptr - buffer); -} - -/* only returns the number passed in, or -1 on an error */ -static ssize_t -stream_write_all(CamelStream *stream, const char *buffer, size_t n) -{ - size_t left = n, w; - - while (left > 0) { - w = camel_stream_write(stream, buffer, left); - if (w == -1) - return -1; - left -= w; - buffer += w; - } - - return n; -} - -static ssize_t -stream_write (CamelStream *stream, const char *buffer, size_t n) -{ - CamelStreamBuffer *sbf = CAMEL_STREAM_BUFFER (stream); - ssize_t total = n; - ssize_t left, todo; - - g_return_val_if_fail( (sbf->mode & CAMEL_STREAM_BUFFER_MODE) == CAMEL_STREAM_BUFFER_WRITE, 0); - - /* first, copy as much as we can */ - left = sbf->size - (sbf->ptr-sbf->buf); - todo = MIN(left, n); - - memcpy(sbf->ptr, buffer, todo); - n -= todo; - buffer += todo; - sbf->ptr += todo; - - /* if we've filled the buffer, write it out, reset buffer */ - if (left == todo) { - if (stream_write_all(sbf->stream, sbf->buf, sbf->size) == -1) - return -1; - - sbf->ptr = sbf->buf; - } - - /* if we still have more, write directly, or copy to buffer */ - if (n > 0) { - if (n >= sbf->size/3) { - if (stream_write_all(sbf->stream, buffer, n) == -1) - return -1; - } else { - memcpy(sbf->ptr, buffer, n); - sbf->ptr += n; - } - } - - return total; -} - -static int -stream_flush (CamelStream *stream) -{ - CamelStreamBuffer *sbf = CAMEL_STREAM_BUFFER (stream); - - if ((sbf->mode & CAMEL_STREAM_BUFFER_MODE) == CAMEL_STREAM_BUFFER_WRITE) { - int len = sbf->ptr-sbf->buf; - int written = camel_stream_write(sbf->stream, sbf->buf, len); - if (written > 0) - sbf->ptr += written; - if (written != len) - return -1; - } else { - /* nothing to do for read mode 'flush' */ - } - - return camel_stream_flush(sbf->stream); -} - -static int -stream_close (CamelStream *stream) -{ - CamelStreamBuffer *sbf = CAMEL_STREAM_BUFFER (stream); - - if (stream_flush(stream) == -1) - return -1; - return camel_stream_close(sbf->stream); -} - -static gboolean -stream_eos (CamelStream *stream) -{ - CamelStreamBuffer *sbf = CAMEL_STREAM_BUFFER (stream); - - return camel_stream_eos(sbf->stream) && sbf->ptr == sbf->end; -} - -/** - * camel_stream_buffer_gets: - * @sbf: A CamelStreamBuffer. - * @buf: Memory to write the string to. - * @max: Maxmimum number of characters to store. - * - * Read a line of characters up to the next newline character or - * @max-1 characters. - * - * If the newline character is encountered, then it will be - * included in the buffer @buf. The buffer will be #NUL terminated. - * - * Return value: The number of characters read, or 0 for end of file, - * and -1 on error. - **/ -int camel_stream_buffer_gets(CamelStreamBuffer *sbf, char *buf, unsigned int max) -{ - register char *outptr, *inptr, *inend, c, *outend; - int bytes_read; - - outptr = buf; - inptr = sbf->ptr; - inend = sbf->end; - outend = buf+max-1; /* room for NUL */ - - do { - while (inptrptr = inptr; - return outptr-buf; - } - } - if (outptr == outend) - break; - - bytes_read = camel_stream_read (sbf->stream, sbf->buf, sbf->size); - if (bytes_read == -1) { - if (buf == outptr) - return -1; - else - bytes_read = 0; - } - inptr = sbf->ptr = sbf->buf; - inend = sbf->end = sbf->buf + bytes_read; - } while (bytes_read>0); - - sbf->ptr = inptr; - *outptr = 0; - - return (int)(outptr - buf); -} - -/** - * camel_stream_buffer_read_line: read a complete line from the stream - * @sbf: A CamelStreamBuffer - * - * This function reads a complete newline-terminated line from the stream - * and returns it in allocated memory. The trailing newline (and carriage - * return if any) are not included in the returned string. - * - * Return value: the line read, which the caller must free when done with, - * or NULL on eof. If an error occurs, @ex will be set. - **/ -char * -camel_stream_buffer_read_line (CamelStreamBuffer *sbf) -{ - unsigned char *p; - int nread; - - p = sbf->linebuf; - - while (1) { - nread = camel_stream_buffer_gets (sbf, p, sbf->linesize - (p - sbf->linebuf)); - if (nread <=0) { - if (p > sbf->linebuf) - break; - return NULL; - } - - p += nread; - if (p[-1] == '\n') - break; - - nread = p - sbf->linebuf; - sbf->linesize *= 2; - sbf->linebuf = g_realloc (sbf->linebuf, sbf->linesize); - p = sbf->linebuf + nread; - } - - p--; - if (p > sbf->linebuf && p[-1] == '\r') - p--; - p[0] = 0; - - return g_strdup(sbf->linebuf); -} - - - - - - diff --git a/camel/camel-stream-buffer.h b/camel/camel-stream-buffer.h deleted file mode 100644 index 03a8517066..0000000000 --- a/camel/camel-stream-buffer.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-stream-buffer.h :stream which buffers another stream */ - -/* - * - * Author : - * Michael Zucchi - * - * Copyright 2000 Ximian Inc. (www.ximian.com) . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_STREAM_BUFFER_H -#define CAMEL_STREAM_BUFFER_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include - -#define CAMEL_STREAM_BUFFER_TYPE (camel_stream_buffer_get_type ()) -#define CAMEL_STREAM_BUFFER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_STREAM_BUFFER_TYPE, CamelStreamBuffer)) -#define CAMEL_STREAM_BUFFER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_STREAM_BUFFER_TYPE, CamelStreamBufferClass)) -#define CAMEL_IS_STREAM_BUFFER(o) (CAMEL_CHECK_TYPE((o), CAMEL_STREAM_BUFFER_TYPE)) - -typedef enum { - CAMEL_STREAM_BUFFER_BUFFER = 0, - CAMEL_STREAM_BUFFER_NONE, - CAMEL_STREAM_BUFFER_READ = 0x00, - CAMEL_STREAM_BUFFER_WRITE = 0x80, - CAMEL_STREAM_BUFFER_MODE = 0x80 -} CamelStreamBufferMode; - -struct _CamelStreamBuffer -{ - CamelStream parent_object; - - /* these are all of course, private */ - CamelStream *stream; - - unsigned char *buf, *ptr, *end; - int size; - - unsigned char *linebuf; /* for reading lines at a time */ - int linesize; - - CamelStreamBufferMode mode; - unsigned int flags; /* internal flags */ -}; - - -typedef struct { - CamelStreamClass parent_class; - - /* Virtual methods */ - void (*init) (CamelStreamBuffer *stream_buffer, CamelStream *stream, - CamelStreamBufferMode mode); - void (*init_vbuf) (CamelStreamBuffer *stream_buffer, - CamelStream *stream, CamelStreamBufferMode mode, - char *buf, guint32 size); - -} CamelStreamBufferClass; - - -/* Standard Camel function */ -CamelType camel_stream_buffer_get_type (void); - - -/* public methods */ -CamelStream *camel_stream_buffer_new (CamelStream *s, - CamelStreamBufferMode mode); -CamelStream *camel_stream_buffer_new_with_vbuf (CamelStream *s, - CamelStreamBufferMode mode, - char *buf, guint32 size); - -/* unimplemented - CamelStream *camel_stream_buffer_set_vbuf (CamelStreamBuffer *b, CamelStreamBufferMode mode, char *buf, guint32 size); */ - -/* read a line of characters */ -int camel_stream_buffer_gets (CamelStreamBuffer *b, char *buf, unsigned int max); - -char *camel_stream_buffer_read_line (CamelStreamBuffer *sbf); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_STREAM_BUFFER_H */ diff --git a/camel/camel-stream-filter.c b/camel/camel-stream-filter.c deleted file mode 100644 index 059a5198f1..0000000000 --- a/camel/camel-stream-filter.c +++ /dev/null @@ -1,406 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include "camel-stream-filter.h" - -#define d(x) - -/* use my malloc debugger? */ -/*extern void g_check(void *mp);*/ -#define g_check(x) - -struct _filter { - struct _filter *next; - int id; - CamelMimeFilter *filter; -}; - -struct _CamelStreamFilterPrivate { - struct _filter *filters; - int filterid; /* next filter id */ - - char *realbuffer; /* buffer - READ_PAD */ - char *buffer; /* READ_SIZE bytes */ - - char *filtered; /* the filtered data */ - size_t filteredlen; - - int last_was_read:1; /* was the last op read or write? */ - int flushed:1; /* were the filters flushed? */ -}; - -#define READ_PAD (128) /* bytes padded before buffer */ -#define READ_SIZE (4096) - -#define _PRIVATE(o) (((CamelStreamFilter *)(o))->priv) - -static void camel_stream_filter_class_init (CamelStreamFilterClass *klass); -static void camel_stream_filter_init (CamelStreamFilter *obj); - -static ssize_t do_read (CamelStream *stream, char *buffer, size_t n); -static ssize_t do_write (CamelStream *stream, const char *buffer, size_t n); -static int do_flush (CamelStream *stream); -static int do_close (CamelStream *stream); -static gboolean do_eos (CamelStream *stream); -static int do_reset (CamelStream *stream); - -static CamelStreamClass *camel_stream_filter_parent; - -static void -camel_stream_filter_class_init (CamelStreamFilterClass *klass) -{ - CamelStreamClass *camel_stream_class = (CamelStreamClass *) klass; - - camel_stream_filter_parent = CAMEL_STREAM_CLASS (camel_type_get_global_classfuncs (camel_stream_get_type ())); - - camel_stream_class->read = do_read; - camel_stream_class->write = do_write; - camel_stream_class->flush = do_flush; - camel_stream_class->close = do_close; - camel_stream_class->eos = do_eos; - camel_stream_class->reset = do_reset; - -} - -static void -camel_stream_filter_init (CamelStreamFilter *obj) -{ - struct _CamelStreamFilterPrivate *p; - - _PRIVATE(obj) = p = g_malloc0(sizeof(*p)); - p->realbuffer = g_malloc(READ_SIZE + READ_PAD); - p->buffer = p->realbuffer + READ_PAD; - p->last_was_read = TRUE; - p->flushed = FALSE; -} - -static void -camel_stream_filter_finalize(CamelObject *o) -{ - CamelStreamFilter *filter = (CamelStreamFilter *)o; - struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); - struct _filter *fn, *f; - - f = p->filters; - while (f) { - fn = f->next; - camel_object_unref((CamelObject *)f->filter); - g_free(f); - f = fn; - } - g_free(p->realbuffer); - g_free(p); - camel_object_unref((CamelObject *)filter->source); -} - -CamelType -camel_stream_filter_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (CAMEL_STREAM_TYPE, "CamelStreamFilter", - sizeof (CamelStreamFilter), - sizeof (CamelStreamFilterClass), - (CamelObjectClassInitFunc) camel_stream_filter_class_init, - NULL, - (CamelObjectInitFunc) camel_stream_filter_init, - (CamelObjectFinalizeFunc) camel_stream_filter_finalize); - } - - return type; -} - -/** - * camel_stream_filter_new: - * - * Create a new CamelStreamFilter object. - * - * Return value: A new CamelStreamFilter object. - **/ -CamelStreamFilter * -camel_stream_filter_new_with_stream(CamelStream *stream) -{ - CamelStreamFilter *new = CAMEL_STREAM_FILTER ( camel_object_new (camel_stream_filter_get_type ())); - - new->source = stream; - camel_object_ref ((CamelObject *)stream); - - return new; -} - -/** - * camel_stream_filter_add: - * @filter: Initialised CamelStreamFilter. - * @mf: Filter to perform processing on stream. - * - * Add a new CamelMimeFilter to execute during the processing of this - * stream. Each filter added is processed after the previous one. - * - * Note that a filter should only be added to a single stream - * at a time, otherwise unpredictable results may occur. - * - * Return value: A filter id for this CamelStreamFilter. - **/ -int -camel_stream_filter_add(CamelStreamFilter *filter, CamelMimeFilter *mf) -{ - struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); - struct _filter *fn, *f; - - fn = g_malloc(sizeof(*fn)); - fn->id = p->filterid++; - fn->filter = mf; - camel_object_ref((CamelObject *)mf); - - /* sure, we could use a GList, but we wouldn't save much */ - f = (struct _filter *)&p->filters; - while (f->next) - f = f->next; - f->next = fn; - fn->next = NULL; - return fn->id; -} - -/** - * camel_stream_filter_remove: - * @filter: Initialised CamelStreamFilter. - * @id: Filter id, as returned from camel_stream_filter_add(). - * - * Remove a processing filter from the stream, by id. - **/ -void -camel_stream_filter_remove(CamelStreamFilter *filter, int id) -{ - struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); - struct _filter *fn, *f; - - f = (struct _filter *)&p->filters; - while (f && f->next) { - fn = f->next; - if (fn->id == id) { - f->next = fn->next; - camel_object_unref((CamelObject *)fn->filter); - g_free(fn); - } - f = f->next; - } -} - -static ssize_t -do_read (CamelStream *stream, char *buffer, size_t n) -{ - CamelStreamFilter *filter = (CamelStreamFilter *)stream; - struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); - ssize_t size; - struct _filter *f; - - p->last_was_read = TRUE; - - g_check(p->realbuffer); - - if (p->filteredlen<=0) { - size_t presize = READ_PAD; - - size = camel_stream_read(filter->source, p->buffer, READ_SIZE); - if (size <= 0) { - /* this is somewhat untested */ - if (camel_stream_eos(filter->source)) { - f = p->filters; - p->filtered = p->buffer; - p->filteredlen = 0; - while (f) { - camel_mime_filter_complete(f->filter, p->filtered, p->filteredlen, - presize, &p->filtered, &p->filteredlen, &presize); - g_check(p->realbuffer); - f = f->next; - } - size = p->filteredlen; - p->flushed = TRUE; - } - if (size <= 0) - return size; - } else { - f = p->filters; - p->filtered = p->buffer; - p->filteredlen = size; - - d(printf ("\n\nOriginal content (%s): '", ((CamelObject *)filter->source)->klass->name)); - d(fwrite(p->filtered, sizeof(char), p->filteredlen, stdout)); - d(printf("'\n")); - - while (f) { - camel_mime_filter_filter(f->filter, p->filtered, p->filteredlen, presize, - &p->filtered, &p->filteredlen, &presize); - g_check(p->realbuffer); - - d(printf ("Filtered content (%s): '", ((CamelObject *)f->filter)->klass->name)); - d(fwrite(p->filtered, sizeof(char), p->filteredlen, stdout)); - d(printf("'\n")); - - f = f->next; - } - } - } - - size = MIN(n, p->filteredlen); - memcpy(buffer, p->filtered, size); - p->filteredlen -= size; - p->filtered += size; - - g_check(p->realbuffer); - - return size; -} - -/* Note: Since the caller expects to write out as much as they asked us to - write (for 'success'), we return what they asked us to write (for 'success') - rather than the true number of written bytes */ -static ssize_t -do_write (CamelStream *stream, const char *buf, size_t n) -{ - CamelStreamFilter *filter = (CamelStreamFilter *)stream; - struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); - struct _filter *f; - size_t presize; - char *buffer = (char *)buf; - size_t len = n; - - p->last_was_read = FALSE; - - d(printf ("\n\nWriting: Original content (%s): '", ((CamelObject *)filter->source)->klass->name)); - d(fwrite(buffer, sizeof(char), len, stdout)); - d(printf("'\n")); - - g_check(p->realbuffer); - - f = p->filters; - presize = 0; - while (f) { - camel_mime_filter_filter(f->filter, buffer, len, presize, &buffer, &len, &presize); - - g_check(p->realbuffer); - - d(printf ("Filtered content (%s): '", ((CamelObject *)f->filter)->klass->name)); - d(fwrite(buffer, sizeof(char), len, stdout)); - d(printf("'\n")); - - f = f->next; - } - - if (camel_stream_write(filter->source, buffer, len) != len) - return -1; - - g_check(p->realbuffer); - - return n; -} - -static int -do_flush (CamelStream *stream) -{ - CamelStreamFilter *filter = (CamelStreamFilter *)stream; - struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); - struct _filter *f; - char *buffer; - size_t presize; - size_t len; - - if (p->last_was_read) - return 0; - - buffer = ""; - len = 0; - presize = 0; - f = p->filters; - - d(printf ("\n\nFlushing: Original content (%s): '", ((CamelObject *)filter->source)->klass->name)); - d(fwrite(buffer, sizeof(char), len, stdout)); - d(printf("'\n")); - - while (f) { - camel_mime_filter_complete(f->filter, buffer, len, presize, &buffer, &len, &presize); - - d(printf ("Filtered content (%s): '", ((CamelObject *)f->filter)->klass->name)); - d(fwrite(buffer, sizeof(char), len, stdout)); - d(printf("'\n")); - - f = f->next; - } - if (len > 0 && camel_stream_write(filter->source, buffer, len) == -1) - return -1; - return camel_stream_flush(filter->source); -} - -static int -do_close (CamelStream *stream) -{ - CamelStreamFilter *filter = (CamelStreamFilter *)stream; - struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); - - if (!p->last_was_read) { - do_flush(stream); - } - return camel_stream_close(filter->source); -} - -static gboolean -do_eos (CamelStream *stream) -{ - CamelStreamFilter *filter = (CamelStreamFilter *)stream; - struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); - - if (p->filteredlen > 0) - return FALSE; - - if (!p->flushed) - return FALSE; - - return camel_stream_eos(filter->source); -} - -static int -do_reset (CamelStream *stream) -{ - CamelStreamFilter *filter = (CamelStreamFilter *)stream; - struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); - struct _filter *f; - - p->filteredlen = 0; - p->flushed = FALSE; - - /* and reset filters */ - f = p->filters; - while (f) { - camel_mime_filter_reset(f->filter); - f = f->next; - } - - return camel_stream_reset(filter->source); -} - diff --git a/camel/camel-stream-filter.h b/camel/camel-stream-filter.h deleted file mode 100644 index 3d265e8b4c..0000000000 --- a/camel/camel-stream-filter.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_STREAM_FILTER_H -#define _CAMEL_STREAM_FILTER_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include - -#define CAMEL_STREAM_FILTER(obj) CAMEL_CHECK_CAST (obj, camel_stream_filter_get_type (), CamelStreamFilter) -#define CAMEL_STREAM_FILTER_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_stream_filter_get_type (), CamelStreamFilterClass) -#define CAMEL_IS_STREAM_FILTER(obj) CAMEL_CHECK_TYPE (obj, camel_stream_filter_get_type ()) - -typedef struct _CamelStreamFilterClass CamelStreamFilterClass; - -struct _CamelStreamFilter { - CamelStream parent; - - CamelStream *source; - - struct _CamelStreamFilterPrivate *priv; -}; - -struct _CamelStreamFilterClass { - CamelStreamClass parent_class; -}; - -CamelType camel_stream_filter_get_type (void); - -CamelStreamFilter *camel_stream_filter_new_with_stream (CamelStream *stream); - -int camel_stream_filter_add (CamelStreamFilter *filter, CamelMimeFilter *); -void camel_stream_filter_remove (CamelStreamFilter *filter, int id); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_STREAM_FILTER_H */ diff --git a/camel/camel-stream-fs.c b/camel/camel-stream-fs.c deleted file mode 100644 index 6560512d0c..0000000000 --- a/camel/camel-stream-fs.c +++ /dev/null @@ -1,304 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-stream-fs.c : file system based stream */ - -/* - * Authors: Bertrand Guiheneuf - * Michael Zucchi - * - * Copyright 1999-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include "camel-file-utils.h" -#include "camel-operation.h" -#include "camel-stream-fs.h" -#include "camel-session.h" - -static CamelSeekableStreamClass *parent_class = NULL; - -/* Returns the class for a CamelStreamFS */ -#define CSFS_CLASS(so) CAMEL_STREAM_FS_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n); -static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n); -static int stream_flush (CamelStream *stream); -static int stream_close (CamelStream *stream); -static off_t stream_seek (CamelSeekableStream *stream, off_t offset, - CamelStreamSeekPolicy policy); - -static void -camel_stream_fs_class_init (CamelStreamFsClass *camel_stream_fs_class) -{ - CamelSeekableStreamClass *camel_seekable_stream_class = - CAMEL_SEEKABLE_STREAM_CLASS (camel_stream_fs_class); - CamelStreamClass *camel_stream_class = - CAMEL_STREAM_CLASS (camel_stream_fs_class); - - parent_class = CAMEL_SEEKABLE_STREAM_CLASS (camel_type_get_global_classfuncs (camel_seekable_stream_get_type ())); - - /* virtual method overload */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->flush = stream_flush; - camel_stream_class->close = stream_close; - - camel_seekable_stream_class->seek = stream_seek; -} - -static void -camel_stream_fs_init (gpointer object, gpointer klass) -{ - CamelStreamFs *stream = CAMEL_STREAM_FS (object); - - stream->fd = -1; - ((CamelSeekableStream *)stream)->bound_end = CAMEL_STREAM_UNBOUND; -} - -static void -camel_stream_fs_finalize (CamelObject *object) -{ - CamelStreamFs *stream_fs = CAMEL_STREAM_FS (object); - - if (stream_fs->fd != -1) - close (stream_fs->fd); -} - - -CamelType -camel_stream_fs_get_type (void) -{ - static CamelType camel_stream_fs_type = CAMEL_INVALID_TYPE; - - if (camel_stream_fs_type == CAMEL_INVALID_TYPE) { - camel_stream_fs_type = camel_type_register (camel_seekable_stream_get_type (), "CamelStreamFs", - sizeof (CamelStreamFs), - sizeof (CamelStreamFsClass), - (CamelObjectClassInitFunc) camel_stream_fs_class_init, - NULL, - (CamelObjectInitFunc) camel_stream_fs_init, - (CamelObjectFinalizeFunc) camel_stream_fs_finalize); - } - - return camel_stream_fs_type; -} - -/** - * camel_stream_fs_new_with_fd: - * @fd: a file descriptor - * - * Creates a new fs stream using the given file descriptor @fd as the - * backing store. When the stream is destroyed, the file descriptor - * will be closed. - * - * Returns a new fs stream. - **/ -CamelStream * -camel_stream_fs_new_with_fd (int fd) -{ - CamelStreamFs *stream_fs; - off_t offset; - - if (fd == -1) - return NULL; - - stream_fs = CAMEL_STREAM_FS (camel_object_new (camel_stream_fs_get_type ())); - stream_fs->fd = fd; - offset = lseek (fd, 0, SEEK_CUR); - if (offset == -1) - offset = 0; - CAMEL_SEEKABLE_STREAM (stream_fs)->position = offset; - - return CAMEL_STREAM (stream_fs); -} - -/** - * camel_stream_fs_new_with_fd_and_bounds: - * @fd: a file descriptor - * @start: the first valid position in the file - * @end: the first invalid position in the file, or CAMEL_STREAM_UNBOUND - * - * Returns a stream associated with the given file descriptor and bounds. - * When the stream is destroyed, the file descriptor will be closed. - * - * Return value: the stream - **/ -CamelStream * -camel_stream_fs_new_with_fd_and_bounds (int fd, off_t start, off_t end) -{ - CamelStream *stream; - - stream = camel_stream_fs_new_with_fd (fd); - camel_seekable_stream_set_bounds (CAMEL_SEEKABLE_STREAM (stream), start, end); - - return stream; -} - -/** - * camel_stream_fs_new_with_name: - * @name: a local filename - * @flags: flags as in open(2) - * @mode: a file mode - * - * Creates a new CamelStream corresponding to the named file, flags, - * and mode. - * - * Return value: the stream, or #NULL on error. - **/ -CamelStream * -camel_stream_fs_new_with_name (const char *name, int flags, mode_t mode) -{ - int fd; - - fd = open (name, flags, mode); - if (fd == -1) { - return NULL; - } - - return camel_stream_fs_new_with_fd (fd); -} - -/** - * camel_stream_fs_new_with_name_and_bounds: - * @name: a local filename - * @flags: flags as in open(2) - * @mode: a file mode - * @start: the first valid position in the file - * @end: the first invalid position in the file, or CAMEL_STREAM_UNBOUND - * - * Creates a new CamelStream corresponding to the given arguments. - * - * Return value: the stream, or NULL on error. - **/ -CamelStream * -camel_stream_fs_new_with_name_and_bounds (const char *name, int flags, - mode_t mode, off_t start, off_t end) -{ - CamelStream *stream; - - stream = camel_stream_fs_new_with_name (name, flags, mode); - if (stream == NULL) - return NULL; - - camel_seekable_stream_set_bounds (CAMEL_SEEKABLE_STREAM (stream), - start, end); - - return stream; -} - - -static ssize_t -stream_read (CamelStream *stream, char *buffer, size_t n) -{ - CamelStreamFs *stream_fs = CAMEL_STREAM_FS (stream); - CamelSeekableStream *seekable = CAMEL_SEEKABLE_STREAM (stream); - ssize_t nread; - - if (seekable->bound_end != CAMEL_STREAM_UNBOUND) - n = MIN (seekable->bound_end - seekable->position, n); - - if ((nread = camel_read (stream_fs->fd, buffer, n)) > 0) - seekable->position += nread; - else if (nread == 0) - stream->eos = TRUE; - - return nread; -} - -static ssize_t -stream_write (CamelStream *stream, const char *buffer, size_t n) -{ - CamelStreamFs *stream_fs = CAMEL_STREAM_FS (stream); - CamelSeekableStream *seekable = CAMEL_SEEKABLE_STREAM (stream); - ssize_t nwritten; - - if (seekable->bound_end != CAMEL_STREAM_UNBOUND) - n = MIN (seekable->bound_end - seekable->position, n); - - if ((nwritten = camel_write (stream_fs->fd, buffer, n)) > 0) - seekable->position += nwritten; - - return nwritten; -} - -static int -stream_flush (CamelStream *stream) -{ - return fsync(((CamelStreamFs *)stream)->fd); -} - -static int -stream_close (CamelStream *stream) -{ - if (close (((CamelStreamFs *)stream)->fd) == -1) - return -1; - - ((CamelStreamFs *)stream)->fd = -1; - return 0; -} - -static off_t -stream_seek (CamelSeekableStream *stream, off_t offset, CamelStreamSeekPolicy policy) -{ - CamelStreamFs *stream_fs = CAMEL_STREAM_FS (stream); - off_t real = 0; - - switch (policy) { - case CAMEL_STREAM_SET: - real = offset; - break; - case CAMEL_STREAM_CUR: - real = stream->position + offset; - break; - case CAMEL_STREAM_END: - if (stream->bound_end == CAMEL_STREAM_UNBOUND) { - real = lseek(stream_fs->fd, offset, SEEK_END); - if (real != -1) { - if (realbound_start) - real = stream->bound_start; - stream->position = real; - } - return real; - } - real = stream->bound_end + offset; - break; - } - - if (stream->bound_end != CAMEL_STREAM_UNBOUND) - real = MIN (real, stream->bound_end); - real = MAX (real, stream->bound_start); - - real = lseek(stream_fs->fd, real, SEEK_SET); - if (real == -1) - return -1; - - if (real != stream->position && ((CamelStream *)stream)->eos) - ((CamelStream *)stream)->eos = FALSE; - - stream->position = real; - - return real; -} diff --git a/camel/camel-stream-fs.h b/camel/camel-stream-fs.h deleted file mode 100644 index 7db13ac244..0000000000 --- a/camel/camel-stream-fs.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-stream-fs.h :stream based on unix filesystem */ - -/* - * Author: - * Bertrand Guiheneuf - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_STREAM_FS_H -#define CAMEL_STREAM_FS_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -/* for open flags */ -#include -#include -#include - -#include - -#define CAMEL_STREAM_FS_TYPE (camel_stream_fs_get_type ()) -#define CAMEL_STREAM_FS(obj) (CAMEL_CHECK_CAST((obj), CAMEL_STREAM_FS_TYPE, CamelStreamFs)) -#define CAMEL_STREAM_FS_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_STREAM_FS_TYPE, CamelStreamFsClass)) -#define CAMEL_IS_STREAM_FS(o) (CAMEL_CHECK_TYPE((o), CAMEL_STREAM_FS_TYPE)) - -struct _CamelStreamFs -{ - CamelSeekableStream parent_object; - - int fd; /* file descriptor on the underlying file */ -}; - -typedef struct { - CamelSeekableStreamClass parent_class; - -} CamelStreamFsClass; - -/* Standard Camel function */ -CamelType camel_stream_fs_get_type (void); - -/* public methods */ -CamelStream * camel_stream_fs_new_with_name (const char *name, int flags, mode_t mode); -CamelStream * camel_stream_fs_new_with_name_and_bounds (const char *name, int flags, mode_t mode, - off_t start, off_t end); - -CamelStream * camel_stream_fs_new_with_fd (int fd); -CamelStream * camel_stream_fs_new_with_fd_and_bounds (int fd, off_t start, off_t end); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_STREAM_FS_H */ diff --git a/camel/camel-stream-mem.c b/camel/camel-stream-mem.c deleted file mode 100644 index 7b93b7864b..0000000000 --- a/camel/camel-stream-mem.c +++ /dev/null @@ -1,248 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-stream-mem.c: memory buffer based stream */ - -/* - * Authors: Bertrand Guiheneuf - * Michael Zucchi - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "camel-stream-mem.h" - -static CamelSeekableStreamClass *parent_class = NULL; - -/* Returns the class for a CamelStreamMem */ -#define CSM_CLASS(so) CAMEL_STREAM_MEM_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n); -static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n); -static gboolean stream_eos (CamelStream *stream); -static off_t stream_seek (CamelSeekableStream *stream, off_t offset, - CamelStreamSeekPolicy policy); - -static void camel_stream_mem_finalize (CamelObject *object); - -static void -camel_stream_mem_class_init (CamelStreamMemClass *camel_stream_mem_class) -{ - CamelSeekableStreamClass *camel_seekable_stream_class = - CAMEL_SEEKABLE_STREAM_CLASS (camel_stream_mem_class); - CamelStreamClass *camel_stream_class = - CAMEL_STREAM_CLASS (camel_stream_mem_class); - - parent_class = CAMEL_SEEKABLE_STREAM_CLASS( camel_type_get_global_classfuncs( CAMEL_SEEKABLE_STREAM_TYPE ) ); - - /* virtual method overload */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->eos = stream_eos; - - camel_seekable_stream_class->seek = stream_seek; -} - -static void -camel_stream_mem_init (CamelObject *object) -{ - CamelStreamMem *stream_mem = CAMEL_STREAM_MEM (object); - - stream_mem->owner = FALSE; - stream_mem->buffer = 0; -} - -CamelType -camel_stream_mem_get_type (void) -{ - static CamelType camel_stream_mem_type = CAMEL_INVALID_TYPE; - - if (camel_stream_mem_type == CAMEL_INVALID_TYPE) { - camel_stream_mem_type = camel_type_register( CAMEL_SEEKABLE_STREAM_TYPE, - "CamelStreamMem", - sizeof( CamelStreamMem ), - sizeof( CamelStreamMemClass ), - (CamelObjectClassInitFunc) camel_stream_mem_class_init, - NULL, - (CamelObjectInitFunc) camel_stream_mem_init, - (CamelObjectFinalizeFunc) camel_stream_mem_finalize ); - } - - return camel_stream_mem_type; -} - - -CamelStream * -camel_stream_mem_new (void) -{ - return camel_stream_mem_new_with_byte_array (g_byte_array_new ()); -} - -CamelStream * -camel_stream_mem_new_with_buffer (const char *buffer, size_t len) -{ - GByteArray *ba; - - ba = g_byte_array_new (); - g_byte_array_append (ba, (const guint8 *)buffer, len); - return camel_stream_mem_new_with_byte_array (ba); -} - -CamelStream * -camel_stream_mem_new_with_byte_array (GByteArray *byte_array) -{ - CamelStreamMem *stream_mem; - - stream_mem = CAMEL_STREAM_MEM( camel_object_new (CAMEL_STREAM_MEM_TYPE) ); - stream_mem->buffer = byte_array; - stream_mem->owner = TRUE; - - return CAMEL_STREAM (stream_mem); -} - -/* note: with these functions the caller is the 'owner' of the buffer */ -void camel_stream_mem_set_byte_array (CamelStreamMem *s, GByteArray *buffer) -{ - if (s->buffer && s->owner) - g_byte_array_free(s->buffer, TRUE); - s->owner = FALSE; - s->buffer = buffer; -} - -void camel_stream_mem_set_buffer (CamelStreamMem *s, const char *buffer, size_t len) -{ - GByteArray *ba; - - ba = g_byte_array_new (); - g_byte_array_append(ba, (const guint8 *)buffer, len); - camel_stream_mem_set_byte_array(s, ba); - s->owner = TRUE; -} - -static void -camel_stream_mem_finalize (CamelObject *object) -{ - CamelStreamMem *stream_mem = CAMEL_STREAM_MEM (object); - - if (stream_mem->buffer && stream_mem->owner) - g_byte_array_free (stream_mem->buffer, TRUE); - - /* Will be called automagically in the Camel Type System! - * Wheeee! - * G_TK_OBJECT_CLASS (parent_class)->finalize (object); - */ -} - -static ssize_t -stream_read (CamelStream *stream, char *buffer, size_t n) -{ - CamelStreamMem *camel_stream_mem = CAMEL_STREAM_MEM (stream); - CamelSeekableStream *seekable = CAMEL_SEEKABLE_STREAM (stream); - ssize_t nread; - - if (seekable->bound_end != CAMEL_STREAM_UNBOUND) - n = MIN(seekable->bound_end - seekable->position, n); - - nread = MIN (n, camel_stream_mem->buffer->len - seekable->position); - if (nread > 0) { - memcpy (buffer, camel_stream_mem->buffer->data + seekable->position, nread); - seekable->position += nread; - } else - nread = 0; - - return nread; -} - -static ssize_t -stream_write (CamelStream *stream, const char *buffer, size_t n) -{ - CamelStreamMem *stream_mem = CAMEL_STREAM_MEM (stream); - CamelSeekableStream *seekable = CAMEL_SEEKABLE_STREAM (stream); - ssize_t nwrite = n; - - if (seekable->bound_end != CAMEL_STREAM_UNBOUND) - nwrite = MIN(seekable->bound_end - seekable->position, n); - - /* FIXME: we shouldn't use g_byte_arrays or g_malloc perhaps? */ - if (seekable->position == stream_mem->buffer->len) { - g_byte_array_append(stream_mem->buffer, (const guint8 *)buffer, nwrite); - } else { - g_byte_array_set_size(stream_mem->buffer, nwrite + stream_mem->buffer->len); - memcpy(stream_mem->buffer->data + seekable->position, buffer, nwrite); - } - seekable->position += nwrite; - - return nwrite; -} - -static gboolean -stream_eos (CamelStream *stream) -{ - CamelStreamMem *stream_mem = CAMEL_STREAM_MEM (stream); - CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (stream); - - return stream_mem->buffer->len <= seekable_stream->position; -} - -static off_t -stream_seek (CamelSeekableStream *stream, off_t offset, - CamelStreamSeekPolicy policy) -{ - off_t position; - CamelStreamMem *stream_mem = CAMEL_STREAM_MEM (stream); - - switch (policy) { - case CAMEL_STREAM_SET: - position = offset; - break; - case CAMEL_STREAM_CUR: - position = stream->position + offset; - break; - case CAMEL_STREAM_END: - position = (stream_mem->buffer)->len + offset; - break; - default: - position = offset; - break; - } - - if (stream->bound_end != CAMEL_STREAM_UNBOUND) - position = MIN (position, stream->bound_end); - if (stream->bound_start != CAMEL_STREAM_UNBOUND) - position = MAX (position, 0); - else - position = MAX (position, stream->bound_start); - - if (position > stream_mem->buffer->len) { - int oldlen = stream_mem->buffer->len; - g_byte_array_set_size (stream_mem->buffer, position); - memset (stream_mem->buffer->data + oldlen, 0, - position - oldlen); - } - - stream->position = position; - - return position; -} diff --git a/camel/camel-stream-mem.h b/camel/camel-stream-mem.h deleted file mode 100644 index af51c36ff7..0000000000 --- a/camel/camel-stream-mem.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-stream-mem.h: stream based on memory buffer */ - -/* - * Authors: Bertrand Guiheneuf - * Michael Zucchi - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_STREAM_MEM_H -#define CAMEL_STREAM_MEM_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include - -#define CAMEL_STREAM_MEM_TYPE (camel_stream_mem_get_type ()) -#define CAMEL_STREAM_MEM(obj) (CAMEL_CHECK_CAST((obj), CAMEL_STREAM_MEM_TYPE, CamelStreamMem)) -#define CAMEL_STREAM_MEM_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_STREAM_MEM_TYPE, CamelStreamMemClass)) -#define CAMEL_IS_STREAM_MEM(o) (CAMEL_CHECK_TYPE((o), CAMEL_STREAM_MEM_TYPE)) - -typedef struct _CamelStreamMemClass CamelStreamMemClass; - -struct _CamelStreamMem { - CamelSeekableStream parent_object; - - gboolean owner; /* do we own the buffer? */ - GByteArray *buffer; -}; - -struct _CamelStreamMemClass { - CamelSeekableStreamClass parent_class; - - /* Virtual methods */ -}; - -/* Standard Camel function */ -CamelType camel_stream_mem_get_type (void); - -/* public methods */ -CamelStream *camel_stream_mem_new(void); -CamelStream *camel_stream_mem_new_with_byte_array(GByteArray *buffer); -CamelStream *camel_stream_mem_new_with_buffer(const char *buffer, size_t len); - -/* these are really only here for implementing classes */ -void camel_stream_mem_set_byte_array(CamelStreamMem *, GByteArray *buffer); -void camel_stream_mem_set_buffer(CamelStreamMem *, const char *buffer, size_t len); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_STREAM_MEM_H */ diff --git a/camel/camel-stream-null.c b/camel/camel-stream-null.c deleted file mode 100644 index 3c0fdee47b..0000000000 --- a/camel/camel-stream-null.c +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* camel-stream.c : abstract class for a stream */ - -/* - * Author: - * Michael Zucchi - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "camel-stream-null.h" - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelStream */ -#define CS_CLASS(so) CAMEL_STREAM_NULL_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -/* dummy implementations, for a NULL stream */ -static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n) { return 0; } -static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n) { ((CamelStreamNull *)stream)->written += n; return n; } -static int stream_close (CamelStream *stream) { return 0; } -static int stream_flush (CamelStream *stream) { return 0; } -static gboolean stream_eos (CamelStream *stream) { return TRUE; } -static int stream_reset (CamelStream *stream) { ((CamelStreamNull *)stream)->written = 0; return 0; } - -static void -camel_stream_null_class_init (CamelStreamClass *camel_stream_null_class) -{ - CamelStreamClass *camel_stream_class = (CamelStreamClass *)camel_stream_null_class; - - parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE ); - - /* virtual method definition */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->close = stream_close; - camel_stream_class->flush = stream_flush; - camel_stream_class->eos = stream_eos; - camel_stream_class->reset = stream_reset; -} - -CamelType -camel_stream_null_get_type (void) -{ - static CamelType camel_stream_null_type = CAMEL_INVALID_TYPE; - - if (camel_stream_null_type == CAMEL_INVALID_TYPE) { - camel_stream_null_type = camel_type_register( camel_stream_get_type(), - "CamelStreamNull", - sizeof( CamelStreamNull ), - sizeof( CamelStreamNullClass ), - (CamelObjectClassInitFunc) camel_stream_null_class_init, - NULL, - NULL, - NULL ); - } - - return camel_stream_null_type; -} - -/** - * camel_stream_null_new: - * - * Returns a NULL stream. A null stream is always at eof, and - * always returns success for all reads and writes. - * - * Return value: the stream - **/ -CamelStream * -camel_stream_null_new(void) -{ - return (CamelStream *)camel_object_new(camel_stream_null_get_type ()); -} diff --git a/camel/camel-stream-null.h b/camel/camel-stream-null.h deleted file mode 100644 index be11da7741..0000000000 --- a/camel/camel-stream-null.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_STREAM_NULL_H -#define _CAMEL_STREAM_NULL_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#define CAMEL_STREAM_NULL(obj) CAMEL_CHECK_CAST (obj, camel_stream_null_get_type (), CamelStreamNull) -#define CAMEL_STREAM_NULL_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_stream_null_get_type (), CamelStreamNullClass) -#define CAMEL_IS_STREAM_NULL(obj) CAMEL_CHECK_TYPE (obj, camel_stream_null_get_type ()) - -typedef struct _CamelStreamNullClass CamelStreamNullClass; - -struct _CamelStreamNull { - CamelStream parent; - - size_t written; -}; - -struct _CamelStreamNullClass { - CamelStreamClass parent_class; -}; - -CamelType camel_stream_null_get_type (void); - -CamelStream *camel_stream_null_new (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_STREAM_NULL_H */ diff --git a/camel/camel-stream-process.c b/camel/camel-stream-process.c deleted file mode 100644 index 6a48ae40d0..0000000000 --- a/camel/camel-stream-process.c +++ /dev/null @@ -1,273 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* camel-stream-process.c : stream over piped process */ - -/* - * Copyright (C) 2003 Ximian Inc. - * - * Authors: David Woodhouse , - * Jeffrey Stedfast - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "camel-stream-process.h" -#include "camel-file-utils.h" - -extern int camel_verbose_debug; - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelStream */ -#define CS_CLASS(so) CAMEL_STREAM_PROCESS_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -/* dummy implementations, for a PROCESS stream */ -static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n); -static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n); -static int stream_close (CamelStream *stream); -static int stream_flush (CamelStream *stream); - -static void -camel_stream_process_finalise (CamelObject *object) -{ - /* Ensure we clean up after ourselves -- kill - the child process and reap it. */ - stream_close (CAMEL_STREAM (object)); -} - -static void -camel_stream_process_class_init (CamelStreamProcessClass *camel_stream_process_class) -{ - CamelStreamClass *camel_stream_class = (CamelStreamClass *) camel_stream_process_class; - - parent_class = camel_type_get_global_classfuncs (CAMEL_OBJECT_TYPE); - - /* virtual method definition */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->close = stream_close; - camel_stream_class->flush = stream_flush; -} - -static void -camel_stream_process_init (gpointer object, gpointer klass) -{ - CamelStreamProcess *stream = CAMEL_STREAM_PROCESS (object); - - stream->sockfd = -1; - stream->childpid = 0; -} - - -CamelType -camel_stream_process_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_stream_get_type (), - "CamelStreamProcess", - sizeof (CamelStreamProcess), - sizeof (CamelStreamProcessClass), - (CamelObjectClassInitFunc) camel_stream_process_class_init, - NULL, - (CamelObjectInitFunc) camel_stream_process_init, - (CamelObjectFinalizeFunc) camel_stream_process_finalise); - } - - return type; -} - -/** - * camel_stream_process_new: - * - * Returns a PROCESS stream. - * - * Return value: the stream - **/ -CamelStream * -camel_stream_process_new (void) -{ - return (CamelStream *) camel_object_new (camel_stream_process_get_type ()); -} - - -static ssize_t -stream_read (CamelStream *stream, char *buffer, size_t n) -{ - CamelStreamProcess *stream_process = CAMEL_STREAM_PROCESS (stream); - - return camel_read (stream_process->sockfd, buffer, n); -} - -static ssize_t -stream_write (CamelStream *stream, const char *buffer, size_t n) -{ - CamelStreamProcess *stream_process = CAMEL_STREAM_PROCESS (stream); - - return camel_write (stream_process->sockfd, buffer, n); -} - -static int -stream_flush (CamelStream *stream) -{ - return 0; -} - -static int -stream_close (CamelStream *object) -{ - CamelStreamProcess *stream = CAMEL_STREAM_PROCESS (object); - - if (camel_verbose_debug) - fprintf (stderr, "Process stream close. sockfd %d, childpid %d\n", - stream->sockfd, stream->childpid); - - if (stream->sockfd != -1) { - close (stream->sockfd); - stream->sockfd = -1; - } - - if (stream->childpid) { - int ret, i; - for (i = 0; i < 4; i++) { - ret = waitpid (stream->childpid, NULL, WNOHANG); - if (camel_verbose_debug) - fprintf (stderr, "waitpid() for pid %d returned %d (errno %d)\n", - stream->childpid, ret, ret == -1 ? errno : 0); - if (ret == stream->childpid || errno == ECHILD) - break; - switch (i) { - case 0: - if (camel_verbose_debug) - fprintf (stderr, "Sending SIGTERM to pid %d\n", - stream->childpid); - kill (stream->childpid, SIGTERM); - break; - case 2: - if (camel_verbose_debug) - fprintf (stderr, "Sending SIGKILL to pid %d\n", - stream->childpid); - kill (stream->childpid, SIGKILL); - break; - case 1: - case 3: - sleep (1); - break; - } - } - - stream->childpid = 0; - } - - return 0; -} - -static void -do_exec_command (int fd, const char *command, char **env) -{ - int i, maxopen; - - /* 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); - - /* What to do with stderr? Possibly put it through a separate pipe - and bring up a dialog box with its output if anything does get - spewed to it? It'd help the user understand what was going wrong - with their command, but it's hard to do cleanly. For now we just - leave it as it is. Perhaps we should close it and reopen /dev/null? */ - - maxopen = sysconf (_SC_OPEN_MAX); - for (i = 3; i < maxopen; i++) - fcntl (i, F_SETFD, FD_CLOEXEC); - - setsid (); -#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. */ - if ((fd = open ("/dev/tty", O_RDONLY)) != -1) { - ioctl (fd, TIOCNOTTY, NULL); - close (fd); - } -#endif /* TIOCNOTTY */ - - /* Set up child's environment. We _add_ to it, don't use execle, - because otherwise we'd destroy stuff like SSH_AUTH_SOCK etc. */ - for ( ; env && *env; env++) { - char *eq = strchr (*env, '='); - - if (!eq) { - unsetenv (*env); - continue; - } - - *eq++ = '\0'; - - setenv (*env, eq, 1); - } - - execl ("/bin/sh", "/bin/sh", "-c", command, NULL); - - if (camel_verbose_debug) - fprintf (stderr, "exec failed %d\n", errno); - - exit (1); -} - -int -camel_stream_process_connect (CamelStreamProcess *stream, const char *command, const char **env) -{ - int sockfds[2]; - - if (stream->sockfd != -1 || stream->childpid) - stream_close (CAMEL_STREAM (stream)); - - if (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfds)) - return -1; - - stream->childpid = fork (); - if (!stream->childpid) { - do_exec_command (sockfds[1], command, (char **)env); - } else if (stream->childpid == -1) { - close (sockfds[0]); - close (sockfds[1]); - stream->sockfd = -1; - return -1; - } - - close (sockfds[1]); - stream->sockfd = sockfds[0]; - - return 0; -} diff --git a/camel/camel-stream-process.h b/camel/camel-stream-process.h deleted file mode 100644 index 15a68e9a60..0000000000 --- a/camel/camel-stream-process.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2003 Ximian Inc. - * - * Authors: David Woodhouse - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_STREAM_NULL_H -#define _CAMEL_STREAM_NULL_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#define CAMEL_STREAM_PROCESS(obj) CAMEL_CHECK_CAST (obj, camel_stream_process_get_type (), CamelStreamProcess) -#define CAMEL_STREAM_PROCESS_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_stream_process_get_type (), CamelStreamProcessClass) -#define CAMEL_IS_STREAM_PROCESS(obj) CAMEL_CHECK_TYPE (obj, camel_stream_process_get_type ()) - -typedef struct _CamelStreamProcessClass CamelStreamProcessClass; -typedef struct _CamelStreamProcess CamelStreamProcess; - -struct _CamelStreamProcess { - CamelStream parent; - - int sockfd; - pid_t childpid; -}; - -struct _CamelStreamProcessClass { - CamelStreamClass parent_class; -}; - -CamelType camel_stream_process_get_type (void); -CamelStream *camel_stream_process_new (void); -int camel_stream_process_connect(CamelStreamProcess *, const char *, const char **); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_STREAM_PROCESS_H */ diff --git a/camel/camel-stream.c b/camel/camel-stream.c deleted file mode 100644 index bcc4640697..0000000000 --- a/camel/camel-stream.c +++ /dev/null @@ -1,281 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-stream.c : abstract class for a stream */ - -/* - * Author: - * Bertrand Guiheneuf - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "camel-stream.h" - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelStream */ -#define CS_CLASS(so) CAMEL_STREAM_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -/* default implementations, do very little */ -static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n) { return 0; } -static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n) { return n; } -static int stream_close (CamelStream *stream) { return 0; } -static int stream_flush (CamelStream *stream) { return 0; } -static gboolean stream_eos (CamelStream *stream) { return stream->eos; } -static int stream_reset (CamelStream *stream) { return 0; } - -static void -camel_stream_class_init (CamelStreamClass *camel_stream_class) -{ - parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE ); - - /* virtual method definition */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->close = stream_close; - camel_stream_class->flush = stream_flush; - camel_stream_class->eos = stream_eos; - camel_stream_class->reset = stream_reset; -} - -CamelType -camel_stream_get_type (void) -{ - static CamelType camel_stream_type = CAMEL_INVALID_TYPE; - - if (camel_stream_type == CAMEL_INVALID_TYPE) { - camel_stream_type = camel_type_register( CAMEL_OBJECT_TYPE, - "CamelStream", - sizeof( CamelStream ), - sizeof( CamelStreamClass ), - (CamelObjectClassInitFunc) camel_stream_class_init, - NULL, - NULL, - NULL ); - } - - return camel_stream_type; -} - - -/** - * camel_stream_read: - * @stream: a CamelStream. - * @buffer: output buffer - * @n: max number of bytes to read. - * - * Attempts to read up to @len bytes from @stream into @buf. - * - * Returns the number of bytes actually read, or -1 on error and set - * errno. - **/ -ssize_t -camel_stream_read (CamelStream *stream, char *buffer, size_t n) -{ - g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); - g_return_val_if_fail (n == 0 || buffer, -1); - - return CS_CLASS (stream)->read (stream, buffer, n); -} - - -/** - * camel_stream_write: - * @stream: a CamelStream object. - * @buffer: buffer to write. - * @n: number of bytes to write - * - * Attempts to write up to @n bytes of @buffer into @stream. - * - * Returns the number of bytes written to the stream, or -1 on error - * along with setting errno. - **/ -ssize_t -camel_stream_write (CamelStream *stream, const char *buffer, size_t n) -{ - g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); - g_return_val_if_fail (n == 0 || buffer, -1); - - return CS_CLASS (stream)->write (stream, buffer, n); -} - - -/** - * camel_stream_flush: - * @stream: stream - * - * Flushes any buffered data to the stream's backing store. Only - * meaningful for writable streams. - * - * Returns 0 on success or -1 on fail along with setting errno. - **/ -int -camel_stream_flush (CamelStream *stream) -{ - g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); - - return CS_CLASS (stream)->flush (stream); -} - - -/** - * camel_stream_close: - * @stream: - * - * Closes the stream. - * - * Returns 0 on success or -1 on error. - **/ -int -camel_stream_close (CamelStream *stream) -{ - g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); - - return CS_CLASS (stream)->close (stream); -} - - -/** - * camel_stream_eos: - * @stream: a CamelStream object - * - * Tests if there are bytes left to read on the @stream object. - * - * Returns %TRUE on EOS or %FALSE otherwise. - **/ -gboolean -camel_stream_eos (CamelStream *stream) -{ - g_return_val_if_fail (CAMEL_IS_STREAM (stream), TRUE); - - return CS_CLASS (stream)->eos (stream); -} - - -/** - * camel_stream_reset: - * @stream: the stream object - * - * Resets the stream. That is, put it in a state where it can be read - * from the beginning again. Not all streams in Camel are seekable, - * but they must all be resettable. - * - * Returns 0 on success or -1 on error along with setting errno. - **/ -int -camel_stream_reset (CamelStream *stream) -{ - g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); - - return CS_CLASS (stream)->reset (stream); -} - -/***************** Utility functions ********************/ - -/** - * camel_stream_write_string: - * @stream: a stream object - * @string: a string - * - * Writes the string to the stream. - * - * Returns the number of characters written or -1 on error. - **/ -ssize_t -camel_stream_write_string (CamelStream *stream, const char *string) -{ - return camel_stream_write (stream, string, strlen (string)); -} - - -/** - * camel_stream_printf: - * @stream: a stream object - * @fmt: a printf-style format string - * - * Write formatted output to a stream. - * - * Returns the number of characters written or -1 on error. - **/ -ssize_t -camel_stream_printf (CamelStream *stream, const char *fmt, ... ) -{ - va_list args; - char *string; - ssize_t ret; - - g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); - - va_start (args, fmt); - string = g_strdup_vprintf (fmt, args); - va_end (args); - - if (!string) - return -1; - - ret = camel_stream_write (stream, string, strlen (string)); - g_free (string); - return ret; -} - - -/** - * camel_stream_write_to_stream: - * @stream: Source CamelStream. - * @output_stream: Destination CamelStream. - * - * Write all of a stream (until eos) into another stream, in a - * blocking fashion. - * - * Returns -1 on error, or the number of bytes succesfully - * copied across streams. - **/ -ssize_t -camel_stream_write_to_stream (CamelStream *stream, CamelStream *output_stream) -{ - char tmp_buf[4096]; - ssize_t total = 0; - ssize_t nb_read; - ssize_t nb_written; - - g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); - g_return_val_if_fail (CAMEL_IS_STREAM (output_stream), -1); - - while (!camel_stream_eos (stream)) { - nb_read = camel_stream_read (stream, tmp_buf, sizeof (tmp_buf)); - if (nb_read < 0) - return -1; - else if (nb_read > 0) { - nb_written = 0; - - while (nb_written < nb_read) { - ssize_t len = camel_stream_write (output_stream, tmp_buf + nb_written, - nb_read - nb_written); - if (len < 0) - return -1; - nb_written += len; - } - total += nb_written; - } - } - return total; -} diff --git a/camel/camel-stream.h b/camel/camel-stream.h deleted file mode 100644 index f75e882a70..0000000000 --- a/camel/camel-stream.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* camel-stream.h : class for an abstract stream */ - -/* - * Author: - * Bertrand Guiheneuf - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_STREAM_H -#define CAMEL_STREAM_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include -#include - -#define CAMEL_STREAM_TYPE (camel_stream_get_type ()) -#define CAMEL_STREAM(obj) (CAMEL_CHECK_CAST((obj), CAMEL_STREAM_TYPE, CamelStream)) -#define CAMEL_STREAM_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_STREAM_TYPE, CamelStreamClass)) -#define CAMEL_IS_STREAM(o) (CAMEL_CHECK_TYPE((o), CAMEL_STREAM_TYPE)) - -struct _CamelStream -{ - CamelObject parent_object; - - gboolean eos; -}; - -typedef struct { - CamelObjectClass parent_class; - - /* Virtual methods */ - - ssize_t (*read) (CamelStream *stream, char *buffer, size_t n); - ssize_t (*write) (CamelStream *stream, const char *buffer, size_t n); - int (*close) (CamelStream *stream); - int (*flush) (CamelStream *stream); - gboolean (*eos) (CamelStream *stream); - int (*reset) (CamelStream *stream); - -} CamelStreamClass; - -/* Standard Camel function */ -CamelType camel_stream_get_type (void); - -/* public methods */ -ssize_t camel_stream_read (CamelStream *stream, char *buffer, size_t n); -ssize_t camel_stream_write (CamelStream *stream, const char *buffer, size_t n); -int camel_stream_flush (CamelStream *stream); -int camel_stream_close (CamelStream *stream); -gboolean camel_stream_eos (CamelStream *stream); -int camel_stream_reset (CamelStream *stream); - -/* utility macros and funcs */ -ssize_t camel_stream_write_string (CamelStream *stream, const char *string); -ssize_t camel_stream_printf (CamelStream *stream, const char *fmt, ... ) G_GNUC_PRINTF (2, 3); -ssize_t camel_stream_vprintf (CamelStream *stream, const char *fmt, va_list ap); - -/* Write a whole stream to another stream, until eof or error on - * either stream. - */ -ssize_t camel_stream_write_to_stream (CamelStream *stream, CamelStream *output_stream); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_STREAM_H */ diff --git a/camel/camel-string-utils.c b/camel/camel-string-utils.c deleted file mode 100644 index d9927d629a..0000000000 --- a/camel/camel-string-utils.c +++ /dev/null @@ -1,110 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "camel-string-utils.h" - - -int -camel_strcase_equal (gconstpointer a, gconstpointer b) -{ - return (g_ascii_strcasecmp ((const char *) a, (const char *) b) == 0); -} - -guint -camel_strcase_hash (gconstpointer v) -{ - const char *p = (char *) v; - guint h = 0, g; - - for ( ; *p != '\0'; p++) { - h = (h << 4) + g_ascii_toupper (*p); - if ((g = h & 0xf0000000)) { - h = h ^ (g >> 24); - h = h ^ g; - } - } - - return h; -} - - -static void -free_string (gpointer string, gpointer user_data) -{ - g_free (string); -} - -void -camel_string_list_free (GList *string_list) -{ - if (string_list == NULL) - return; - - g_list_foreach (string_list, free_string, NULL); - g_list_free (string_list); -} - -char * -camel_strstrcase (const char *haystack, const char *needle) -{ - /* find the needle in the haystack neglecting case */ - const char *ptr; - guint len; - - g_return_val_if_fail (haystack != NULL, NULL); - g_return_val_if_fail (needle != NULL, NULL); - - len = strlen (needle); - if (len > strlen (haystack)) - return NULL; - - if (len == 0) - return (char *) haystack; - - for (ptr = haystack; *(ptr + len - 1) != '\0'; ptr++) - if (!strncasecmp (ptr, needle, len)) - return (char *) ptr; - - return NULL; -} - - -const char * -camel_strdown (char *str) -{ - register char *s = str; - - while (*s) { - if (*s >= 'A' && *s <= 'Z') - *s += 0x20; - s++; - } - - return str; -} diff --git a/camel/camel-string-utils.h b/camel/camel-string-utils.h deleted file mode 100644 index 54cbad3fad..0000000000 --- a/camel/camel-string-utils.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __CAMEL_STRING_UTILS_H__ -#define __CAMEL_STRING_UTILS_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -int camel_strcase_equal (gconstpointer a, gconstpointer b); -guint camel_strcase_hash (gconstpointer v); - -void camel_string_list_free (GList *string_list); - -char *camel_strstrcase (const char *haystack, const char *needle); - -const char *camel_strdown (char *str); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_STRING_UTILS_H__ */ diff --git a/camel/camel-tcp-stream-openssl.c b/camel/camel-tcp-stream-openssl.c deleted file mode 100644 index c7250a84d1..0000000000 --- a/camel/camel-tcp-stream-openssl.c +++ /dev/null @@ -1,954 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_OPENSSL - -#include "camel-tcp-stream-ssl.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "camel-session.h" -#include "camel-service.h" -#include "camel-operation.h" -#include "camel-certdb.h" - -#define d(x) - -#define TIMEOUT_USEC (10000) - -static CamelTcpStreamClass *parent_class = NULL; - -/* Returns the class for a CamelTcpStreamSSL */ -#define CTSR_CLASS(so) CAMEL_TCP_STREAM_SSL_CLASS (CAMEL_OBJECT_GET_CLASS (so)) - -static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n); -static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n); -static int stream_flush (CamelStream *stream); -static int stream_close (CamelStream *stream); - -static int stream_connect (CamelTcpStream *stream, struct hostent *host, int port); -static int stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data); -static int stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data); -static CamelTcpAddress *stream_get_local_address (CamelTcpStream *stream); -static CamelTcpAddress *stream_get_remote_address (CamelTcpStream *stream); - -static SSL *open_ssl_connection (CamelService *service, int sockfd, CamelTcpStreamSSL *openssl); - -struct _CamelTcpStreamSSLPrivate { - int sockfd; - SSL *ssl; - - CamelService *service; - char *expected_host; - gboolean ssl_mode; - guint32 flags; -}; - -static void -camel_tcp_stream_ssl_class_init (CamelTcpStreamSSLClass *camel_tcp_stream_ssl_class) -{ - CamelTcpStreamClass *camel_tcp_stream_class = - CAMEL_TCP_STREAM_CLASS (camel_tcp_stream_ssl_class); - CamelStreamClass *camel_stream_class = - CAMEL_STREAM_CLASS (camel_tcp_stream_ssl_class); - - parent_class = CAMEL_TCP_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ())); - - /* virtual method overload */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->flush = stream_flush; - camel_stream_class->close = stream_close; - - camel_tcp_stream_class->connect = stream_connect; - camel_tcp_stream_class->getsockopt = stream_getsockopt; - camel_tcp_stream_class->setsockopt = stream_setsockopt; - camel_tcp_stream_class->get_local_address = stream_get_local_address; - camel_tcp_stream_class->get_remote_address = stream_get_remote_address; - - /* init OpenSSL stuff */ - SSLeay_add_ssl_algorithms (); - SSL_load_error_strings (); -} - -static void -camel_tcp_stream_ssl_init (gpointer object, gpointer klass) -{ - CamelTcpStreamSSL *stream = CAMEL_TCP_STREAM_SSL (object); - - stream->priv = g_new0 (struct _CamelTcpStreamSSLPrivate, 1); - stream->priv->sockfd = -1; -} - -static void -camel_tcp_stream_ssl_finalize (CamelObject *object) -{ - CamelTcpStreamSSL *stream = CAMEL_TCP_STREAM_SSL (object); - - if (stream->priv->ssl) { - SSL_shutdown (stream->priv->ssl); - - if (stream->priv->ssl->ctx) { - SSL_CTX_free (stream->priv->ssl->ctx); - } - - SSL_free (stream->priv->ssl); - } - - if (stream->priv->sockfd != -1) - close (stream->priv->sockfd); - - g_free (stream->priv->expected_host); - - g_free (stream->priv); -} - - -CamelType -camel_tcp_stream_ssl_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_tcp_stream_get_type (), - "CamelTcpStreamSSL", - sizeof (CamelTcpStreamSSL), - sizeof (CamelTcpStreamSSLClass), - (CamelObjectClassInitFunc) camel_tcp_stream_ssl_class_init, - NULL, - (CamelObjectInitFunc) camel_tcp_stream_ssl_init, - (CamelObjectFinalizeFunc) camel_tcp_stream_ssl_finalize); - } - - return type; -} - - -/** - * camel_tcp_stream_ssl_new: - * @service: camel service - * @expected_host: host that the stream is expecting to connect with. - * @flags: flags - * - * Since the SSL certificate authenticator may need to prompt the - * user, a CamelService is needed. @expected_host is needed as a - * protection against an MITM attack. - * - * Return value: a ssl stream (in ssl mode) - **/ -CamelStream * -camel_tcp_stream_ssl_new (CamelService *service, const char *expected_host, guint32 flags) -{ - CamelTcpStreamSSL *stream; - - stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ())); - - stream->priv->service = service; - stream->priv->expected_host = g_strdup (expected_host); - stream->priv->ssl_mode = TRUE; - stream->priv->flags = flags; - - return CAMEL_STREAM (stream); -} - - -/** - * camel_tcp_stream_ssl_new_raw: - * @service: camel service - * @expected_host: host that the stream is expecting to connect with. - * @flags: flags - * - * Since the SSL certificate authenticator may need to prompt the - * user, a CamelService is needed. @expected_host is needed as a - * protection against an MITM attack. - * - * Return value: a ssl-capable stream (in non ssl mode) - **/ -CamelStream * -camel_tcp_stream_ssl_new_raw (CamelService *service, const char *expected_host, guint32 flags) -{ - CamelTcpStreamSSL *stream; - - stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ())); - - stream->priv->service = service; - stream->priv->expected_host = g_strdup (expected_host); - stream->priv->ssl_mode = FALSE; - stream->priv->flags = flags; - - return CAMEL_STREAM (stream); -} - - -static int -ssl_errno (SSL *ssl, int ret) -{ - switch (SSL_get_error (ssl, ret)) { - case SSL_ERROR_NONE: - return 0; - case SSL_ERROR_ZERO_RETURN: - /* this one does not map well at all */ - d(printf ("ssl_errno: SSL_ERROR_ZERO_RETURN\n")); - return EINVAL; - case SSL_ERROR_WANT_READ: /* non-fatal; retry */ - case SSL_ERROR_WANT_WRITE: /* non-fatal; retry */ - d(printf ("ssl_errno: SSL_ERROR_WANT_[READ,WRITE]\n")); - return EAGAIN; - case SSL_ERROR_SYSCALL: - d(printf ("ssl_errno: SSL_ERROR_SYSCALL\n")); - return EINTR; - case SSL_ERROR_SSL: - d(printf ("ssl_errno: SSL_ERROR_SSL <-- very useful error...riiiiight\n")); - return EINTR; - default: - d(printf ("ssl_errno: default error\n")); - return EINTR; - } -} - - -/** - * camel_tcp_stream_ssl_enable_ssl: - * @stream: ssl stream - * - * Toggles an ssl-capable stream into ssl mode (if it isn't already). - * - * Returns 0 on success or -1 on fail. - **/ -int -camel_tcp_stream_ssl_enable_ssl (CamelTcpStreamSSL *stream) -{ - SSL *ssl; - - g_return_val_if_fail (CAMEL_IS_TCP_STREAM_SSL (stream), -1); - - if (stream->priv->sockfd != -1 && !stream->priv->ssl_mode) { - ssl = open_ssl_connection (stream->priv->service, stream->priv->sockfd, stream); - if (ssl == NULL) { - stream->priv->sockfd = -1; - return -1; - } - - stream->priv->ssl = ssl; - } - - stream->priv->ssl_mode = TRUE; - - return 0; -} - - -static ssize_t -stream_read (CamelStream *stream, char *buffer, size_t n) -{ - CamelTcpStreamSSL *openssl = CAMEL_TCP_STREAM_SSL (stream); - SSL *ssl = openssl->priv->ssl; - ssize_t nread; - int cancel_fd; - - if (camel_operation_cancel_check (NULL)) { - errno = EINTR; - return -1; - } - - cancel_fd = camel_operation_cancel_fd (NULL); - if (cancel_fd == -1) { - do { - if (ssl) { - nread = SSL_read (ssl, buffer, n); - if (nread < 0) - errno = ssl_errno (ssl, nread); - } else { - nread = read (openssl->priv->sockfd, buffer, n); - } - } while (nread < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); - } else { - int error, flags, fdmax; - struct timeval timeout; - fd_set rdset; - - flags = fcntl (openssl->priv->sockfd, F_GETFL); - fcntl (openssl->priv->sockfd, F_SETFL, flags | O_NONBLOCK); - - fdmax = MAX (openssl->priv->sockfd, cancel_fd) + 1; - - do { - FD_ZERO (&rdset); - FD_SET (openssl->priv->sockfd, &rdset); - FD_SET (cancel_fd, &rdset); - - timeout.tv_sec = 0; - timeout.tv_usec = TIMEOUT_USEC; - select (fdmax, &rdset, 0, 0, &timeout); - if (FD_ISSET (cancel_fd, &rdset)) { - fcntl (openssl->priv->sockfd, F_SETFL, flags); - errno = EINTR; - return -1; - } - - do { - if (ssl) { - nread = SSL_read (ssl, buffer, n); - if (nread < 0) - errno = ssl_errno (ssl, nread); - } else { - nread = read (openssl->priv->sockfd, buffer, n); - } - } while (nread < 0 && errno == EINTR); - } while (nread < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)); - - error = errno; - fcntl (openssl->priv->sockfd, F_SETFL, flags); - errno = error; - } - - return nread; -} - -static ssize_t -stream_write (CamelStream *stream, const char *buffer, size_t n) -{ - CamelTcpStreamSSL *openssl = CAMEL_TCP_STREAM_SSL (stream); - SSL *ssl = openssl->priv->ssl; - ssize_t w, written = 0; - int cancel_fd; - - if (camel_operation_cancel_check (NULL)) { - errno = EINTR; - return -1; - } - - cancel_fd = camel_operation_cancel_fd (NULL); - if (cancel_fd == -1) { - do { - do { - if (ssl) { - w = SSL_write (ssl, buffer + written, n - written); - if (w < 0) - errno = ssl_errno (ssl, w); - } else { - w = write (openssl->priv->sockfd, buffer + written, n - written); - } - } while (w < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); - - if (w > 0) - written += w; - } while (w != -1 && written < n); - } else { - int error, flags, fdmax; - struct timeval timeout; - fd_set rdset, wrset; - - flags = fcntl (openssl->priv->sockfd, F_GETFL); - fcntl (openssl->priv->sockfd, F_SETFL, flags | O_NONBLOCK); - - fdmax = MAX (openssl->priv->sockfd, cancel_fd) + 1; - do { - FD_ZERO (&rdset); - FD_ZERO (&wrset); - FD_SET (openssl->priv->sockfd, &wrset); - FD_SET (cancel_fd, &rdset); - - timeout.tv_sec = 0; - timeout.tv_usec = TIMEOUT_USEC; - select (fdmax, &rdset, &wrset, 0, &timeout); - if (FD_ISSET (cancel_fd, &rdset)) { - fcntl (openssl->priv->sockfd, F_SETFL, flags); - errno = EINTR; - return -1; - } - - do { - if (ssl) { - w = SSL_write (ssl, buffer + written, n - written); - if (w < 0) - errno = ssl_errno (ssl, w); - } else { - w = write (openssl->priv->sockfd, buffer + written, n - written); - } - } while (w < 0 && errno == EINTR); - - if (w < 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - w = 0; - } else { - error = errno; - fcntl (openssl->priv->sockfd, F_SETFL, flags); - errno = error; - return -1; - } - } else - written += w; - } while (w >= 0 && written < n); - - fcntl (openssl->priv->sockfd, F_SETFL, flags); - } - - return written; -} - -static int -stream_flush (CamelStream *stream) -{ - return 0; -} - - -static void -close_ssl_connection (SSL *ssl) -{ - if (ssl) { - SSL_shutdown (ssl); - - if (ssl->ctx) - SSL_CTX_free (ssl->ctx); - - SSL_free (ssl); - } -} - -static int -stream_close (CamelStream *stream) -{ - close_ssl_connection (((CamelTcpStreamSSL *)stream)->priv->ssl); - ((CamelTcpStreamSSL *)stream)->priv->ssl = NULL; - - if (close (((CamelTcpStreamSSL *)stream)->priv->sockfd) == -1) - return -1; - - ((CamelTcpStreamSSL *)stream)->priv->sockfd = -1; - return 0; -} - -/* this is a 'cancellable' connect, cancellable from camel_operation_cancel etc */ -/* returns -1 & errno == EINTR if the connection was cancelled */ -static int -socket_connect (struct hostent *h, int port) -{ -#ifdef ENABLE_IPv6 - struct sockaddr_in6 sin6; -#endif - struct sockaddr_in sin; - struct sockaddr *saddr; - struct timeval tv; - socklen_t len; - int cancel_fd; - int ret, fd; - - /* see if we're cancelled yet */ - if (camel_operation_cancel_check (NULL)) { - errno = EINTR; - return -1; - } - - /* setup connect, we do it using a nonblocking socket so we can poll it */ -#ifdef ENABLE_IPv6 - if (h->h_addrtype == AF_INET6) { - sin6.sin6_port = htons (port); - sin6.sin6_family = h->h_addrtype; - memcpy (&sin6.sin6_addr, h->h_addr, sizeof (sin6.sin6_addr)); - saddr = (struct sockaddr *) &sin6; - len = sizeof (sin6); - } else { -#endif - sin.sin_port = htons (port); - sin.sin_family = h->h_addrtype; - memcpy (&sin.sin_addr, h->h_addr, sizeof (sin.sin_addr)); - saddr = (struct sockaddr *) &sin; - len = sizeof (sin); -#ifdef ENABLE_IPv6 - } -#endif - - fd = socket (h->h_addrtype, SOCK_STREAM, 0); - - cancel_fd = camel_operation_cancel_fd (NULL); - if (cancel_fd == -1) { - ret = connect (fd, saddr, len); - if (ret == -1) { - close (fd); - return -1; - } - - return fd; - } else { - fd_set rdset, wrset; - int flags, fdmax; - - flags = fcntl (fd, F_GETFL); - fcntl (fd, F_SETFL, flags | O_NONBLOCK); - - ret = connect (fd, saddr, len); - if (ret == 0) { - fcntl (fd, F_SETFL, flags); - return fd; - } - - if (errno != EINPROGRESS) { - close (fd); - return -1; - } - - FD_ZERO (&rdset); - FD_ZERO (&wrset); - FD_SET (fd, &wrset); - FD_SET (cancel_fd, &rdset); - fdmax = MAX (fd, cancel_fd) + 1; - tv.tv_usec = 0; - tv.tv_sec = 60 * 4; - - if (select (fdmax, &rdset, &wrset, 0, &tv) == 0) { - close (fd); - errno = ETIMEDOUT; - return -1; - } - - if (cancel_fd != -1 && FD_ISSET (cancel_fd, &rdset)) { - close (fd); - errno = EINTR; - return -1; - } else { - len = sizeof (int); - - if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &len) == -1) { - close (fd); - return -1; - } - - if (ret != 0) { - close (fd); - errno = ret; - return -1; - } - } - - fcntl (fd, F_SETFL, flags); - } - - return fd; -} - -static const char * -x509_strerror (int err) -{ - switch (err) { - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - return _("Unable to get issuer's certificate"); - case X509_V_ERR_UNABLE_TO_GET_CRL: - return _("Unable to get Certificate Revocation List"); - case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: - return _("Unable to decrypt certificate signature"); - case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: - return _("Unable to decrypt Certificate Revocation List signature"); - case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: - return _("Unable to decode issuer's public key"); - case X509_V_ERR_CERT_SIGNATURE_FAILURE: - return _("Certificate signature failure"); - case X509_V_ERR_CRL_SIGNATURE_FAILURE: - return _("Certificate Revocation List signature failure"); - case X509_V_ERR_CERT_NOT_YET_VALID: - return _("Certificate not yet valid"); - case X509_V_ERR_CERT_HAS_EXPIRED: - return _("Certificate has expired"); - case X509_V_ERR_CRL_NOT_YET_VALID: - return _("CRL not yet valid"); - case X509_V_ERR_CRL_HAS_EXPIRED: - return _("CRL has expired"); - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: - case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: - return _("Error in CRL"); - case X509_V_ERR_OUT_OF_MEM: - return _("Out of memory"); - case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - return _("Zero-depth self-signed certificate"); - case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - return _("Self-signed certificate in chain"); - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - return _("Unable to get issuer's certificate locally"); - case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: - return _("Unable to verify leaf signature"); - case X509_V_ERR_CERT_CHAIN_TOO_LONG: - return _("Certificate chain too long"); - case X509_V_ERR_CERT_REVOKED: - return _("Certificate Revoked"); - case X509_V_ERR_INVALID_CA: - return _("Invalid Certificate Authority (CA)"); - case X509_V_ERR_PATH_LENGTH_EXCEEDED: - return _("Path length exceeded"); - case X509_V_ERR_INVALID_PURPOSE: - return _("Invalid purpose"); - case X509_V_ERR_CERT_UNTRUSTED: - return _("Certificate untrusted"); - case X509_V_ERR_CERT_REJECTED: - return _("Certificate rejected"); - /* These are 'informational' when looking for issuer cert */ - case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: - return _("Subject/Issuer mismatch"); - case X509_V_ERR_AKID_SKID_MISMATCH: - return _("AKID/SKID mismatch"); - case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: - return _("AKID/Issuer serial mismatch"); - case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: - return _("Key usage does not support certificate signing"); - /* The application is not happy */ - case X509_V_ERR_APPLICATION_VERIFICATION: - return _("Error in application verification"); - default: - return _("Unknown"); - } -} - -static int -ssl_verify (int ok, X509_STORE_CTX *ctx) -{ - unsigned char md5sum[16], fingerprint[40], *f; - CamelTcpStreamSSL *stream; - CamelService *service; - CamelCertDB *certdb = NULL; - CamelCert *ccert = NULL; - char *prompt, *cert_str; - int err, md5len, i; - char buf[257]; - X509 *cert; - SSL *ssl; - - if (ok) - return TRUE; - - ssl = X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx ()); - - stream = SSL_CTX_get_app_data (ssl->ctx); - if (!stream) - return FALSE; - - service = stream->priv->service; - - cert = X509_STORE_CTX_get_current_cert (ctx); - err = X509_STORE_CTX_get_error (ctx); - - /* calculate the MD5 hash of the raw certificate */ - md5len = sizeof (md5sum); - X509_digest (cert, EVP_md5 (), md5sum, &md5len); - for (i = 0, f = fingerprint; i < 16; i++, f += 3) - sprintf (f, "%.2x%c", md5sum[i], i != 15 ? ':' : '\0'); - -#define GET_STRING(name) X509_NAME_oneline (name, buf, 256) - - certdb = camel_certdb_get_default (); - if (certdb) { - ccert = camel_certdb_get_cert (certdb, fingerprint); - if (ccert) { - if (ccert->trust != CAMEL_CERT_TRUST_UNKNOWN) { - ok = ccert->trust != CAMEL_CERT_TRUST_NEVER; - camel_certdb_cert_unref (certdb, ccert); - camel_object_unref (certdb); - - return ok; - } - } else { - /* create a new camel-cert */ - ccert = camel_certdb_cert_new (certdb); - camel_cert_set_issuer (certdb, ccert, GET_STRING (X509_get_issuer_name (cert))); - camel_cert_set_subject (certdb, ccert, GET_STRING (X509_get_subject_name (cert))); - camel_cert_set_hostname (certdb, ccert, stream->priv->expected_host); - camel_cert_set_fingerprint (certdb, ccert, fingerprint); - camel_cert_set_trust (certdb, ccert, CAMEL_CERT_TRUST_UNKNOWN); - - /* Add the certificate to our db */ - camel_certdb_add (certdb, ccert); - } - } - - cert_str = g_strdup_printf (_("Issuer: %s\n" - "Subject: %s\n" - "Fingerprint: %s\n" - "Signature: %s"), - GET_STRING (X509_get_issuer_name (cert)), - GET_STRING (X509_get_subject_name (cert)), - fingerprint, cert->valid ? _("GOOD") : _("BAD")); - - prompt = g_strdup_printf (_("Bad certificate from %s:\n\n%s\n\n%s\n\n" - "Do you wish to accept anyway?"), - service->url->host, cert_str, x509_strerror (err)); - - ok = camel_session_alert_user (service->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE); - g_free (prompt); - - if (ok && ccert) { - camel_cert_set_trust (certdb, ccert, CAMEL_CERT_TRUST_FULLY); - camel_certdb_touch (certdb); - } - - if (certdb) { - camel_certdb_cert_unref (certdb, ccert); - camel_object_unref (certdb); - } - - return ok; -} - -static SSL * -open_ssl_connection (CamelService *service, int sockfd, CamelTcpStreamSSL *openssl) -{ - SSL_CTX *ssl_ctx = NULL; - SSL *ssl = NULL; - int n; - - /* SSLv23_client_method will negotiate with SSL v2, v3, or TLS v1 */ - ssl_ctx = SSL_CTX_new (SSLv23_client_method ()); - g_return_val_if_fail (ssl_ctx != NULL, NULL); - - SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_PEER, &ssl_verify); - ssl = SSL_new (ssl_ctx); - SSL_set_fd (ssl, sockfd); - - SSL_CTX_set_app_data (ssl_ctx, openssl); - - n = SSL_connect (ssl); - if (n != 1) { - int errnosave = ssl_errno (ssl, n); - - SSL_shutdown (ssl); - - if (ssl->ctx) - SSL_CTX_free (ssl->ctx); - - SSL_free (ssl); - ssl = NULL; - - close (sockfd); - - errno = errnosave; - } - - return ssl; -} - -static int -stream_connect (CamelTcpStream *stream, struct hostent *host, int port) -{ - CamelTcpStreamSSL *openssl = CAMEL_TCP_STREAM_SSL (stream); - SSL *ssl = NULL; - int fd; - - g_return_val_if_fail (host != NULL, -1); - - fd = socket_connect (host, port); - if (fd == -1) - return -1; - - if (openssl->priv->ssl_mode) { - ssl = open_ssl_connection (openssl->priv->service, fd, openssl); - if (!ssl) - return -1; - } - - openssl->priv->sockfd = fd; - openssl->priv->ssl = ssl; - - return 0; -} - - -static int -get_sockopt_level (const CamelSockOptData *data) -{ - switch (data->option) { - case CAMEL_SOCKOPT_MAXSEGMENT: - case CAMEL_SOCKOPT_NODELAY: - return IPPROTO_TCP; - default: - return SOL_SOCKET; - } -} - -static int -get_sockopt_optname (const CamelSockOptData *data) -{ - switch (data->option) { - case CAMEL_SOCKOPT_MAXSEGMENT: - return TCP_MAXSEG; - case CAMEL_SOCKOPT_NODELAY: - return TCP_NODELAY; - case CAMEL_SOCKOPT_BROADCAST: - return SO_BROADCAST; - case CAMEL_SOCKOPT_KEEPALIVE: - return SO_KEEPALIVE; - case CAMEL_SOCKOPT_LINGER: - return SO_LINGER; - case CAMEL_SOCKOPT_RECVBUFFERSIZE: - return SO_RCVBUF; - case CAMEL_SOCKOPT_SENDBUFFERSIZE: - return SO_SNDBUF; - case CAMEL_SOCKOPT_REUSEADDR: - return SO_REUSEADDR; - case CAMEL_SOCKOPT_IPTYPEOFSERVICE: - return SO_TYPE; - default: - return -1; - } -} - -static int -stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data) -{ - int optname, optlen; - - if ((optname = get_sockopt_optname (data)) == -1) - return -1; - - if (data->option == CAMEL_SOCKOPT_NONBLOCKING) { - int flags; - - flags = fcntl (((CamelTcpStreamSSL *) stream)->priv->sockfd, F_GETFL); - if (flags == -1) - return -1; - - data->value.non_blocking = flags & O_NONBLOCK ? TRUE : FALSE; - - return 0; - } - - return getsockopt (((CamelTcpStreamSSL *) stream)->priv->sockfd, - get_sockopt_level (data), - optname, - (void *) &data->value, - &optlen); -} - -static int -stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data) -{ - int optname; - - if ((optname = get_sockopt_optname (data)) == -1) - return -1; - - if (data->option == CAMEL_SOCKOPT_NONBLOCKING) { - int flags, set; - - flags = fcntl (((CamelTcpStreamSSL *) stream)->priv->sockfd, F_GETFL); - if (flags == -1) - return -1; - - set = data->value.non_blocking ? O_NONBLOCK : 0; - flags = (flags & ~O_NONBLOCK) | set; - - if (fcntl (((CamelTcpStreamSSL *) stream)->priv->sockfd, F_SETFL, flags) == -1) - return -1; - - return 0; - } - - return setsockopt (((CamelTcpStreamSSL *) stream)->priv->sockfd, - get_sockopt_level (data), - optname, - (void *) &data->value, - sizeof (data->value)); -} - -#ifdef ENABLE_IPv6 -#define MIN_SOCKADDR_BUFLEN (sizeof (struct sockaddr_in6)) -#else -#define MIN_SOCKADDR_BUFLEN (sizeof (struct sockaddr_in)) -#endif - -static CamelTcpAddress * -stream_get_local_address (CamelTcpStream *stream) -{ - unsigned char buf[MIN_SOCKADDR_BUFLEN]; -#ifdef ENABLE_IPv6 - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) buf; -#endif - struct sockaddr_in *sin = (struct sockaddr_in *) buf; - struct sockaddr *saddr = (struct sockaddr *) buf; - gpointer address; - socklen_t len; - int family; - - len = MIN_SOCKADDR_BUFLEN; - - if (getsockname (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd, saddr, &len) == -1) - return NULL; - - if (saddr->sa_family == AF_INET) { - family = CAMEL_TCP_ADDRESS_IPv4; - address = &sin->sin_addr; -#ifdef ENABLE_IPv6 - } else if (saddr->sa_family == AF_INET6) { - family = CAMEL_TCP_ADDRESS_IPv6; - address = &sin6->sin6_addr; -#endif - } else - return NULL; - - return camel_tcp_address_new (family, sin->sin_port, len, address); -} - -static CamelTcpAddress * -stream_get_remote_address (CamelTcpStream *stream) -{ - unsigned char buf[MIN_SOCKADDR_BUFLEN]; -#ifdef ENABLE_IPv6 - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) buf; -#endif - struct sockaddr_in *sin = (struct sockaddr_in *) buf; - struct sockaddr *saddr = (struct sockaddr *) buf; - gpointer address; - socklen_t len; - int family; - - len = MIN_SOCKADDR_BUFLEN; - - if (getpeername (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd, saddr, &len) == -1) - return NULL; - - if (saddr->sa_family == AF_INET) { - family = CAMEL_TCP_ADDRESS_IPv4; - address = &sin->sin_addr; -#ifdef ENABLE_IPv6 - } else if (saddr->sa_family == AF_INET6) { - family = CAMEL_TCP_ADDRESS_IPv6; - address = &sin6->sin6_addr; -#endif - } else - return NULL; - - return camel_tcp_address_new (family, sin->sin_port, len, address); -} - -#endif /* HAVE_OPENSSL */ diff --git a/camel/camel-tcp-stream-raw.c b/camel/camel-tcp-stream-raw.c deleted file mode 100644 index 819647cff6..0000000000 --- a/camel/camel-tcp-stream-raw.c +++ /dev/null @@ -1,562 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "camel-tcp-stream-raw.h" -#include "camel-file-utils.h" -#include "camel-operation.h" - -static CamelTcpStreamClass *parent_class = NULL; - -/* Returns the class for a CamelTcpStreamRaw */ -#define CTSR_CLASS(so) CAMEL_TCP_STREAM_RAW_CLASS (CAMEL_OBJECT_GET_CLASS (so)) - -static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n); -static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n); -static int stream_flush (CamelStream *stream); -static int stream_close (CamelStream *stream); - -static int stream_connect (CamelTcpStream *stream, struct hostent *host, int port); -static int stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data); -static int stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data); -static CamelTcpAddress *stream_get_local_address (CamelTcpStream *stream); -static CamelTcpAddress *stream_get_remote_address (CamelTcpStream *stream); - -static void -camel_tcp_stream_raw_class_init (CamelTcpStreamRawClass *camel_tcp_stream_raw_class) -{ - CamelTcpStreamClass *camel_tcp_stream_class = - CAMEL_TCP_STREAM_CLASS (camel_tcp_stream_raw_class); - CamelStreamClass *camel_stream_class = - CAMEL_STREAM_CLASS (camel_tcp_stream_raw_class); - - parent_class = CAMEL_TCP_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ())); - - /* virtual method overload */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->flush = stream_flush; - camel_stream_class->close = stream_close; - - camel_tcp_stream_class->connect = stream_connect; - camel_tcp_stream_class->getsockopt = stream_getsockopt; - camel_tcp_stream_class->setsockopt = stream_setsockopt; - camel_tcp_stream_class->get_local_address = stream_get_local_address; - camel_tcp_stream_class->get_remote_address = stream_get_remote_address; -} - -static void -camel_tcp_stream_raw_init (gpointer object, gpointer klass) -{ - CamelTcpStreamRaw *stream = CAMEL_TCP_STREAM_RAW (object); - - stream->sockfd = -1; -} - -static void -camel_tcp_stream_raw_finalize (CamelObject *object) -{ - CamelTcpStreamRaw *stream = CAMEL_TCP_STREAM_RAW (object); - - if (stream->sockfd != -1) - close (stream->sockfd); -} - - -CamelType -camel_tcp_stream_raw_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_tcp_stream_get_type (), - "CamelTcpStreamRaw", - sizeof (CamelTcpStreamRaw), - sizeof (CamelTcpStreamRawClass), - (CamelObjectClassInitFunc) camel_tcp_stream_raw_class_init, - NULL, - (CamelObjectInitFunc) camel_tcp_stream_raw_init, - (CamelObjectFinalizeFunc) camel_tcp_stream_raw_finalize); - } - - return type; -} - -#ifdef SIMULATE_FLAKY_NETWORK -static ssize_t -flaky_tcp_write (int fd, const char *buffer, size_t buflen) -{ - size_t len = buflen; - ssize_t nwritten; - int val; - - if (buflen == 0) - return 0; - - val = 1 + (int) (10.0 * rand () / (RAND_MAX + 1.0)); - - switch (val) { - case 1: - printf ("flaky_tcp_write (%d, ..., %d): (-1) EINTR\n", fd, buflen); - errno = EINTR; - return -1; - case 2: - printf ("flaky_tcp_write (%d, ..., %d): (-1) EAGAIN\n", fd, buflen); - errno = EAGAIN; - return -1; - case 3: - printf ("flaky_tcp_write (%d, ..., %d): (-1) EWOULDBLOCK\n", fd, buflen); - errno = EWOULDBLOCK; - return -1; - case 4: - case 5: - case 6: - len = 1 + (size_t) (buflen * rand () / (RAND_MAX + 1.0)); - len = MIN (len, buflen); - /* fall through... */ - default: - printf ("flaky_tcp_write (%d, ..., %d): (%d) '%.*s'", fd, buflen, len, (int) len, buffer); - nwritten = write (fd, buffer, len); - if (nwritten < 0) - printf (" errno => %s\n", strerror (errno)); - else if (nwritten < len) - printf (" only wrote %d bytes\n", nwritten); - else - printf ("\n"); - - return nwritten; - } -} - -#define write(fd, buffer, buflen) flaky_tcp_write (fd, buffer, buflen) - -static ssize_t -flaky_tcp_read (int fd, char *buffer, size_t buflen) -{ - size_t len = buflen; - ssize_t nread; - int val; - - if (buflen == 0) - return 0; - - val = 1 + (int) (10.0 * rand () / (RAND_MAX + 1.0)); - - switch (val) { - case 1: - printf ("flaky_tcp_read (%d, ..., %d): (-1) EINTR\n", fd, buflen); - errno = EINTR; - return -1; - case 2: - printf ("flaky_tcp_read (%d, ..., %d): (-1) EAGAIN\n", fd, buflen); - errno = EAGAIN; - return -1; - case 3: - printf ("flaky_tcp_read (%d, ..., %d): (-1) EWOULDBLOCK\n", fd, buflen); - errno = EWOULDBLOCK; - return -1; - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - len = 1 + (size_t) (10.0 * rand () / (RAND_MAX + 1.0)); - len = MIN (len, buflen); - /* fall through... */ - default: - printf ("flaky_tcp_read (%d, ..., %d): (%d)", fd, buflen, len); - nread = read (fd, buffer, len); - if (nread < 0) - printf (" errno => %s\n", strerror (errno)); - else if (nread < len) - printf (" only read %d bytes\n", nread); - else - printf ("\n"); - - return nread; - } -} - -#define read(fd, buffer, buflen) flaky_tcp_read (fd, buffer, buflen) - -#endif /* SIMULATE_FLAKY_NETWORK */ - - - -/** - * camel_tcp_stream_raw_new: - * - * Return value: a tcp stream - **/ -CamelStream * -camel_tcp_stream_raw_new () -{ - CamelTcpStreamRaw *stream; - - stream = CAMEL_TCP_STREAM_RAW (camel_object_new (camel_tcp_stream_raw_get_type ())); - - return CAMEL_STREAM (stream); -} - -static ssize_t -stream_read (CamelStream *stream, char *buffer, size_t n) -{ - CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream); - - return camel_read (raw->sockfd, buffer, n); -} - -static ssize_t -stream_write (CamelStream *stream, const char *buffer, size_t n) -{ - CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream); - - return camel_write (raw->sockfd, buffer, n); -} - -static int -stream_flush (CamelStream *stream) -{ - return 0; -} - -static int -stream_close (CamelStream *stream) -{ - if (close (((CamelTcpStreamRaw *)stream)->sockfd) == -1) - return -1; - - ((CamelTcpStreamRaw *)stream)->sockfd = -1; - return 0; -} - -/* this is a 'cancellable' connect, cancellable from camel_operation_cancel etc */ -/* returns -1 & errno == EINTR if the connection was cancelled */ -static int -socket_connect (struct hostent *h, int port) -{ -#ifdef ENABLE_IPv6 - struct sockaddr_in6 sin6; -#endif - struct sockaddr_in sin; - struct sockaddr *saddr; - struct timeval tv; - socklen_t len; - int cancel_fd; - int ret, fd; - - /* see if we're cancelled yet */ - if (camel_operation_cancel_check (NULL)) { - errno = EINTR; - return -1; - } - - /* setup connect, we do it using a nonblocking socket so we can poll it */ -#ifdef ENABLE_IPv6 - if (h->h_addrtype == AF_INET6) { - sin6.sin6_port = htons (port); - sin6.sin6_family = h->h_addrtype; - memcpy (&sin6.sin6_addr, h->h_addr, sizeof (sin6.sin6_addr)); - saddr = (struct sockaddr *) &sin6; - len = sizeof (sin6); - } else { -#endif - sin.sin_port = htons (port); - sin.sin_family = h->h_addrtype; - memcpy (&sin.sin_addr, h->h_addr, sizeof (sin.sin_addr)); - saddr = (struct sockaddr *) &sin; - len = sizeof (sin); -#ifdef ENABLE_IPv6 - } -#endif - - fd = socket (h->h_addrtype, SOCK_STREAM, 0); - - cancel_fd = camel_operation_cancel_fd (NULL); - if (cancel_fd == -1) { - ret = connect (fd, saddr, len); - if (ret == -1) { - close (fd); - return -1; - } - - return fd; - } else { - int flags, fdmax, status; - fd_set rdset, wrset; - - flags = fcntl (fd, F_GETFL); - fcntl (fd, F_SETFL, flags | O_NONBLOCK); - - ret = connect (fd, saddr, len); - if (ret == 0) { - fcntl (fd, F_SETFL, flags); - return fd; - } - - if (errno != EINPROGRESS) { - close (fd); - return -1; - } - - do { - FD_ZERO (&rdset); - FD_ZERO (&wrset); - FD_SET (fd, &wrset); - FD_SET (cancel_fd, &rdset); - fdmax = MAX (fd, cancel_fd) + 1; - tv.tv_sec = 60 * 4; - tv.tv_usec = 0; - - status = select (fdmax, &rdset, &wrset, 0, &tv); - } while (status == -1 && errno == EINTR); - - if (status <= 0) { - close (fd); - errno = ETIMEDOUT; - return -1; - } - - if (cancel_fd != -1 && FD_ISSET (cancel_fd, &rdset)) { - close (fd); - errno = EINTR; - return -1; - } else { - len = sizeof (int); - - if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &len) == -1) { - close (fd); - return -1; - } - - if (ret != 0) { - close (fd); - errno = ret; - return -1; - } - } - - fcntl (fd, F_SETFL, flags); - } - - return fd; -} - -static int -stream_connect (CamelTcpStream *stream, struct hostent *host, int port) -{ - CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream); - int fd; - - g_return_val_if_fail (host != NULL, -1); - - fd = socket_connect (host, port); - if (fd == -1) - return -1; - - raw->sockfd = fd; - - return 0; -} - - -static int -get_sockopt_level (const CamelSockOptData *data) -{ - switch (data->option) { - case CAMEL_SOCKOPT_MAXSEGMENT: - case CAMEL_SOCKOPT_NODELAY: - return IPPROTO_TCP; - default: - return SOL_SOCKET; - } -} - -static int -get_sockopt_optname (const CamelSockOptData *data) -{ - switch (data->option) { - case CAMEL_SOCKOPT_MAXSEGMENT: - return TCP_MAXSEG; - case CAMEL_SOCKOPT_NODELAY: - return TCP_NODELAY; - case CAMEL_SOCKOPT_BROADCAST: - return SO_BROADCAST; - case CAMEL_SOCKOPT_KEEPALIVE: - return SO_KEEPALIVE; - case CAMEL_SOCKOPT_LINGER: - return SO_LINGER; - case CAMEL_SOCKOPT_RECVBUFFERSIZE: - return SO_RCVBUF; - case CAMEL_SOCKOPT_SENDBUFFERSIZE: - return SO_SNDBUF; - case CAMEL_SOCKOPT_REUSEADDR: - return SO_REUSEADDR; - case CAMEL_SOCKOPT_IPTYPEOFSERVICE: - return SO_TYPE; - default: - return -1; - } -} - -static int -stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data) -{ - int optname, optlen; - - if ((optname = get_sockopt_optname (data)) == -1) - return -1; - - if (data->option == CAMEL_SOCKOPT_NONBLOCKING) { - int flags; - - flags = fcntl (((CamelTcpStreamRaw *)stream)->sockfd, F_GETFL); - if (flags == -1) - return -1; - - data->value.non_blocking = flags & O_NONBLOCK ? TRUE : FALSE; - - return 0; - } - - return getsockopt (((CamelTcpStreamRaw *)stream)->sockfd, - get_sockopt_level (data), - optname, - (void *) &data->value, - &optlen); -} - -static int -stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data) -{ - int optname; - - if ((optname = get_sockopt_optname (data)) == -1) - return -1; - - if (data->option == CAMEL_SOCKOPT_NONBLOCKING) { - int flags, set; - - flags = fcntl (((CamelTcpStreamRaw *)stream)->sockfd, F_GETFL); - if (flags == -1) - return -1; - - set = data->value.non_blocking ? O_NONBLOCK : 0; - flags = (flags & ~O_NONBLOCK) | set; - - if (fcntl (((CamelTcpStreamRaw *)stream)->sockfd, F_SETFL, flags) == -1) - return -1; - - return 0; - } - - return setsockopt (((CamelTcpStreamRaw *)stream)->sockfd, - get_sockopt_level (data), - optname, - (void *) &data->value, - sizeof (data->value)); -} - -#ifdef ENABLE_IPv6 -#define MIN_SOCKADDR_BUFLEN (sizeof (struct sockaddr_in6)) -#else -#define MIN_SOCKADDR_BUFLEN (sizeof (struct sockaddr_in)) -#endif - -static CamelTcpAddress * -stream_get_local_address (CamelTcpStream *stream) -{ - unsigned char buf[MIN_SOCKADDR_BUFLEN]; -#ifdef ENABLE_IPv6 - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) buf; -#endif - struct sockaddr_in *sin = (struct sockaddr_in *) buf; - struct sockaddr *saddr = (struct sockaddr *) buf; - gpointer address; - socklen_t len; - int family; - - len = MIN_SOCKADDR_BUFLEN; - - if (getsockname (CAMEL_TCP_STREAM_RAW (stream)->sockfd, saddr, &len) == -1) - return NULL; - - if (saddr->sa_family == AF_INET) { - family = CAMEL_TCP_ADDRESS_IPv4; - address = &sin->sin_addr; -#ifdef ENABLE_IPv6 - } else if (saddr->sa_family == AF_INET6) { - family = CAMEL_TCP_ADDRESS_IPv6; - address = &sin6->sin6_addr; -#endif - } else - return NULL; - - return camel_tcp_address_new (family, sin->sin_port, len, address); -} - -static CamelTcpAddress * -stream_get_remote_address (CamelTcpStream *stream) -{ - unsigned char buf[MIN_SOCKADDR_BUFLEN]; -#ifdef ENABLE_IPv6 - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) buf; -#endif - struct sockaddr_in *sin = (struct sockaddr_in *) buf; - struct sockaddr *saddr = (struct sockaddr *) buf; - gpointer address; - socklen_t len; - int family; - - len = MIN_SOCKADDR_BUFLEN; - - if (getpeername (CAMEL_TCP_STREAM_RAW (stream)->sockfd, saddr, &len) == -1) - return NULL; - - if (saddr->sa_family == AF_INET) { - family = CAMEL_TCP_ADDRESS_IPv4; - address = &sin->sin_addr; -#ifdef ENABLE_IPv6 - } else if (saddr->sa_family == AF_INET6) { - family = CAMEL_TCP_ADDRESS_IPv6; - address = &sin6->sin6_addr; -#endif - } else - return NULL; - - return camel_tcp_address_new (family, sin->sin_port, len, address); -} diff --git a/camel/camel-tcp-stream-raw.h b/camel/camel-tcp-stream-raw.h deleted file mode 100644 index 0ffec5cd5c..0000000000 --- a/camel/camel-tcp-stream-raw.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - - -#ifndef CAMEL_TCP_STREAM_RAW_H -#define CAMEL_TCP_STREAM_RAW_H - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#define CAMEL_TCP_STREAM_RAW_TYPE (camel_tcp_stream_raw_get_type ()) -#define CAMEL_TCP_STREAM_RAW(obj) (CAMEL_CHECK_CAST((obj), CAMEL_TCP_STREAM_RAW_TYPE, CamelTcpStreamRaw)) -#define CAMEL_TCP_STREAM_RAW_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_TCP_STREAM_RAW_TYPE, CamelTcpStreamRawClass)) -#define CAMEL_IS_TCP_STREAM_RAW(o) (CAMEL_CHECK_TYPE((o), CAMEL_TCP_STREAM_RAW_TYPE)) - -struct _CamelTcpStreamRaw -{ - CamelTcpStream parent_object; - - int sockfd; -}; - -typedef struct { - CamelTcpStreamClass parent_class; - - /* virtual functions */ - -} CamelTcpStreamRawClass; - -/* Standard Camel function */ -CamelType camel_tcp_stream_raw_get_type (void); - -/* public methods */ -CamelStream *camel_tcp_stream_raw_new (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_TCP_STREAM_RAW_H */ diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c deleted file mode 100644 index 1c8f1b34de..0000000000 --- a/camel/camel-tcp-stream-ssl.c +++ /dev/null @@ -1,1211 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -/* NOTE: This is the default implementation of CamelTcpStreamSSL, - * used when the Mozilla NSS libraries are used. If you configured - * OpenSSL support instead, then this file won't be compiled and - * the CamelTcpStreamSSL implementation in camel-tcp-stream-openssl.c - * will be used instead. - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_NSS -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include "nss.h" /* Don't use <> here or it will include the system nss.h instead */ -#include -#include -#include -#include - -/* this is commented because otherwise we get an error about the - redefinition of MD5Context...yay */ -/*#include */ - -#include "camel-tcp-stream-ssl.h" -#include "camel-stream-fs.h" -#include "camel-session.h" -#include "camel-certdb.h" -#include "camel-operation.h" - -/* from md5-utils.h */ -void md5_get_digest (const char *buffer, int buffer_size, unsigned char digest[16]); - - -static CamelTcpStreamClass *parent_class = NULL; - -/* Returns the class for a CamelTcpStreamSSL */ -#define CTSS_CLASS(so) CAMEL_TCP_STREAM_SSL_CLASS (CAMEL_OBJECT_GET_CLASS (so)) - -static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n); -static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n); -static int stream_flush (CamelStream *stream); -static int stream_close (CamelStream *stream); - -static PRFileDesc *enable_ssl (CamelTcpStreamSSL *ssl, PRFileDesc *fd); - -static int stream_connect (CamelTcpStream *stream, struct hostent *host, int port); -static int stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data); -static int stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data); -static CamelTcpAddress *stream_get_local_address (CamelTcpStream *stream); -static CamelTcpAddress *stream_get_remote_address (CamelTcpStream *stream); - -struct _CamelTcpStreamSSLPrivate { - PRFileDesc *sockfd; - - struct _CamelSession *session; - char *expected_host; - gboolean ssl_mode; - guint32 flags; -}; - -static void -camel_tcp_stream_ssl_class_init (CamelTcpStreamSSLClass *camel_tcp_stream_ssl_class) -{ - CamelTcpStreamClass *camel_tcp_stream_class = - CAMEL_TCP_STREAM_CLASS (camel_tcp_stream_ssl_class); - CamelStreamClass *camel_stream_class = - CAMEL_STREAM_CLASS (camel_tcp_stream_ssl_class); - - parent_class = CAMEL_TCP_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ())); - - /* virtual method overload */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->flush = stream_flush; - camel_stream_class->close = stream_close; - - camel_tcp_stream_class->connect = stream_connect; - camel_tcp_stream_class->getsockopt = stream_getsockopt; - camel_tcp_stream_class->setsockopt = stream_setsockopt; - camel_tcp_stream_class->get_local_address = stream_get_local_address; - camel_tcp_stream_class->get_remote_address = stream_get_remote_address; -} - -static void -camel_tcp_stream_ssl_init (gpointer object, gpointer klass) -{ - CamelTcpStreamSSL *stream = CAMEL_TCP_STREAM_SSL (object); - - stream->priv = g_new0 (struct _CamelTcpStreamSSLPrivate, 1); -} - -static void -camel_tcp_stream_ssl_finalize (CamelObject *object) -{ - CamelTcpStreamSSL *stream = CAMEL_TCP_STREAM_SSL (object); - - if (stream->priv->sockfd != NULL) - PR_Close (stream->priv->sockfd); - - if (stream->priv->session) - camel_object_unref(stream->priv->session); - - g_free (stream->priv->expected_host); - - g_free (stream->priv); -} - - -CamelType -camel_tcp_stream_ssl_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_tcp_stream_get_type (), - "CamelTcpStreamSSL", - sizeof (CamelTcpStreamSSL), - sizeof (CamelTcpStreamSSLClass), - (CamelObjectClassInitFunc) camel_tcp_stream_ssl_class_init, - NULL, - (CamelObjectInitFunc) camel_tcp_stream_ssl_init, - (CamelObjectFinalizeFunc) camel_tcp_stream_ssl_finalize); - } - - return type; -} - - -/** - * camel_tcp_stream_ssl_new: - * @session: active session - * @expected_host: host that the stream is expected to connect with. - * @flags: ENABLE_SSL2, ENABLE_SSL3 and/or ENABLE_TLS - * - * Since the SSL certificate authenticator may need to prompt the - * user, a CamelSession is needed. @expected_host is needed as a - * protection against an MITM attack. - * - * Return value: a ssl stream (in ssl mode) - **/ -CamelStream * -camel_tcp_stream_ssl_new (CamelSession *session, const char *expected_host, guint32 flags) -{ - CamelTcpStreamSSL *stream; - - g_assert(CAMEL_IS_SESSION(session)); - - stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ())); - - stream->priv->session = session; - camel_object_ref(session); - stream->priv->expected_host = g_strdup (expected_host); - stream->priv->ssl_mode = TRUE; - stream->priv->flags = flags; - - return CAMEL_STREAM (stream); -} - - -/** - * camel_tcp_stream_ssl_new_raw: - * @session: active session - * @expected_host: host that the stream is expected to connect with. - * @flags: ENABLE_SSL2, ENABLE_SSL3 and/or ENABLE_TLS - * - * Since the SSL certificate authenticator may need to prompt the - * user, a CamelSession is needed. @expected_host is needed as a - * protection against an MITM attack. - * - * Return value: a ssl-capable stream (in non ssl mode) - **/ -CamelStream * -camel_tcp_stream_ssl_new_raw (CamelSession *session, const char *expected_host, guint32 flags) -{ - CamelTcpStreamSSL *stream; - - g_assert(CAMEL_IS_SESSION(session)); - - stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ())); - - stream->priv->session = session; - camel_object_ref(session); - stream->priv->expected_host = g_strdup (expected_host); - stream->priv->ssl_mode = FALSE; - stream->priv->flags = flags; - - return CAMEL_STREAM (stream); -} - - -static void -set_errno (int code) -{ - /* FIXME: this should handle more. */ - switch (code) { - case PR_INVALID_ARGUMENT_ERROR: - errno = EINVAL; - break; - case PR_PENDING_INTERRUPT_ERROR: - errno = EINTR; - break; - case PR_IO_PENDING_ERROR: - errno = EAGAIN; - break; - case PR_WOULD_BLOCK_ERROR: - errno = EWOULDBLOCK; - break; - case PR_IN_PROGRESS_ERROR: - errno = EINPROGRESS; - break; - case PR_ALREADY_INITIATED_ERROR: - errno = EALREADY; - break; - case PR_NETWORK_UNREACHABLE_ERROR: - errno = EHOSTUNREACH; - break; - case PR_CONNECT_REFUSED_ERROR: - errno = ECONNREFUSED; - break; - case PR_CONNECT_TIMEOUT_ERROR: - case PR_IO_TIMEOUT_ERROR: - errno = ETIMEDOUT; - break; - case PR_NOT_CONNECTED_ERROR: - errno = ENOTCONN; - break; - case PR_CONNECT_RESET_ERROR: - errno = ECONNRESET; - break; - case PR_IO_ERROR: - default: - errno = EIO; - break; - } -} - - -/** - * camel_tcp_stream_ssl_enable_ssl: - * @ssl: ssl stream - * - * Toggles an ssl-capable stream into ssl mode (if it isn't already). - * - * Returns 0 on success or -1 on fail. - **/ -int -camel_tcp_stream_ssl_enable_ssl (CamelTcpStreamSSL *ssl) -{ - PRFileDesc *fd; - - g_return_val_if_fail (CAMEL_IS_TCP_STREAM_SSL (ssl), -1); - - if (ssl->priv->sockfd && !ssl->priv->ssl_mode) { - if (!(fd = enable_ssl (ssl, NULL))) { - set_errno (PR_GetError ()); - return -1; - } - - ssl->priv->sockfd = fd; - - if (SSL_ResetHandshake (fd, FALSE) == SECFailure) { - set_errno (PR_GetError ()); - return -1; - } - - if (SSL_ForceHandshake (fd) == -1) { - set_errno (PR_GetError ()); - return -1; - } - } - - ssl->priv->ssl_mode = TRUE; - - return 0; -} - - -static ssize_t -stream_read (CamelStream *stream, char *buffer, size_t n) -{ - CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream); - PRFileDesc *cancel_fd; - ssize_t nread; - - if (camel_operation_cancel_check (NULL)) { - errno = EINTR; - return -1; - } - - cancel_fd = camel_operation_cancel_prfd (NULL); - if (cancel_fd == NULL) { - do { - nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); - if (nread == -1) - set_errno (PR_GetError ()); - } while (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); - } else { - PRSocketOptionData sockopts; - PRPollDesc pollfds[2]; - gboolean nonblock; - int error; - - /* get O_NONBLOCK options */ - sockopts.option = PR_SockOpt_Nonblocking; - PR_GetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); - sockopts.option = PR_SockOpt_Nonblocking; - nonblock = sockopts.value.non_blocking; - sockopts.value.non_blocking = TRUE; - PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); - - pollfds[0].fd = tcp_stream_ssl->priv->sockfd; - pollfds[0].in_flags = PR_POLL_READ; - pollfds[1].fd = cancel_fd; - pollfds[1].in_flags = PR_POLL_READ; - - do { - pollfds[0].out_flags = 0; - pollfds[1].out_flags = 0; - - nread = -1; - if (PR_Poll (pollfds, 2, -1) != -1) { - if (pollfds[1].out_flags == PR_POLL_READ) { - sockopts.option = PR_SockOpt_Nonblocking; - sockopts.value.non_blocking = nonblock; - PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); - errno = EINTR; - return -1; - } - - do { - nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); - if (nread == -1) - set_errno (PR_GetError ()); - } while (nread == -1 && errno == EINTR); - } else { - errno = EAGAIN; - } - } while (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); - - /* restore O_NONBLOCK options */ - error = errno; - sockopts.option = PR_SockOpt_Nonblocking; - sockopts.value.non_blocking = nonblock; - PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); - errno = error; - } - - return nread; -} - -static ssize_t -stream_write (CamelStream *stream, const char *buffer, size_t n) -{ - CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream); - ssize_t w, written = 0; - PRFileDesc *cancel_fd; - - if (camel_operation_cancel_check (NULL)) { - errno = EINTR; - return -1; - } - - cancel_fd = camel_operation_cancel_prfd (NULL); - if (cancel_fd == NULL) { - do { - do { - w = PR_Write (tcp_stream_ssl->priv->sockfd, buffer + written, n - written); - if (w == -1) - set_errno (PR_GetError ()); - } while (w == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); - - if (w > 0) - written += w; - } while (w != -1 && written < n); - } else { - PRSocketOptionData sockopts; - PRPollDesc pollfds[2]; - gboolean nonblock; - int error; - - /* get O_NONBLOCK options */ - sockopts.option = PR_SockOpt_Nonblocking; - PR_GetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); - sockopts.option = PR_SockOpt_Nonblocking; - nonblock = sockopts.value.non_blocking; - sockopts.value.non_blocking = TRUE; - PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); - - pollfds[0].fd = tcp_stream_ssl->priv->sockfd; - pollfds[0].in_flags = PR_POLL_WRITE; - pollfds[1].fd = cancel_fd; - pollfds[1].in_flags = PR_POLL_READ; - - do { - pollfds[0].out_flags = 0; - pollfds[1].out_flags = 0; - - w = -1; - if (PR_Poll (pollfds, 2, -1) != -1) { - if (pollfds[1].out_flags == PR_POLL_READ) { - sockopts.option = PR_SockOpt_Nonblocking; - sockopts.value.non_blocking = nonblock; - PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); - errno = EINTR; - return -1; - } - - do { - w = PR_Write (tcp_stream_ssl->priv->sockfd, buffer + written, n - written); - if (w == -1) - set_errno (PR_GetError ()); - } while (w == -1 && errno == EINTR); - - if (w == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - w = 0; - } else { - error = errno; - sockopts.option = PR_SockOpt_Nonblocking; - sockopts.value.non_blocking = nonblock; - PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); - errno = error; - return -1; - } - } else - written += w; - } else { - set_errno (PR_GetError ()); - if (errno == EINTR) - w = 0; - } - } while (w != -1 && written < n); - - /* restore O_NONBLOCK options */ - error = errno; - sockopts.option = PR_SockOpt_Nonblocking; - sockopts.value.non_blocking = nonblock; - PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); - errno = error; - } - - if (w == -1) - return -1; - - return written; -} - -static int -stream_flush (CamelStream *stream) -{ - return PR_Sync (((CamelTcpStreamSSL *)stream)->priv->sockfd); -} - -static int -stream_close (CamelStream *stream) -{ - if (PR_Close (((CamelTcpStreamSSL *)stream)->priv->sockfd) == PR_FAILURE) - return -1; - - ((CamelTcpStreamSSL *)stream)->priv->sockfd = NULL; - - return 0; -} - -#if 0 -/* Since this is default implementation, let NSS handle it. */ -static SECStatus -ssl_get_client_auth (void *data, PRFileDesc *sockfd, - struct CERTDistNamesStr *caNames, - struct CERTCertificateStr **pRetCert, - struct SECKEYPrivateKeyStr **pRetKey) -{ - SECStatus status = SECFailure; - SECKEYPrivateKey *privkey; - CERTCertificate *cert; - void *proto_win; - - proto_win = SSL_RevealPinArg (sockfd); - - if ((char *) data) { - cert = PK11_FindCertFromNickname ((char *) data, proto_win); - if (cert) { - privKey = PK11_FindKeyByAnyCert (cert, proto_win); - if (privkey) { - status = SECSuccess; - } else { - CERT_DestroyCertificate (cert); - } - } - } else { - /* no nickname given, automatically find the right cert */ - CERTCertNicknames *names; - int i; - - names = CERT_GetCertNicknames (CERT_GetDefaultCertDB (), - SEC_CERT_NICKNAMES_USER, - proto_win); - - if (names != NULL) { - for (i = 0; i < names->numnicknames; i++) { - cert = PK11_FindCertFromNickname (names->nicknames[i], - proto_win); - if (!cert) - continue; - - /* Only check unexpired certs */ - if (CERT_CheckCertValidTimes (cert, PR_Now (), PR_FALSE) != secCertTimeValid) { - CERT_DestroyCertificate (cert); - continue; - } - - status = NSS_CmpCertChainWCANames (cert, caNames); - if (status == SECSuccess) { - privkey = PK11_FindKeyByAnyCert (cert, proto_win); - if (privkey) - break; - - status = SECFailure; - break; - } - - CERT_FreeNicknames (names); - } - } - } - - if (status == SECSuccess) { - *pRetCert = cert; - *pRetKey = privkey; - } - - return status; -} -#endif - -#if 0 -/* Since this is the default NSS implementation, no need for us to use this. */ -static SECStatus -ssl_auth_cert (void *data, PRFileDesc *sockfd, PRBool checksig, PRBool is_server) -{ - CERTCertificate *cert; - SECStatus status; - void *pinarg; - char *host; - - cert = SSL_PeerCertificate (sockfd); - pinarg = SSL_RevealPinArg (sockfd); - status = CERT_VerifyCertNow ((CERTCertDBHandle *)data, cert, - checksig, certUsageSSLClient, pinarg); - - if (status != SECSuccess) - return SECFailure; - - /* Certificate is OK. Since this is the client side of an SSL - * connection, we need to verify that the name field in the cert - * matches the desired hostname. This is our defense against - * man-in-the-middle attacks. - */ - - /* SSL_RevealURL returns a hostname, not a URL. */ - host = SSL_RevealURL (sockfd); - - if (host && *host) { - status = CERT_VerifyCertName (cert, host); - } else { - PR_SetError (SSL_ERROR_BAD_CERT_DOMAIN, 0); - status = SECFailure; - } - - if (host) - PR_Free (host); - - return secStatus; -} -#endif - -CamelCert *camel_certdb_nss_cert_get(CamelCertDB *certdb, CERTCertificate *cert); -CamelCert *camel_certdb_nss_cert_add(CamelCertDB *certdb, CERTCertificate *cert); -void camel_certdb_nss_cert_set(CamelCertDB *certdb, CamelCert *ccert, CERTCertificate *cert); - -static char * -cert_fingerprint(CERTCertificate *cert) -{ - unsigned char md5sum[16], fingerprint[50], *f; - int i; - const char tohex[16] = "0123456789abcdef"; - - md5_get_digest (cert->derCert.data, cert->derCert.len, md5sum); - for (i=0,f = fingerprint; i<16; i++) { - unsigned int c = md5sum[i]; - - *f++ = tohex[(c >> 4) & 0xf]; - *f++ = tohex[c & 0xf]; - *f++ = ':'; - } - - fingerprint[47] = 0; - - return g_strdup(fingerprint); -} - -/* lookup a cert uses fingerprint to index an on-disk file */ -CamelCert * -camel_certdb_nss_cert_get(CamelCertDB *certdb, CERTCertificate *cert) -{ - char *fingerprint, *path; - CamelCert *ccert; - struct stat st; - size_t nread; - ssize_t n; - int fd; - - fingerprint = cert_fingerprint (cert); - ccert = camel_certdb_get_cert (certdb, fingerprint); - if (ccert == NULL) { - g_free (fingerprint); - return ccert; - } - - if (ccert->rawcert == NULL) { - path = g_strdup_printf ("%s/.camel_certs/%s", getenv ("HOME"), fingerprint); - if (stat (path, &st) == -1 - || (fd = open (path, O_RDONLY)) == -1) { - g_warning ("could not load cert %s: %s", path, strerror (errno)); - g_free (fingerprint); - g_free (path); - camel_cert_set_trust (certdb, ccert, CAMEL_CERT_TRUST_UNKNOWN); - camel_certdb_touch (certdb); - - return ccert; - } - g_free(path); - - ccert->rawcert = g_byte_array_new (); - g_byte_array_set_size (ccert->rawcert, st.st_size); - - nread = 0; - do { - do { - n = read (fd, ccert->rawcert->data + nread, st.st_size - nread); - } while (n == -1 && errno == EINTR); - - if (n > 0) - nread += n; - } while (nread < st.st_size && n != -1); - - close (fd); - - if (nread != st.st_size) { - g_warning ("cert size read truncated %s: %d != %ld", path, nread, st.st_size); - g_byte_array_free(ccert->rawcert, TRUE); - ccert->rawcert = NULL; - g_free(fingerprint); - camel_cert_set_trust(certdb, ccert, CAMEL_CERT_TRUST_UNKNOWN); - camel_certdb_touch(certdb); - - return ccert; - } - } - - g_free(fingerprint); - if (ccert->rawcert->len != cert->derCert.len - || memcmp(ccert->rawcert->data, cert->derCert.data, cert->derCert.len) != 0) { - g_warning("rawcert != derCer"); - camel_cert_set_trust(certdb, ccert, CAMEL_CERT_TRUST_UNKNOWN); - camel_certdb_touch(certdb); - } - - return ccert; -} - -/* add a cert to the certdb */ -CamelCert * -camel_certdb_nss_cert_add(CamelCertDB *certdb, CERTCertificate *cert) -{ - CamelCert *ccert; - char *fingerprint; - - fingerprint = cert_fingerprint(cert); - - ccert = camel_certdb_cert_new(certdb); - camel_cert_set_issuer(certdb, ccert, CERT_NameToAscii(&cert->issuer)); - camel_cert_set_subject(certdb, ccert, CERT_NameToAscii(&cert->subject)); - /* hostname is set in caller */ - /*camel_cert_set_hostname(certdb, ccert, ssl->priv->expected_host);*/ - camel_cert_set_fingerprint(certdb, ccert, fingerprint); - camel_cert_set_trust(certdb, ccert, CAMEL_CERT_TRUST_UNKNOWN); - g_free(fingerprint); - - camel_certdb_nss_cert_set(certdb, ccert, cert); - - camel_certdb_add(certdb, ccert); - - return ccert; -} - -/* set the 'raw' cert (& save it) */ -void -camel_certdb_nss_cert_set(CamelCertDB *certdb, CamelCert *ccert, CERTCertificate *cert) -{ - char *dir, *path, *fingerprint; - CamelStream *stream; - struct stat st; - - fingerprint = ccert->fingerprint; - - if (ccert->rawcert == NULL) - ccert->rawcert = g_byte_array_new (); - - g_byte_array_set_size (ccert->rawcert, cert->derCert.len); - memcpy (ccert->rawcert->data, cert->derCert.data, cert->derCert.len); - - dir = g_strdup_printf ("%s/.camel_certs", getenv ("HOME")); - if (stat (dir, &st) == -1 && mkdir (dir, 0700) == -1) { - g_warning ("Could not create cert directory '%s': %s", dir, strerror (errno)); - g_free (dir); - return; - } - - path = g_strdup_printf ("%s/%s", dir, fingerprint); - g_free (dir); - - stream = camel_stream_fs_new_with_name (path, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (stream != NULL) { - if (camel_stream_write (stream, ccert->rawcert->data, ccert->rawcert->len) == -1) { - g_warning ("Could not save cert: %s: %s", path, strerror (errno)); - unlink (path); - } - camel_stream_close (stream); - camel_object_unref (stream); - } else { - g_warning ("Could not save cert: %s: %s", path, strerror (errno)); - } - - g_free (path); -} - - -#if 0 -/* used by the mozilla-like code below */ -static char * -get_nickname(CERTCertificate *cert) -{ - char *server, *nick = NULL; - int i; - PRBool status = PR_TRUE; - - server = CERT_GetCommonName(&cert->subject); - if (server == NULL) - return NULL; - - for (i=1;status == PR_TRUE;i++) { - if (nick) { - g_free(nick); - nick = g_strdup_printf("%s #%d", server, i); - } else { - nick = g_strdup(server); - } - status = SEC_CertNicknameConflict(server, &cert->derSubject, cert->dbhandle); - } - - return nick; -} -#endif - -static SECStatus -ssl_bad_cert (void *data, PRFileDesc *sockfd) -{ - gboolean accept; - CamelCertDB *certdb = NULL; - CamelCert *ccert = NULL; - char *prompt, *cert_str, *fingerprint; - CamelTcpStreamSSL *ssl; - CERTCertificate *cert; - SECStatus status = SECFailure; - - g_return_val_if_fail (data != NULL, SECFailure); - g_return_val_if_fail (CAMEL_IS_TCP_STREAM_SSL (data), SECFailure); - - ssl = data; - - cert = SSL_PeerCertificate (sockfd); - if (cert == NULL) - return SECFailure; - - certdb = camel_certdb_get_default(); - ccert = camel_certdb_nss_cert_get(certdb, cert); - if (ccert == NULL) { - ccert = camel_certdb_nss_cert_add(certdb, cert); - camel_cert_set_hostname(certdb, ccert, ssl->priv->expected_host); - } - - if (ccert->trust == CAMEL_CERT_TRUST_UNKNOWN) { - status = CERT_VerifyCertNow(cert->dbhandle, cert, TRUE, certUsageSSLClient, NULL); - fingerprint = cert_fingerprint(cert); - cert_str = g_strdup_printf (_("Issuer: %s\n" - "Subject: %s\n" - "Fingerprint: %s\n" - "Signature: %s"), - CERT_NameToAscii (&cert->issuer), - CERT_NameToAscii (&cert->subject), - fingerprint, status == SECSuccess?_("GOOD"):_("BAD")); - g_free(fingerprint); - - /* construct our user prompt */ - prompt = g_strdup_printf (_("SSL Certificate check for %s:\n\n%s\n\nDo you wish to accept?"), - ssl->priv->expected_host, cert_str); - g_free (cert_str); - - /* query the user to find out if we want to accept this certificate */ - accept = camel_session_alert_user (ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE); - g_free(prompt); - if (accept) { - camel_certdb_nss_cert_set(certdb, ccert, cert); - camel_cert_set_trust(certdb, ccert, CAMEL_CERT_TRUST_FULLY); - camel_certdb_touch(certdb); - } - } else { - accept = ccert->trust != CAMEL_CERT_TRUST_NEVER; - } - - camel_certdb_cert_unref(certdb, ccert); - camel_object_unref(certdb); - - return accept ? SECSuccess : SECFailure; - -#if 0 - int i, error; - CERTCertTrust trust; - SECItem *certs[1]; - int go = 1; - char *host, *nick; - - error = PR_GetError(); - - /* This code is basically what mozilla does - however it doesn't seem to work here - very reliably :-/ */ - while (go && status != SECSuccess) { - char *prompt = NULL; - - printf("looping, error '%d'\n", error); - - switch(error) { - case SEC_ERROR_UNKNOWN_ISSUER: - case SEC_ERROR_CA_CERT_INVALID: - case SEC_ERROR_UNTRUSTED_ISSUER: - case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: - /* add certificate */ - printf("unknown issuer, adding ... \n"); - prompt = g_strdup_printf(_("Certificate problem: %s\nIssuer: %s"), cert->subjectName, cert->issuerName); - - if (camel_session_alert_user(ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE)) { - - nick = get_nickname(cert); - if (NULL == nick) { - g_free(prompt); - status = SECFailure; - break; - } - - printf("adding cert '%s'\n", nick); - - if (!cert->trust) { - cert->trust = (CERTCertTrust*)PORT_ArenaZAlloc(cert->arena, sizeof(CERTCertTrust)); - CERT_DecodeTrustString(cert->trust, "P"); - } - - certs[0] = &cert->derCert; - /*CERT_ImportCerts (cert->dbhandle, certUsageSSLServer, 1, certs, NULL, TRUE, FALSE, nick);*/ - CERT_ImportCerts(cert->dbhandle, certUsageUserCertImport, 1, certs, NULL, TRUE, FALSE, nick); - g_free(nick); - - printf(" cert type %08x\n", cert->nsCertType); - - memset((void*)&trust, 0, sizeof(trust)); - if (CERT_GetCertTrust(cert, &trust) != SECSuccess) { - CERT_DecodeTrustString(&trust, "P"); - } - trust.sslFlags |= CERTDB_VALID_PEER | CERTDB_TRUSTED; - if (CERT_ChangeCertTrust(cert->dbhandle, cert, &trust) != SECSuccess) { - printf("couldn't change cert trust?\n"); - } - - /*status = SECSuccess;*/ -#if 1 - /* re-verify? */ - status = CERT_VerifyCertNow(cert->dbhandle, cert, TRUE, certUsageSSLServer, NULL); - error = PR_GetError(); - printf("re-verify status %d, error %d\n", status, error); -#endif - - printf(" cert type %08x\n", cert->nsCertType); - } else { - printf("failed/cancelled\n"); - go = 0; - } - - break; - case SSL_ERROR_BAD_CERT_DOMAIN: - printf("bad domain\n"); - - prompt = g_strdup_printf(_("Bad certificate domain: %s\nIssuer: %s"), cert->subjectName, cert->issuerName); - - if (camel_session_alert_user (ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE)) { - host = SSL_RevealURL(sockfd); - status = CERT_AddOKDomainName(cert, host); - printf("add ok domain name : %s\n", status == SECFailure?"fail":"ok"); - error = PR_GetError(); - if (status == SECFailure) - go = 0; - } else { - go = 0; - } - - break; - - case SEC_ERROR_EXPIRED_CERTIFICATE: - printf("expired\n"); - - prompt = g_strdup_printf(_("Certificate expired: %s\nIssuer: %s"), cert->subjectName, cert->issuerName); - - if (camel_session_alert_user(ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE)) { - cert->timeOK = PR_TRUE; - status = CERT_VerifyCertNow(cert->dbhandle, cert, TRUE, certUsageSSLClient, NULL); - error = PR_GetError(); - if (status == SECFailure) - go = 0; - } else { - go = 0; - } - - break; - - case SEC_ERROR_CRL_EXPIRED: - printf("crl expired\n"); - - prompt = g_strdup_printf(_("Certificate revocation list expired: %s\nIssuer: %s"), cert->subjectName, cert->issuerName); - - if (camel_session_alert_user(ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE)) { - host = SSL_RevealURL(sockfd); - status = CERT_AddOKDomainName(cert, host); - } - - go = 0; - break; - - default: - printf("generic error\n"); - go = 0; - break; - } - - g_free(prompt); - } - - CERT_DestroyCertificate(cert); - - return status; -#endif -} - -static PRFileDesc * -enable_ssl (CamelTcpStreamSSL *ssl, PRFileDesc *fd) -{ - PRFileDesc *ssl_fd; - - ssl_fd = SSL_ImportFD (NULL, fd ? fd : ssl->priv->sockfd); - if (!ssl_fd) - return NULL; - - SSL_OptionSet (ssl_fd, SSL_SECURITY, PR_TRUE); - if (ssl->priv->flags & CAMEL_TCP_STREAM_SSL_ENABLE_SSL2) - SSL_OptionSet (ssl_fd, SSL_ENABLE_SSL2, PR_TRUE); - else - SSL_OptionSet (ssl_fd, SSL_ENABLE_SSL2, PR_FALSE); - if (ssl->priv->flags & CAMEL_TCP_STREAM_SSL_ENABLE_SSL3) - SSL_OptionSet (ssl_fd, SSL_ENABLE_SSL3, PR_TRUE); - else - SSL_OptionSet (ssl_fd, SSL_ENABLE_SSL3, PR_FALSE); - if (ssl->priv->flags & CAMEL_TCP_STREAM_SSL_ENABLE_TLS) - SSL_OptionSet (ssl_fd, SSL_ENABLE_TLS, PR_TRUE); - else - SSL_OptionSet (ssl_fd, SSL_ENABLE_TLS, PR_FALSE); - - SSL_SetURL (ssl_fd, ssl->priv->expected_host); - - /*SSL_GetClientAuthDataHook (sslSocket, ssl_get_client_auth, (void *) certNickname);*/ - /*SSL_AuthCertificateHook (ssl_fd, ssl_auth_cert, (void *) CERT_GetDefaultCertDB ());*/ - SSL_BadCertHook (ssl_fd, ssl_bad_cert, ssl); - - ssl->priv->ssl_mode = TRUE; - - return ssl_fd; -} - -#define CONNECT_TIMEOUT PR_TicksPerSecond () * 120 - -static int -stream_connect (CamelTcpStream *stream, struct hostent *host, int port) -{ - CamelTcpStreamSSL *ssl = CAMEL_TCP_STREAM_SSL (stream); - PRIntervalTime timeout = CONNECT_TIMEOUT; - PRNetAddr netaddr; - PRFileDesc *fd; - - g_return_val_if_fail (host != NULL, -1); - - memset ((void *) &netaddr, 0, sizeof (PRNetAddr)); -#ifdef ENABLE_IPv6 - if (host->h_addrtype == AF_INET6) - memcpy (&netaddr.ipv6.ip, host->h_addr, sizeof (netaddr.ipv6.ip)); - else - memcpy (&netaddr.inet.ip, host->h_addr, sizeof (netaddr.inet.ip)); -#else - memcpy (&netaddr.inet.ip, host->h_addr, sizeof (netaddr.inet.ip)); -#endif - - if (PR_InitializeNetAddr (PR_IpAddrNull, port, &netaddr) == PR_FAILURE) { - set_errno (PR_GetError ()); - return -1; - } - - fd = PR_OpenTCPSocket (host->h_addrtype); - if (fd == NULL) { - set_errno (PR_GetError ()); - return -1; - } - - if (ssl->priv->ssl_mode) { - PRFileDesc *ssl_fd; - - ssl_fd = enable_ssl (ssl, fd); - if (ssl_fd == NULL) { - int errnosave; - - set_errno (PR_GetError ()); - errnosave = errno; - PR_Close (fd); - errno = errnosave; - - return -1; - } - - fd = ssl_fd; - } - - if (PR_Connect (fd, &netaddr, timeout) == PR_FAILURE) { - int errnosave; - - set_errno (PR_GetError ()); - if (errno == EINPROGRESS) { - gboolean connected = FALSE; - PRPollDesc poll; - - do { - poll.fd = fd; - poll.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; - poll.out_flags = 0; - - timeout = CONNECT_TIMEOUT; - - if (PR_Poll (&poll, 1, timeout) == PR_FAILURE) { - set_errno (PR_GetError ()); - goto exception; - } - - if (PR_GetConnectStatus (&poll) == PR_FAILURE) { - set_errno (PR_GetError ()); - if (errno != EINPROGRESS) - goto exception; - } else { - connected = TRUE; - } - } while (!connected); - } else { - exception: - errnosave = errno; - PR_Close (fd); - ssl->priv->sockfd = NULL; - errno = errnosave; - - return -1; - } - - errno = 0; - } - - ssl->priv->sockfd = fd; - - return 0; -} - - -static int -stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data) -{ - PRSocketOptionData sodata; - - memset ((void *) &sodata, 0, sizeof (sodata)); - memcpy ((void *) &sodata, (void *) data, sizeof (CamelSockOptData)); - - if (PR_GetSocketOption (((CamelTcpStreamSSL *)stream)->priv->sockfd, &sodata) == PR_FAILURE) - return -1; - - memcpy ((void *) data, (void *) &sodata, sizeof (CamelSockOptData)); - - return 0; -} - -static int -stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data) -{ - PRSocketOptionData sodata; - - memset ((void *) &sodata, 0, sizeof (sodata)); - memcpy ((void *) &sodata, (void *) data, sizeof (CamelSockOptData)); - - if (PR_SetSocketOption (((CamelTcpStreamSSL *)stream)->priv->sockfd, &sodata) == PR_FAILURE) - return -1; - - return 0; -} - -static CamelTcpAddress * -stream_get_local_address (CamelTcpStream *stream) -{ - PRFileDesc *sockfd = CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd; - int family, length; - gpointer address; - PRNetAddr addr; - - PR_GetSockName (sockfd, &addr); - - if (addr.inet.family == PR_AF_INET) { - family = CAMEL_TCP_ADDRESS_IPv4; - address = &addr.inet.ip; - length = 4; -#ifdef ENABLE_IPv6 - } else if (addr.inet.family == PR_AF_INET6) { - family = CAMEL_TCP_ADDRESS_IPv6; - address = &addr.ipv6.ip; - length = 16; -#endif - } else - return NULL; - - return camel_tcp_address_new (family, addr.inet.port, length, address); -} - -static CamelTcpAddress * -stream_get_remote_address (CamelTcpStream *stream) -{ - PRFileDesc *sockfd = CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd; - int family, length; - gpointer address; - PRNetAddr addr; - - PR_GetPeerName (sockfd, &addr); - - if (addr.inet.family == PR_AF_INET) { - family = CAMEL_TCP_ADDRESS_IPv4; - address = &addr.inet.ip; - length = sizeof (addr.inet.ip); -#ifdef ENABLE_IPv6 - } else if (addr.inet.family == PR_AF_INET6) { - family = CAMEL_TCP_ADDRESS_IPv6; - address = &addr.ipv6.ip; - length = sizeof (addr.ipv6.ip); -#endif - } else - return NULL; - - return camel_tcp_address_new (family, addr.inet.port, length, address); -} - -#endif /* HAVE_NSS */ diff --git a/camel/camel-tcp-stream-ssl.h b/camel/camel-tcp-stream-ssl.h deleted file mode 100644 index d11c2efdcb..0000000000 --- a/camel/camel-tcp-stream-ssl.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - - -#ifndef CAMEL_TCP_STREAM_SSL_H -#define CAMEL_TCP_STREAM_SSL_H - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#define CAMEL_TCP_STREAM_SSL_TYPE (camel_tcp_stream_ssl_get_type ()) -#define CAMEL_TCP_STREAM_SSL(obj) (CAMEL_CHECK_CAST((obj), CAMEL_TCP_STREAM_SSL_TYPE, CamelTcpStreamSSL)) -#define CAMEL_TCP_STREAM_SSL_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_TCP_STREAM_SSL_TYPE, CamelTcpStreamSSLClass)) -#define CAMEL_IS_TCP_STREAM_SSL(o) (CAMEL_CHECK_TYPE((o), CAMEL_TCP_STREAM_SSL_TYPE)) - -struct _CamelSession; - -enum { - CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 = (1 << 0), - CAMEL_TCP_STREAM_SSL_ENABLE_SSL3 = (1 << 1), - CAMEL_TCP_STREAM_SSL_ENABLE_TLS = (1 << 2), -}; - -struct _CamelTcpStreamSSL { - CamelTcpStream parent_object; - - struct _CamelTcpStreamSSLPrivate *priv; -}; - -typedef struct { - CamelTcpStreamClass parent_class; - - /* virtual functions */ - -} CamelTcpStreamSSLClass; - -/* Standard Camel function */ -CamelType camel_tcp_stream_ssl_get_type (void); - -/* public methods */ -CamelStream *camel_tcp_stream_ssl_new (struct _CamelSession *session, const char *expected_host, guint32 flags); - -CamelStream *camel_tcp_stream_ssl_new_raw (struct _CamelSession *session, const char *expected_host, guint32 flags); - -int camel_tcp_stream_ssl_enable_ssl (CamelTcpStreamSSL *ssl); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_TCP_STREAM_SSL_H */ diff --git a/camel/camel-tcp-stream.c b/camel/camel-tcp-stream.c deleted file mode 100644 index fbbcbec451..0000000000 --- a/camel/camel-tcp-stream.c +++ /dev/null @@ -1,249 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "camel-tcp-stream.h" - -#define w(x) - -static CamelStreamClass *parent_class = NULL; - -/* Returns the class for a CamelTcpStream */ -#define CTS_CLASS(so) CAMEL_TCP_STREAM_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static int tcp_connect (CamelTcpStream *stream, struct hostent *host, int port); -static int tcp_getsockopt (CamelTcpStream *stream, CamelSockOptData *data); -static int tcp_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data); -static CamelTcpAddress *tcp_get_local_address (CamelTcpStream *stream); -static CamelTcpAddress *tcp_get_remote_address (CamelTcpStream *stream); - - -static void -camel_tcp_stream_class_init (CamelTcpStreamClass *camel_tcp_stream_class) -{ - /*CamelStreamClass *camel_stream_class = CAMEL_STREAM_CLASS (camel_tcp_stream_class);*/ - - parent_class = CAMEL_STREAM_CLASS (camel_type_get_global_classfuncs (CAMEL_STREAM_TYPE)); - - /* tcp stream methods */ - camel_tcp_stream_class->connect = tcp_connect; - camel_tcp_stream_class->getsockopt = tcp_getsockopt; - camel_tcp_stream_class->setsockopt = tcp_setsockopt; - camel_tcp_stream_class->get_local_address = tcp_get_local_address; - camel_tcp_stream_class->get_remote_address = tcp_get_remote_address; -} - -static void -camel_tcp_stream_init (void *o) -{ - ; -} - -CamelType -camel_tcp_stream_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (CAMEL_STREAM_TYPE, - "CamelTcpStream", - sizeof (CamelTcpStream), - sizeof (CamelTcpStreamClass), - (CamelObjectClassInitFunc) camel_tcp_stream_class_init, - NULL, - (CamelObjectInitFunc) camel_tcp_stream_init, - NULL); - } - - return type; -} - - -static int -tcp_connect (CamelTcpStream *stream, struct hostent *host, int port) -{ - w(g_warning ("CamelTcpStream::connect called on default implementation")); - return -1; -} - -/** - * camel_tcp_stream_connect: - * @stream: a CamelTcpStream object. - * @host: a hostent value - * @port: port - * - * Create a socket and connect based upon the data provided. - * - * Return value: zero on success or -1 on fail. - **/ -int -camel_tcp_stream_connect (CamelTcpStream *stream, struct hostent *host, int port) -{ - g_return_val_if_fail (CAMEL_IS_TCP_STREAM (stream), -1); - - return CTS_CLASS (stream)->connect (stream, host, port); -} - - -static int -tcp_getsockopt (CamelTcpStream *stream, CamelSockOptData *data) -{ - w(g_warning ("CamelTcpStream::getsockopt called on default implementation")); - return -1; -} - - -/** - * camel_tcp_stream_getsockopt: - * @stream: tcp stream object - * @data: socket option data - * - * Get the socket options set on the stream and populate #data. - * - * Return value: zero on success or -1 on fail. - **/ -int -camel_tcp_stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data) -{ - g_return_val_if_fail (CAMEL_IS_TCP_STREAM (stream), -1); - - return CTS_CLASS (stream)->getsockopt (stream, data); -} - - -static int -tcp_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data) -{ - w(g_warning ("CamelTcpStream::setsockopt called on default implementation")); - return -1; -} - - -/** - * camel_tcp_stream_setsockopt: - * @stream: tcp stream object - * @data: socket option data - * - * Set the socket options contained in #data on the stream. - * - * Return value: zero on success or -1 on fail. - **/ -int -camel_tcp_stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data) -{ - g_return_val_if_fail (CAMEL_IS_TCP_STREAM (stream), -1); - - return CTS_CLASS (stream)->setsockopt (stream, data); -} - - -static CamelTcpAddress * -tcp_get_local_address (CamelTcpStream *stream) -{ - w(g_warning ("CamelTcpStream::get_local_address called on default implementation")); - return NULL; -} - -/** - * camel_tcp_stream_get_local_address: - * @stream: tcp stream object - * - * Get the local address of @stream. - * - * Return value: the stream's local address (which must be freed with - * camel_tcp_address_free()) if the stream is connected, or %NULL if not. - **/ -CamelTcpAddress * -camel_tcp_stream_get_local_address (CamelTcpStream *stream) -{ - g_return_val_if_fail (CAMEL_IS_TCP_STREAM (stream), NULL); - - return CTS_CLASS (stream)->get_local_address (stream); -} - - -static CamelTcpAddress * -tcp_get_remote_address (CamelTcpStream *stream) -{ - w(g_warning ("CamelTcpStream::get_remote_address called on default implementation")); - return NULL; -} - -/** - * camel_tcp_stream_get_remote_address: - * @stream: tcp stream object - * - * Get the remote address of @stream. - * - * Return value: the stream's remote address (which must be freed with - * camel_tcp_address_free()) if the stream is connected, or %NULL if not. - **/ -CamelTcpAddress * -camel_tcp_stream_get_remote_address (CamelTcpStream *stream) -{ - g_return_val_if_fail (CAMEL_IS_TCP_STREAM (stream), NULL); - - return CTS_CLASS (stream)->get_remote_address (stream); -} - - -/** - * camel_tcp_address_new: - * @family: the address family - * @port: the port number (in network byte order) - * @length: the length of @address - * @address: the address data (family dependent, in network byte order) - * - * Return value: a new CamelTcpAddress. - **/ -CamelTcpAddress * -camel_tcp_address_new (CamelTcpAddressFamily family, gushort port, - gushort length, gpointer address) -{ - CamelTcpAddress *addr; - - addr = g_malloc (sizeof (CamelTcpAddress) + length - 1); - addr->family = family; - addr->port = port; - addr->length = length; - memcpy (&addr->address, address, length); - - return addr; -} - - -/** - * camel_tcp_address_free: - * @address: the address - * - * Frees @address. - **/ -void -camel_tcp_address_free (CamelTcpAddress *address) -{ - g_free (address); -} diff --git a/camel/camel-tcp-stream.h b/camel/camel-tcp-stream.h deleted file mode 100644 index 9472da10ee..0000000000 --- a/camel/camel-tcp-stream.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - - -#ifndef CAMEL_TCP_STREAM_H -#define CAMEL_TCP_STREAM_H - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include -#include -#include -#include -#include - -#include - -#define CAMEL_TCP_STREAM_TYPE (camel_tcp_stream_get_type ()) -#define CAMEL_TCP_STREAM(obj) (CAMEL_CHECK_CAST((obj), CAMEL_TCP_STREAM_TYPE, CamelTcpStream)) -#define CAMEL_TCP_STREAM_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_TCP_STREAM_TYPE, CamelTcpStreamClass)) -#define CAMEL_IS_TCP_STREAM(o) (CAMEL_CHECK_TYPE((o), CAMEL_TCP_STREAM_TYPE)) - -typedef enum { - CAMEL_SOCKOPT_NONBLOCKING, /* nonblocking io */ - CAMEL_SOCKOPT_LINGER, /* linger on close if data present */ - CAMEL_SOCKOPT_REUSEADDR, /* allow local address reuse */ - CAMEL_SOCKOPT_KEEPALIVE, /* keep connections alive */ - CAMEL_SOCKOPT_RECVBUFFERSIZE, /* receive buffer size */ - CAMEL_SOCKOPT_SENDBUFFERSIZE, /* send buffer size */ - - CAMEL_SOCKOPT_IPTIMETOLIVE, /* time to live */ - CAMEL_SOCKOPT_IPTYPEOFSERVICE, /* type of service and precedence */ - - CAMEL_SOCKOPT_ADDMEMBER, /* add an IP group membership */ - CAMEL_SOCKOPT_DROPMEMBER, /* drop an IP group membership */ - CAMEL_SOCKOPT_MCASTINTERFACE, /* multicast interface address */ - CAMEL_SOCKOPT_MCASTTIMETOLIVE, /* multicast timetolive */ - CAMEL_SOCKOPT_MCASTLOOPBACK, /* multicast loopback */ - - CAMEL_SOCKOPT_NODELAY, /* don't delay send to coalesce packets */ - CAMEL_SOCKOPT_MAXSEGMENT, /* maximum segment size */ - CAMEL_SOCKOPT_BROADCAST, /* enable broadcast */ - CAMEL_SOCKOPT_LAST -} CamelSockOpt; - -typedef struct linger CamelLinger; - -typedef struct _CamelSockOptData { - CamelSockOpt option; - union { - guint ip_ttl; /* IP time to live */ - guint mcast_ttl; /* IP multicast time to live */ - guint tos; /* IP type of service and precedence */ - gboolean non_blocking; /* Non-blocking (network) I/O */ - gboolean reuse_addr; /* Allow local address reuse */ - gboolean keep_alive; /* Keep connections alive */ - gboolean mcast_loopback; /* IP multicast loopback */ - gboolean no_delay; /* Don't delay send to coalesce packets */ - gboolean broadcast; /* Enable broadcast */ - size_t max_segment; /* Maximum segment size */ - size_t recv_buffer_size; /* Receive buffer size */ - size_t send_buffer_size; /* Send buffer size */ - CamelLinger linger; /* Time to linger on close if data present */ - } value; -} CamelSockOptData; - -typedef enum { - CAMEL_TCP_ADDRESS_IPv4, - CAMEL_TCP_ADDRESS_IPv6 -} CamelTcpAddressFamily; - -typedef struct { - CamelTcpAddressFamily family; - gushort port, length; - guint8 address[1]; -} CamelTcpAddress; - - -struct _CamelTcpStream { - CamelStream parent_object; - -}; - -typedef struct { - CamelStreamClass parent_class; - - /* Virtual methods */ - int (*connect) (CamelTcpStream *stream, struct hostent *host, int port); - int (*getsockopt) (CamelTcpStream *stream, CamelSockOptData *data); - int (*setsockopt) (CamelTcpStream *stream, const CamelSockOptData *data); - - CamelTcpAddress * (*get_local_address) (CamelTcpStream *stream); - CamelTcpAddress * (*get_remote_address) (CamelTcpStream *stream); -} CamelTcpStreamClass; - -/* Standard Camel function */ -CamelType camel_tcp_stream_get_type (void); - -/* public methods */ -int camel_tcp_stream_connect (CamelTcpStream *stream, struct hostent *host, int port); -int camel_tcp_stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data); -int camel_tcp_stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data); - -CamelTcpAddress *camel_tcp_stream_get_local_address (CamelTcpStream *stream); -CamelTcpAddress *camel_tcp_stream_get_remote_address (CamelTcpStream *stream); - -CamelTcpAddress *camel_tcp_address_new (CamelTcpAddressFamily family, - gushort port, gushort length, - gpointer address); -void camel_tcp_address_free (CamelTcpAddress *address); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_TCP_STREAM_H */ diff --git a/camel/camel-text-index.c b/camel/camel-text-index.c deleted file mode 100644 index 0e8b1ca96f..0000000000 --- a/camel/camel-text-index.c +++ /dev/null @@ -1,1948 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* - * Copyright (C) 2001-2003 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "e-util/e-msgport.h" -#include "e-util/e-memory.h" - -#include "camel/camel-object.h" - -#include "camel-text-index.h" -#include "camel-block-file.h" -#include "camel-partition-table.h" - -#include - - -#define w(x) -#define io(x) -#define d(x) /*(printf("%s(%d):%s: ", __FILE__, __LINE__, __PRETTY_FUNCTION__),(x))*/ - -/* cursor debug */ -#define c(x) - -#define CAMEL_TEXT_INDEX_MAX_WORDLEN (36) - -#define CAMEL_TEXT_INDEX_LOCK(kf, lock) (e_mutex_lock(((CamelTextIndex *)kf)->priv->lock)) -#define CAMEL_TEXT_INDEX_UNLOCK(kf, lock) (e_mutex_unlock(((CamelTextIndex *)kf)->priv->lock)) - -static int text_index_compress_nosync(CamelIndex *idx); - -/* ********************************************************************** */ - -/* "private" data, shared between index/cursor/name classes */ -typedef struct _CamelTextIndexNamePrivate CamelTextIndexNamePrivate; - -struct _CamelTextIndexNamePrivate { - GString *buffer; - camel_key_t nameid; - EMemPool *pool; -}; - -CamelTextIndexName *camel_text_index_name_new(CamelTextIndex *idx, const char *name, camel_key_t nameid); - -/* ****************************** */ - -typedef struct _CamelTextIndexCursorPrivate CamelTextIndexCursorPrivate; - -struct _CamelTextIndexCursorPrivate { - camel_block_t first; - camel_block_t next; - - int record_index; - - size_t record_count; - camel_key_t *records; - - char *current; -}; - -CamelTextIndexCursor *camel_text_index_cursor_new(CamelTextIndex *idx, camel_block_t data); - -/* ****************************** */ -typedef struct _CamelTextIndexKeyCursorPrivate CamelTextIndexKeyCursorPrivate; - -struct _CamelTextIndexKeyCursorPrivate { - CamelKeyTable *table; - - camel_key_t keyid; - unsigned int flags; - camel_block_t data; - char *current; -}; - -CamelTextIndexKeyCursor *camel_text_index_key_cursor_new(CamelTextIndex *idx, CamelKeyTable *table); - -/* ********************************************************************** */ - -#define CAMEL_TEXT_INDEX_VERSION "TEXT.000" -#define CAMEL_TEXT_INDEX_KEY_VERSION "KEYS.000" - -struct _CamelTextIndexPrivate { - CamelBlockFile *blocks; - CamelKeyFile *links; - - CamelKeyTable *word_index; - CamelPartitionTable *word_hash; - - CamelKeyTable *name_index; - CamelPartitionTable *name_hash; - - /* Cache of words to write */ - int word_cache_limit; - int word_cache_count; - EDList word_cache; - GHashTable *words; - EMutex *lock; -}; - -/* Root block of text index */ -struct _CamelTextIndexRoot { - struct _CamelBlockRoot root; - - /* FIXME: the index root could contain a pointer to the hash root */ - camel_block_t word_index_root; /* a keyindex containing the keyid -> word mapping */ - camel_block_t word_hash_root; /* a partitionindex containing word -> keyid mapping */ - - camel_block_t name_index_root; /* same, for names */ - camel_block_t name_hash_root; - - guint32 words; /* total words */ - guint32 names; /* total names */ - guint32 deleted; /* deleted names */ - guint32 keys; /* total key 'chunks' written, used with deleted to determine fragmentation */ -}; - -struct _CamelTextIndexWord { - struct _CamelTextIndexWord *next; - struct _CamelTextIndexWord *prev; - - camel_block_t data; /* where the data starts */ - camel_key_t wordid; - char *word; - unsigned int used; - camel_key_t names[32]; -}; - -#define CTI_PRIVATE(o) (((CamelTextIndex *)(o))->priv) - -#define CI_CLASS(o) ((CamelTextIndexClass *)(((CamelObject *)o)->classfuncs)) - -/* ********************************************************************** */ -/* CamelTextIndex */ -/* ********************************************************************** */ - -static CamelObjectClass *camel_text_index_parent; - -/* call locked */ -static void -text_index_add_name_to_word(CamelIndex *idx, const char *word, camel_key_t nameid) -{ - struct _CamelTextIndexWord *w, *wp, *ww; - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); - camel_key_t wordid; - camel_block_t data; - struct _CamelTextIndexRoot *rb = (struct _CamelTextIndexRoot *)p->blocks->root; - - w = g_hash_table_lookup(p->words, word); - if (w == NULL) { - wordid = camel_partition_table_lookup(p->word_hash, word); - if (wordid == 0) { - data = 0; - wordid = camel_key_table_add(p->word_index, word, 0, 0); - if (wordid == 0){ - g_warning ("Could not create key entry for word '%s': %s\n", - word, strerror (errno)); - return; - } - if (camel_partition_table_add(p->word_hash, word, wordid) == -1) { - g_warning ("Could not create hash entry for word '%s': %s\n", - word, strerror (errno)); - return; - } - rb->words++; - camel_block_file_touch_block(p->blocks, p->blocks->root_block); - } else { - data = camel_key_table_lookup(p->word_index, wordid, NULL, 0); - if (data == 0) { - g_warning ("Could not find key entry for word '%s': %s\n", - word, strerror (errno)); - return; - } - } - - w = g_malloc0(sizeof(*w)); - w->word = g_strdup(word); - w->wordid = wordid; - w->used = 1; - w->data = data; - - w->names[0] = nameid; - g_hash_table_insert(p->words, w->word, w); - e_dlist_addhead(&p->word_cache, (EDListNode *)w); - p->word_cache_count++; - ww = (struct _CamelTextIndexWord *)p->word_cache.tailpred; - wp = ww->prev; - while (wp && p->word_cache_count > p->word_cache_limit) { - io(printf("writing key file entry '%s' [%x]\n", ww->word, ww->data)); - if (camel_key_file_write(p->links, &ww->data, ww->used, ww->names) != -1) { - io(printf(" new data [%x]\n", ww->data)); - rb->keys++; - camel_block_file_touch_block(p->blocks, p->blocks->root_block); - /* if this call fails - we still point to the old data - not fatal */ - camel_key_table_set_data(p->word_index, ww->wordid, ww->data); - e_dlist_remove((EDListNode *)ww); - g_hash_table_remove(p->words, ww->word); - g_free(ww->word); - g_free(ww); - p->word_cache_count--; - } - ww = wp; - wp = wp->prev; - } - } else { - e_dlist_remove((EDListNode *)w); - e_dlist_addhead(&p->word_cache, (EDListNode *)w); - w->names[w->used] = nameid; - w->used++; - if (w->used == sizeof(w->names)/sizeof(w->names[0])) { - io(printf("writing key file entry '%s' [%x]\n", w->word, w->data)); - if (camel_key_file_write(p->links, &w->data, w->used, w->names) != -1) { - rb->keys++; - camel_block_file_touch_block(p->blocks, p->blocks->root_block); - /* if this call fails - we still point to the old data - not fatal */ - camel_key_table_set_data(p->word_index, w->wordid, w->data); - } - /* FIXME: what to on error? lost data? */ - w->used = 0; - } - } -} - -static int -text_index_sync(CamelIndex *idx) -{ - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); - struct _CamelTextIndexWord *ww; - struct _CamelTextIndexRoot *rb; - int ret = 0, wfrag, nfrag, work = FALSE; - - d(printf("sync: blocks = %p\n", p->blocks)); - - if (p->blocks == NULL) - return 0; - - rb = (struct _CamelTextIndexRoot *)p->blocks->root; - - /* sync/flush word cache */ - - CAMEL_TEXT_INDEX_LOCK(idx, lock); - - /* we sync, bump down the cache limits since we dont need them for reading */ - p->blocks->block_cache_limit = 128; - /* this doesn't really need to be dropped, its only used in updates anyway */ - p->word_cache_limit = 1024; - - work = !e_dlist_empty(&p->word_cache); - - while ( (ww = (struct _CamelTextIndexWord *)e_dlist_remhead(&p->word_cache)) ) { - if (ww->used > 0) { - io(printf("writing key file entry '%s' [%x]\n", ww->word, ww->data)); - if (camel_key_file_write(p->links, &ww->data, ww->used, ww->names) != -1) { - io(printf(" new data [%x]\n", ww->data)); - rb->keys++; - camel_block_file_touch_block(p->blocks, p->blocks->root_block); - camel_key_table_set_data(p->word_index, ww->wordid, ww->data); - } else { - ret = -1; - } - ww->used = 0; - } - g_hash_table_remove(p->words, ww->word); - g_free(ww->word); - g_free(ww); - } - - if (camel_key_table_sync(p->word_index) == -1 - || camel_key_table_sync(p->name_index) == -1 - || camel_partition_table_sync(p->word_hash) == -1 - || camel_partition_table_sync(p->name_hash) == -1) - ret = -1; - - /* only do the frag/compress check if we did some new writes on this index */ - wfrag = rb->words ? (((rb->keys - rb->words) * 100)/ rb->words) : 0; - nfrag = rb->names ? ((rb->deleted * 100) / rb->names) : 0; - d(printf("wfrag = %d, nfrag = %d, work = %s, ret = %d\n", wfrag, nfrag, work?"true":"false", ret)); - d(printf(" words = %d, keys = %d\n", rb->words, rb->keys)); - - if (ret == 0) { - if (wfrag > 30 || nfrag > 20) - ret = text_index_compress_nosync(idx); - } - - ret = camel_block_file_sync(p->blocks); - - CAMEL_TEXT_INDEX_UNLOCK(idx, lock); - - return ret; -} - -static void tmp_name(const char *in, char *o) -{ - char *s; - - s = strrchr(in, '/'); - if (s) { - memcpy(o, in, s-in+1); - memcpy(o+(s-in+1), ".#", 2); - strcpy(o+(s-in+3), s+1); - } else { - sprintf(o, ".#%s", in); - } -} - -static int -text_index_compress(CamelIndex *idx) -{ - int ret; - - CAMEL_TEXT_INDEX_LOCK(idx, lock); - - ret = camel_index_sync(idx); - if (ret != -1) - ret = text_index_compress_nosync(idx); - - CAMEL_TEXT_INDEX_UNLOCK(idx, lock); - - return ret; -} - -/* Attempt to recover index space by compressing the indices */ -static int -text_index_compress_nosync(CamelIndex *idx) -{ - CamelTextIndex *newidx; - struct _CamelTextIndexPrivate *newp, *oldp; - camel_key_t oldkeyid, newkeyid; - GHashTable *remap; - unsigned int deleted; - camel_block_t data, newdata; - int i, ret = -1; - char *name = NULL; - unsigned int flags; - char *newpath, *savepath, *oldpath; - size_t count, newcount; - camel_key_t *records, newrecords[256]; - struct _CamelTextIndexRoot *rb; - - i = strlen(idx->path)+16; - oldpath = alloca(i); - newpath = alloca(i); - savepath = alloca(i); - - strcpy(oldpath, idx->path); - oldpath[strlen(oldpath)-strlen(".index")] = 0; - - tmp_name(oldpath, newpath); - sprintf(savepath, "%s~", oldpath); - - d(printf("Old index: %s\n", idx->path)); - d(printf("Old path: %s\n", oldpath)); - d(printf("New: %s\n", newpath)); - d(printf("Save: %s\n", savepath)); - - newidx = camel_text_index_new(newpath, O_RDWR|O_CREAT); - if (newidx == NULL) - return -1; - - newp = CTI_PRIVATE(newidx); - oldp = CTI_PRIVATE(idx); - - CAMEL_TEXT_INDEX_LOCK(idx, lock); - - rb = (struct _CamelTextIndexRoot *)newp->blocks->root; - - rb->words = 0; - rb->names = 0; - rb->deleted = 0; - rb->keys = 0; - - /* Process: - For each name we still have: - Add it to the new index & setup remap table - - For each word: - Copy word's data to a new file - Add new word to index(*) (can we just copy blocks?) */ - - /* Copy undeleted names to new index file, creating new indices */ - io(printf("Copying undeleted names to new file\n")); - remap = g_hash_table_new(NULL, NULL); - oldkeyid = 0; - deleted = 0; - while ( (oldkeyid = camel_key_table_next(oldp->name_index, oldkeyid, &name, &flags, &data)) ) { - if ((flags&1) == 0) { - io(printf("copying name '%s'\n", name)); - newkeyid = camel_key_table_add(newp->name_index, name, data, flags); - if (newkeyid == 0) - goto fail; - rb->names++; - camel_partition_table_add(newp->name_hash, name, newkeyid); - g_hash_table_insert(remap, GINT_TO_POINTER(oldkeyid), GINT_TO_POINTER(newkeyid)); - } else - io(printf("deleted name '%s'\n", name)); - g_free(name); - name = NULL; - deleted |= flags; - } - - /* Copy word data across, remapping/deleting and create new index for it */ - /* We re-block the data into 256 entry lots while we're at it, since we only - have to do 1 at a time and its cheap */ - oldkeyid = 0; - while ( (oldkeyid = camel_key_table_next(oldp->word_index, oldkeyid, &name, &flags, &data)) ) { - io(printf("copying word '%s'\n", name)); - newdata = 0; - newcount = 0; - if (data) { - rb->words++; - rb->keys++; - } - while (data) { - if (camel_key_file_read(oldp->links, &data, &count, &records) == -1) { - io(printf("could not read from old keys at %d for word '%s'\n", (int)data, name)); - goto fail; - } - for (i=0;ilinks, &newdata, newcount, newrecords) == -1) { - g_free(records); - goto fail; - } - newcount = 0; - } - } - } - g_free(records); - } - - if (newcount > 0) { - if (camel_key_file_write(newp->links, &newdata, newcount, newrecords) == -1) - goto fail; - } - - if (newdata != 0) { - newkeyid = camel_key_table_add(newp->word_index, name, newdata, flags); - if (newkeyid == 0) - goto fail; - camel_partition_table_add(newp->word_hash, name, newkeyid); - } - g_free(name); - name = NULL; - } - - camel_block_file_touch_block(newp->blocks, newp->blocks->root_block); - - if (camel_index_sync((CamelIndex *)newidx) == -1) - goto fail; - - /* Rename underlying files to match */ - ret = camel_index_rename(idx, savepath); - if (ret == -1) - goto fail; - - /* If this fails, we'll pick up something during restart? */ - ret = camel_index_rename((CamelIndex *)newidx, oldpath); - -#define myswap(a, b) { void *tmp = a; a = b; b = tmp; } - /* Poke the private data across to the new object */ - /* And change the fd's over, etc? */ - /* Yes: This is a hack */ - myswap(newp->blocks, oldp->blocks); - myswap(newp->links, oldp->links); - myswap(newp->word_index, oldp->word_index); - myswap(newp->word_hash, oldp->word_hash); - myswap(newp->name_index, oldp->name_index); - myswap(newp->name_hash, oldp->name_hash); - myswap(((CamelIndex *)newidx)->path, ((CamelIndex *)idx)->path); -#undef myswap - - ret = 0; -fail: - CAMEL_TEXT_INDEX_UNLOCK(idx, lock); - - camel_index_delete((CamelIndex *)newidx); - - camel_object_unref((CamelObject *)newidx); - g_free(name); - g_hash_table_destroy(remap); - - /* clean up temp files always */ - sprintf(savepath, "%s~.index", oldpath); - unlink(savepath); - sprintf(newpath, "%s.data", savepath); - unlink(newpath); - - return ret; -} - -static int -text_index_delete(CamelIndex *idx) -{ - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); - int ret = 0; - - if (camel_block_file_delete(p->blocks) == -1) - ret = -1; - if (camel_key_file_delete(p->links) == -1) - ret = -1; - - return ret; -} - -static int -text_index_rename(CamelIndex *idx, const char *path) -{ - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); - char *newlink, *newblock; - int err, ret; - - CAMEL_TEXT_INDEX_LOCK(idx, lock); - - newblock = alloca(strlen(path)+8); - sprintf(newblock, "%s.index", path); - ret = camel_block_file_rename(p->blocks, newblock); - if (ret == -1) { - CAMEL_TEXT_INDEX_UNLOCK(idx, lock); - return -1; - } - - newlink = alloca(strlen(path)+16); - sprintf(newlink, "%s.index.data", path); - ret = camel_key_file_rename(p->links, newlink); - if (ret == -1) { - err = errno; - camel_block_file_rename(p->blocks, idx->path); - CAMEL_TEXT_INDEX_UNLOCK(idx, lock); - errno = err; - return -1; - } - - g_free(idx->path); - idx->path = g_strdup(newblock); - - CAMEL_TEXT_INDEX_UNLOCK(idx, lock); - - return 0; -} - -static int -text_index_has_name(CamelIndex *idx, const char *name) -{ - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); - - return camel_partition_table_lookup(p->name_hash, name) != 0; -} - -static CamelIndexName * -text_index_add_name(CamelIndex *idx, const char *name) -{ - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); - camel_key_t keyid; - CamelIndexName *idn; - struct _CamelTextIndexRoot *rb = (struct _CamelTextIndexRoot *)p->blocks->root; - - CAMEL_TEXT_INDEX_LOCK(idx, lock); - - /* if we're adding words, up the cache limits a lot */ - if (p->blocks) { - p->blocks->block_cache_limit = 1024; - p->word_cache_limit = 8192; - } - - /* If we have it already replace it */ - keyid = camel_partition_table_lookup(p->name_hash, name); - if (keyid != 0) { - /* TODO: We could just update the partition table's - key pointer rather than having to delete it */ - rb->deleted++; - camel_key_table_set_flags(p->name_index, keyid, 1, 1); - camel_partition_table_remove(p->name_hash, name); - } - - keyid = camel_key_table_add(p->name_index, name, 0, 0); - if (keyid != 0) { - camel_partition_table_add(p->name_hash, name, keyid); - rb->names++; - } - - camel_block_file_touch_block(p->blocks, p->blocks->root_block); - - /* TODO: if keyid == 0, we had a failure, we should somehow flag that, but for - now just return a valid object but discard its results, see text_index_write_name */ - - CAMEL_TEXT_INDEX_UNLOCK(idx, lock); - - idn = (CamelIndexName *)camel_text_index_name_new((CamelTextIndex *)idx, name, keyid); - - return idn; -} - -/* call locked */ -static void -hash_write_word(char *word, void *data, CamelIndexName *idn) -{ - CamelTextIndexName *tin = (CamelTextIndexName *)idn; - - text_index_add_name_to_word(idn->index, word, tin->priv->nameid); -} - -static int -text_index_write_name(CamelIndex *idx, CamelIndexName *idn) -{ - /* force 'flush' of any outstanding data */ - camel_index_name_add_buffer(idn, NULL, 0); - - /* see text_index_add_name for when this can be 0 */ - if (((CamelTextIndexName *)idn)->priv->nameid != 0) { - CAMEL_TEXT_INDEX_LOCK(idx, lock); - - g_hash_table_foreach(idn->words, (GHFunc)hash_write_word, idn); - - CAMEL_TEXT_INDEX_UNLOCK(idx, lock); - } - - return 0; -} - -static CamelIndexCursor * -text_index_find_name(CamelIndex *idx, const char *name) -{ - /* what was this for, umm */ - return NULL; -} - -static void -text_index_delete_name(CamelIndex *idx, const char *name) -{ - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); - camel_key_t keyid; - struct _CamelTextIndexRoot *rb = (struct _CamelTextIndexRoot *)p->blocks->root; - - d(printf("Delete name: %s\n", name)); - - /* probably doesn't really need locking, but oh well */ - CAMEL_TEXT_INDEX_LOCK(idx, lock); - - /* We just mark the key deleted, and remove it from the hash table */ - keyid = camel_partition_table_lookup(p->name_hash, name); - if (keyid != 0) { - rb->deleted++; - camel_block_file_touch_block(p->blocks, p->blocks->root_block); - camel_key_table_set_flags(p->name_index, keyid, 1, 1); - camel_partition_table_remove(p->name_hash, name); - } - - CAMEL_TEXT_INDEX_UNLOCK(idx, lock); -} - -static CamelIndexCursor * -text_index_find(CamelIndex *idx, const char *word) -{ - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); - camel_key_t keyid; - camel_block_t data = 0; - unsigned int flags; - CamelIndexCursor *idc; - - CAMEL_TEXT_INDEX_LOCK(idx, lock); - - keyid = camel_partition_table_lookup(p->word_hash, word); - if (keyid != 0) { - data = camel_key_table_lookup(p->word_index, keyid, NULL, &flags); - if (flags & 1) - data = 0; - } - - CAMEL_TEXT_INDEX_UNLOCK(idx, lock); - - idc = (CamelIndexCursor *)camel_text_index_cursor_new((CamelTextIndex *)idx, data); - - return idc; -} - -static CamelIndexCursor * -text_index_words(CamelIndex *idx) -{ - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); - - return (CamelIndexCursor *)camel_text_index_key_cursor_new((CamelTextIndex *)idx, p->word_index); -} - -static CamelIndexCursor * -text_index_names(CamelIndex *idx) -{ - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); - - return (CamelIndexCursor *)camel_text_index_key_cursor_new((CamelTextIndex *)idx, p->name_index); -} - -static void -camel_text_index_class_init(CamelTextIndexClass *klass) -{ - CamelIndexClass *iklass = (CamelIndexClass *)klass; - - camel_text_index_parent = CAMEL_OBJECT_CLASS(camel_type_get_global_classfuncs(camel_object_get_type())); - - iklass->sync = text_index_sync; - iklass->compress = text_index_compress; - iklass->delete = text_index_delete; - - iklass->rename = text_index_rename; - - iklass->has_name = text_index_has_name; - iklass->add_name = text_index_add_name; - iklass->write_name = text_index_write_name; - iklass->find_name = text_index_find_name; - iklass->delete_name = text_index_delete_name; - iklass->find = text_index_find; - - iklass->words = text_index_words; - iklass->names = text_index_names; -} - -static void -camel_text_index_init(CamelTextIndex *idx) -{ - struct _CamelTextIndexPrivate *p; - - p = CTI_PRIVATE(idx) = g_malloc0(sizeof(*p)); - - e_dlist_init(&p->word_cache); - p->words = g_hash_table_new(g_str_hash, g_str_equal); - p->word_cache_count = 0; - /* this cache size and the block cache size have been tuned for about the best - with moderate memory usage. Doubling the memory usage barely affects performance. */ - p->word_cache_limit = 4096; /* 1024 = 128K */ - - p->lock = e_mutex_new(E_MUTEX_REC); -} - -static void -camel_text_index_finalise(CamelTextIndex *idx) -{ - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); - - camel_index_sync((CamelIndex *)idx); - - g_assert(e_dlist_empty(&p->word_cache)); - g_assert(g_hash_table_size(p->words) == 0); - - g_hash_table_destroy(p->words); - - if (p->word_index) - camel_object_unref((CamelObject *)p->word_index); - if (p->word_hash) - camel_object_unref((CamelObject *)p->word_hash); - if (p->name_index) - camel_object_unref((CamelObject *)p->name_index); - if (p->name_hash) - camel_object_unref((CamelObject *)p->name_hash); - - if (p->blocks) - camel_object_unref((CamelObject *)p->blocks); - if (p->links) - camel_object_unref((CamelObject *)p->links); - - e_mutex_destroy(p->lock); - - g_free(p); -} - -CamelType -camel_text_index_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_index_get_type(), "CamelTextIndex", - sizeof (CamelTextIndex), - sizeof (CamelTextIndexClass), - (CamelObjectClassInitFunc) camel_text_index_class_init, - NULL, - (CamelObjectInitFunc) camel_text_index_init, - (CamelObjectFinalizeFunc) camel_text_index_finalise); - } - - return type; -} - -static char * -text_index_normalise(CamelIndex *idx, const char *in, void *data) -{ - char *word; - - /* Sigh, this is really expensive */ - /*g_utf8_normalize(in, strlen(in), G_NORMALIZE_ALL);*/ - word = g_utf8_strdown(in, -1); - - return word; -} - -CamelTextIndex * -camel_text_index_new(const char *path, int flags) -{ - CamelTextIndex *idx = (CamelTextIndex *)camel_object_new(camel_text_index_get_type()); - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); - struct _CamelTextIndexRoot *rb; - char *link; - CamelBlock *bl; - - camel_index_construct((CamelIndex *)idx, path, flags); - camel_index_set_normalise((CamelIndex *)idx, text_index_normalise, NULL); - - p->blocks = camel_block_file_new(idx->parent.path, flags, CAMEL_TEXT_INDEX_VERSION, CAMEL_BLOCK_SIZE); - link = alloca(strlen(idx->parent.path)+7); - sprintf(link, "%s.data", idx->parent.path); - p->links = camel_key_file_new(link, flags, CAMEL_TEXT_INDEX_KEY_VERSION); - - if (p->blocks == NULL || p->links == NULL) { - camel_object_unref((CamelObject *)idx); - return NULL; - } - - rb = (struct _CamelTextIndexRoot *)p->blocks->root; - - if (rb->word_index_root == 0) { - bl = camel_block_file_new_block(p->blocks); - rb->word_index_root = bl->id; - camel_block_file_unref_block(p->blocks, bl); - camel_block_file_touch_block(p->blocks, p->blocks->root_block); - } - - if (rb->word_hash_root == 0) { - bl = camel_block_file_new_block(p->blocks); - rb->word_hash_root = bl->id; - camel_block_file_unref_block(p->blocks, bl); - camel_block_file_touch_block(p->blocks, p->blocks->root_block); - } - - if (rb->name_index_root == 0) { - bl = camel_block_file_new_block(p->blocks); - rb->name_index_root = bl->id; - camel_block_file_unref_block(p->blocks, bl); - camel_block_file_touch_block(p->blocks, p->blocks->root_block); - } - - if (rb->name_hash_root == 0) { - bl = camel_block_file_new_block(p->blocks); - rb->name_hash_root = bl->id; - camel_block_file_unref_block(p->blocks, bl); - camel_block_file_touch_block(p->blocks, p->blocks->root_block); - } - - p->word_index = camel_key_table_new(p->blocks, rb->word_index_root); - p->word_hash = camel_partition_table_new(p->blocks, rb->word_hash_root); - p->name_index = camel_key_table_new(p->blocks, rb->name_index_root); - p->name_hash = camel_partition_table_new(p->blocks, rb->name_hash_root); - - if (p->word_index == NULL || p->word_hash == NULL - || p->name_index == NULL || p->name_hash == NULL) { - camel_object_unref((CamelObject *)idx); - idx = NULL; - } - - return idx; -} - -/* returns 0 if the index exists, is valid, and synced, -1 otherwise */ -int -camel_text_index_check(const char *path) -{ - char *block, *key; - CamelBlockFile *blocks; - CamelKeyFile *keys; - - block = alloca(strlen(path)+7); - sprintf(block, "%s.index", path); - blocks = camel_block_file_new(block, O_RDONLY, CAMEL_TEXT_INDEX_VERSION, CAMEL_BLOCK_SIZE); - if (blocks == NULL) { - io(printf("Check failed: No block file: %s\n", strerror (errno))); - return -1; - } - key = alloca(strlen(path)+12); - sprintf(key, "%s.index.data", path); - keys = camel_key_file_new(key, O_RDONLY, CAMEL_TEXT_INDEX_KEY_VERSION); - if (keys == NULL) { - io(printf("Check failed: No key file: %s\n", strerror (errno))); - camel_object_unref((CamelObject *)blocks); - return -1; - } - - camel_object_unref((CamelObject *)keys); - camel_object_unref((CamelObject *)blocks); - - return 0; -} - -int -camel_text_index_rename(const char *old, const char *new) -{ - char *oldname, *newname; - int err; - - /* TODO: camel_text_index_rename should find out if we have an active index and use that instead */ - - oldname = alloca(strlen(old)+12); - newname = alloca(strlen(new)+12); - sprintf(oldname, "%s.index", old); - sprintf(newname, "%s.index", new); - - if (rename(oldname, newname) == -1 && errno != ENOENT) - return -1; - - sprintf(oldname, "%s.index.data", old); - sprintf(newname, "%s.index.data", new); - - if (rename(oldname, newname) == -1 && errno != ENOENT) { - err = errno; - sprintf(oldname, "%s.index", old); - sprintf(newname, "%s.index", new); - rename(newname, oldname); - errno = err; - return -1; - } - - return 0; -} - -int -camel_text_index_remove(const char *old) -{ - char *block, *key; - int ret = 0; - - /* TODO: needs to poke any active indices to remain unlinked */ - - block = alloca(strlen(old)+12); - key = alloca(strlen(old)+12); - sprintf(block, "%s.index", old); - sprintf(key, "%s.index.data", old); - - if (unlink(block) == -1 && errno != ENOENT) - ret = -1; - if (unlink(key) == -1 && errno != ENOENT) - ret = -1; - - return ret; -} - -/* Debug */ -void -camel_text_index_info(CamelTextIndex *idx) -{ - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); - struct _CamelTextIndexRoot *rb = (struct _CamelTextIndexRoot *)p->blocks->root; - int frag; - - printf("Path: '%s'\n", idx->parent.path); - printf("Version: %d\n", idx->parent.version); - printf("Flags: %08x\n", idx->parent.flags); - printf("Total words: %d\n", rb->words); - printf("Total names: %d\n", rb->names); - printf("Total deleted: %d\n", rb->deleted); - printf("Total key blocks: %d\n", rb->keys); - - if (rb->words > 0) { - frag = ((rb->keys - rb->words) * 100)/ rb->words; - printf("Word fragmentation: %d%%\n", frag); - } - - if (rb->names > 0) { - frag = (rb->deleted * 100)/ rb->names; - printf("Name fragmentation: %d%%\n", frag); - } -} - -/* #define DUMP_RAW */ - -#ifdef DUMP_RAW -enum { KEY_ROOT = 1, KEY_DATA = 2, PARTITION_MAP = 4, PARTITION_DATA = 8 }; - -static void -add_type(GHashTable *map, camel_block_t id, int type) -{ - camel_block_t old; - - old = g_hash_table_lookup(map, id); - if (old == type) - return; - - if (old != 0 && old != type) - g_warning("block %x redefined as type %d, already type %d\n", id, type, old); - g_hash_table_insert(map, id, type|old); -} - -static void -add_partition(GHashTable *map, CamelBlockFile *blocks, camel_block_t id) -{ - CamelBlock *bl; - CamelPartitionMapBlock *pm; - int i; - - while (id) { - add_type(map, id, PARTITION_MAP); - bl = camel_block_file_get_block(blocks, id); - if (bl == NULL) { - g_warning("couldn't get parition: %x\n", id); - return; - } - - pm = (CamelPartitionMapBlock *)&bl->data; - if (pm->used > sizeof(pm->partition)/sizeof(pm->partition[0])) { - g_warning("Partition block %x invalid\n", id); - camel_block_file_unref_block(blocks, bl); - return; - } - - for (i=0;iused;i++) - add_type(map, pm->partition[i].blockid, PARTITION_DATA); - - id = pm->next; - camel_block_file_unref_block(blocks, bl); - } -} - -static void -add_keys(GHashTable *map, CamelBlockFile *blocks, camel_block_t id) -{ - CamelBlock *rbl, *bl; - CamelKeyRootBlock *root; - CamelKeyBlock *kb; - - add_type(map, id, KEY_ROOT); - rbl = camel_block_file_get_block(blocks, id); - if (rbl == NULL) { - g_warning("couldn't get key root: %x\n", id); - return; - } - root = (CamelKeyRootBlock *)&rbl->data; - id = root->first; - - while (id) { - add_type(map, id, KEY_DATA); - bl = camel_block_file_get_block(blocks, id); - if (bl == NULL) { - g_warning("couldn't get key: %x\n", id); - break; - } - - kb = (CamelKeyBlock *)&bl->data; - id = kb->next; - camel_block_file_unref_block(blocks, bl); - } - - camel_block_file_unref_block(blocks, rbl); -} - -static void -dump_raw(GHashTable *map, char *path) -{ - char buf[1024]; - char line[256]; - char *p, c, *e, *a, *o; - int v, n, len, i, type; - char hex[16] = "0123456789ABCDEF"; - int fd; - camel_block_t id, total; - - fd = open(path, O_RDONLY); - if (fd == -1) - return; - - total = 0; - while ((len = read(fd, buf, 1024)) == 1024) { - id = total; - - - - type = g_hash_table_lookup(map, id); - switch(type) { - case 0: - printf(" - unknown -\n"); - break; - default: - printf(" - invalid -\n"); - break; - case KEY_ROOT: { - CamelKeyRootBlock *r = (CamelKeyRootBlock *)buf; - printf("Key root:\n"); - printf("First: %08x Last: %08x Free: %08x\n", r->first, r->last, r->free); - } break; - case KEY_DATA: { - CamelKeyBlock *k = (CamelKeyBlock *)buf; - printf("Key data:\n"); - printf("Next: %08x Used: %u\n", k->next, k->used); - for (i=0;iused;i++) { - if (i == 0) - len = sizeof(k->u.keydata); - else - len = k->u.keys[i-1].offset; - len -= k->u.keys[i].offset; - printf("[%03d]: %08x %5d %06x %3d '%.*s'\n", i, - k->u.keys[i].data, k->u.keys[i].offset, k->u.keys[i].flags, - len, len, k->u.keydata+k->u.keys[i].offset); - } - } break; - case PARTITION_MAP: { - CamelPartitionMapBlock *m = (CamelPartitionMapBlock *)buf; - printf("Partition map\n"); - printf("Next: %08x Used: %u\n", m->next, m->used); - for (i=0;iused;i++) { - printf("[%03d]: %08x -> %08x\n", i, m->partition[i].hashid, m->partition[i].blockid); - } - } break; - case PARTITION_DATA: { - CamelPartitionKeyBlock *k = (CamelPartitionKeyBlock *)buf; - printf("Partition data\n"); - printf("Used: %u\n", k->used); - } break; - } - - - printf("--raw--\n"); - - len = 1024; - p = buf; - do { - sprintf(line, "%08x: ", total); - total += 16; - o = line+10; - a = o+16*2+2; - i = 0; - while (len && i<16) { - c = *p++; - *a++ = isprint(c)?c:'.'; - *o++ = hex[(c>>4)&0x0f]; - *o++ = hex[c&0x0f]; - i++; - if (i==8) - *o++ = ' '; - len--; - } - *a = 0; - printf("%s\n", line); - } while (len); - printf("\n"); - } -} -#endif - -/* Debug */ -void -camel_text_index_dump(CamelTextIndex *idx) -{ - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); -#ifndef DUMP_RAW - camel_key_t keyid; - char *word; - const char *name; - unsigned int flags; - camel_block_t data; - - /* Iterate over all names in the file first */ - - printf("UID's in index\n"); - - keyid = 0; - while ( (keyid = camel_key_table_next(p->name_index, keyid, &word, &flags, &data)) ) { - if ((flags & 1) == 0) - printf(" %s\n", word); - else - printf(" %s (deleted)\n", word); - g_free(word); - } - - printf("Word's in index\n"); - - keyid = 0; - while ( (keyid = camel_key_table_next(p->word_index, keyid, &word, &flags, &data)) ) { - CamelIndexCursor *idc; - - printf("Word: '%s':\n", word); - - idc = camel_index_find((CamelIndex *)idx, word); - while ( (name = camel_index_cursor_next(idc)) ) { - printf(" %s", name); - } - printf("\n"); - camel_object_unref((CamelObject *)idc); - g_free(word); - } -#else - /* a more low-level dump routine */ - GHashTable *block_type = g_hash_table_new(NULL, NULL); - camel_block_t id; - struct stat st; - int type; - - add_keys(block_type, p->blocks, p->word_index->rootid); - add_keys(block_type, p->blocks, p->name_index->rootid); - - add_partition(block_type, p->blocks, p->word_hash->rootid); - add_partition(block_type, p->blocks, p->name_hash->rootid); - - dump_raw(block_type, p->blocks->path); - g_hash_table_destroy(block_type); -#endif -} - -/* more debug stuff */ -void -camel_text_index_validate(CamelTextIndex *idx) -{ - struct _CamelTextIndexPrivate *p = CTI_PRIVATE(idx); - camel_key_t keyid; - char *word; - const char *name; - unsigned int flags; - camel_block_t data; - char *oldword; - camel_key_t *records; - size_t count; - - GHashTable *names, *deleted, *words, *keys, *name_word, *word_word; - - names = g_hash_table_new(NULL, NULL); - deleted = g_hash_table_new(NULL, NULL); - - name_word = g_hash_table_new(g_str_hash, g_str_equal); - - words = g_hash_table_new(NULL, NULL); - keys = g_hash_table_new(NULL, NULL); - - word_word = g_hash_table_new(g_str_hash, g_str_equal); - - /* Iterate over all names in the file first */ - - printf("Checking UID consistency\n"); - - keyid = 0; - while ( (keyid = camel_key_table_next(p->name_index, keyid, &word, &flags, &data)) ) { - if ((oldword = g_hash_table_lookup(names, GINT_TO_POINTER(keyid))) != NULL - || (oldword = g_hash_table_lookup(deleted, GINT_TO_POINTER(keyid))) != NULL) { - printf("Warning, name '%s' duplicates key (%x) with name '%s'\n", word, keyid, oldword); - g_free(word); - } else { - g_hash_table_insert(name_word, word, (void *)1); - if ((flags & 1) == 0) { - g_hash_table_insert(names, GINT_TO_POINTER(keyid), word); - } else { - g_hash_table_insert(deleted, GINT_TO_POINTER(keyid), word); - } - } - } - - printf("Checking WORD member consistency\n"); - - keyid = 0; - while ( (keyid = camel_key_table_next(p->word_index, keyid, &word, &flags, &data)) ) { - CamelIndexCursor *idc; - GHashTable *used; - - /* first, check for duplicates of keyid, and data */ - if ((oldword = g_hash_table_lookup(words, GINT_TO_POINTER(keyid))) != NULL) { - printf("Warning, word '%s' duplicates key (%x) with name '%s'\n", word, keyid, oldword); - g_free(word); - word = oldword; - } else { - g_hash_table_insert(words, GINT_TO_POINTER(keyid), word); - } - - if (data == 0) { - /* This may not be an issue if things have been removed over time, - though it is a problem if its a fresh index */ - printf("Word '%s' has no data associated with it\n", word); - } else { - if ((oldword = g_hash_table_lookup(keys, GUINT_TO_POINTER(data))) != NULL) { - printf("Warning, word '%s' duplicates data (%x) with name '%s'\n", word, data, oldword); - } else { - g_hash_table_insert(keys, GUINT_TO_POINTER(data), word); - } - } - - if ((oldword = g_hash_table_lookup(word_word, word)) != NULL) { - printf("Warning, word '%s' occurs more than once\n", word); - } else { - g_hash_table_insert(word_word, word, word); - } - - used = g_hash_table_new(g_str_hash, g_str_equal); - - idc = camel_index_find((CamelIndex *)idx, word); - while ( (name = camel_index_cursor_next(idc)) ) { - if (g_hash_table_lookup(name_word, name) == NULL) { - printf("word '%s' references non-existant name '%s'\n", word, name); - } - if (g_hash_table_lookup(used, name) != NULL) { - printf("word '%s' uses word '%s' more than once\n", word, name); - } else { - g_hash_table_insert(used, g_strdup(name), (void *)1); - } - } - camel_object_unref((CamelObject *)idc); - - g_hash_table_foreach(used, (GHFunc)g_free, NULL); - g_hash_table_destroy(used); - - printf("word '%s'\n", word); - - while (data) { - printf(" data %x ", data); - if (camel_key_file_read(p->links, &data, &count, &records) == -1) { - printf("Warning, read failed for word '%s', at data '%d'\n", word, data); - data = 0; - } else { - printf("(%d)\n", count); - g_free(records); - } - } - } - - g_hash_table_destroy(names); - g_hash_table_destroy(deleted); - g_hash_table_destroy(words); - g_hash_table_destroy(keys); - - g_hash_table_foreach(name_word, (GHFunc)g_free, NULL); - g_hash_table_destroy(name_word); - - g_hash_table_foreach(word_word, (GHFunc)g_free, NULL); - g_hash_table_destroy(word_word); -} - -/* ********************************************************************** */ -/* CamelTextIndexName */ -/* ********************************************************************** */ - -static CamelIndexNameClass *camel_text_index_name_parent; - -#define CIN_CLASS(o) ((CamelTextIndexNameClass *)(((CamelObject *)o)->classfuncs)) -#define CIN_PRIVATE(o) (((CamelTextIndexName *)(o))->priv) - -static void -text_index_name_add_word(CamelIndexName *idn, const char *word) -{ - struct _CamelTextIndexNamePrivate *p = ((CamelTextIndexName *)idn)->priv; - - if (g_hash_table_lookup(idn->words, word) == NULL) { - char *w = e_mempool_strdup(p->pool, word); - - g_hash_table_insert(idn->words, w, w); - } -} - -/* Why? - Because it doesn't hang/loop forever on bad data - Used to clean up utf8 before it gets further */ - -static inline guint32 -camel_utf8_next(const unsigned char **ptr, const unsigned char *ptrend) -{ - register unsigned char *p = (unsigned char *)*ptr; - register unsigned int c; - register guint32 v; - int l; - - if (p == ptrend) - return 0; - - while ( (c = *p++) ) { - if (c < 0x80) { - *ptr = p; - return c; - } else if ((c&0xe0) == 0xc0) { - v = c & 0x1f; - l = 1; - } else if ((c&0xf0) == 0xe0) { - v = c & 0x0f; - l = 2; - } else if ((c&0xf8) == 0xf0) { - v = c & 0x07; - l = 3; - } else if ((c&0xfc) == 0xf8) { - v = c & 0x03; - l = 4; - } else if ((c&0xfe) == 0xfc) { - v = c & 0x01; - l = 5; - } else - /* Invalid, ignore and look for next start char if room */ - if (p == ptrend) { - return 0; - } else { - continue; - } - - /* bad data or truncated buffer */ - if (p + l > ptrend) - return 0; - - while (l && ((c = *p) & 0xc0) == 0x80) { - p++; - l--; - v = (v << 6) | (c & 0x3f); - } - - /* valid char */ - if (l == 0) { - *ptr = p; - return v; - } - - /* else look for a start char again */ - } - - return 0; -} - -static size_t -text_index_name_add_buffer(CamelIndexName *idn, const char *buffer, size_t len) -{ - CamelTextIndexNamePrivate *p = CIN_PRIVATE(idn); - const unsigned char *ptr, *ptrend; - guint32 c; - unsigned char utf8[8]; - size_t utf8len; - - if (buffer == NULL) { - if (p->buffer->len) { - camel_index_name_add_word(idn, p->buffer->str); - g_string_truncate(p->buffer, 0); - } - return 0; - } - - ptr = buffer; - ptrend = buffer+len; - while ((c = camel_utf8_next(&ptr, ptrend))) { - if (g_unichar_isalnum(c)) { - c = g_unichar_tolower(c); - utf8len = g_unichar_to_utf8(c, utf8); - utf8[utf8len] = 0; - g_string_append(p->buffer, utf8); - } else { - if (p->buffer->len > 0 && p->buffer->len <= CAMEL_TEXT_INDEX_MAX_WORDLEN) { - text_index_name_add_word(idn, p->buffer->str); - /*camel_index_name_add_word(idn, p->buffer->str);*/ - } - - g_string_truncate (p->buffer, 0); - } - } - - return 0; -} - -static void -camel_text_index_name_class_init(CamelTextIndexNameClass *klass) -{ - CamelIndexNameClass *nklass = (CamelIndexNameClass *)klass; - - camel_text_index_name_parent = CAMEL_INDEX_NAME_CLASS(camel_type_get_global_classfuncs(camel_index_name_get_type())); - - nklass->add_word = text_index_name_add_word; - nklass->add_buffer = text_index_name_add_buffer; -} - -static void -camel_text_index_name_init(CamelTextIndexName *idn) -{ - CamelTextIndexNamePrivate *p; - - idn->parent.words = g_hash_table_new(g_str_hash, g_str_equal); - - p = idn->priv = g_malloc0(sizeof(*idn->priv)); - p->buffer = g_string_new(""); - p->pool = e_mempool_new(256, 128, E_MEMPOOL_ALIGN_BYTE); -} - -static void -camel_text_index_name_finalise(CamelTextIndexName *idn) -{ - CamelTextIndexNamePrivate *p = CIN_PRIVATE(idn); - - g_hash_table_destroy(idn->parent.words); - - g_string_free(p->buffer, TRUE); - e_mempool_destroy(p->pool); - - g_free(p); -} - -CamelType -camel_text_index_name_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_index_name_get_type(), "CamelTextIndexName", - sizeof (CamelTextIndexName), - sizeof (CamelTextIndexNameClass), - (CamelObjectClassInitFunc) camel_text_index_name_class_init, - NULL, - (CamelObjectInitFunc) camel_text_index_name_init, - (CamelObjectFinalizeFunc) camel_text_index_name_finalise); - } - - return type; -} - -CamelTextIndexName * -camel_text_index_name_new(CamelTextIndex *idx, const char *name, camel_key_t nameid) -{ - CamelTextIndexName *idn = (CamelTextIndexName *)camel_object_new(camel_text_index_name_get_type()); - CamelIndexName *cin = &idn->parent; - CamelTextIndexNamePrivate *p = CIN_PRIVATE(idn); - - cin->index = (CamelIndex *)idx; - camel_object_ref((CamelObject *)idx); - cin->name = e_mempool_strdup(p->pool, name); - p->nameid = nameid; - - return idn; -} - -/* ********************************************************************** */ -/* CamelTextIndexCursor */ -/* ********************************************************************** */ - -static CamelIndexCursorClass *camel_text_index_cursor_parent; - -#define CIC_CLASS(o) ((CamelTextIndexCursorClass *)(((CamelObject *)o)->classfuncs)) -#define CIC_PRIVATE(o) (((CamelTextIndexCursor *)(o))->priv) - -static const char * -text_index_cursor_next(CamelIndexCursor *idc) -{ - struct _CamelTextIndexCursorPrivate *p = CIC_PRIVATE(idc); - struct _CamelTextIndexPrivate *tip = CTI_PRIVATE(idc->index); - unsigned int flags; - - c(printf("Going to next cursor for word with data '%08x' next %08x\n", p->first, p->next)); - - do { - while (p->record_index >= p->record_count) { - g_free(p->records); - p->records = NULL; - p->record_index = 0; - p->record_count = 0; - if (p->next == 0) - return NULL; - if (camel_key_file_read(tip->links, &p->next, &p->record_count, &p->records) == -1) - return NULL; - } - - g_free(p->current); - camel_key_table_lookup(tip->name_index, p->records[p->record_index], &p->current, &flags); - if (flags & 1) { - g_free(p->current); - p->current = NULL; - } - p->record_index++; - } while (p->current == NULL); - - return p->current; -} - -static void -text_index_cursor_reset(CamelIndexCursor *idc) -{ - struct _CamelTextIndexCursorPrivate *p = CIC_PRIVATE(idc); - - g_free(p->records); - p->records = NULL; - g_free(p->current); - p->current = NULL; - p->record_count = 0; - p->record_index = 0; - p->next = p->first; -} - -static void -camel_text_index_cursor_class_init(CamelTextIndexCursorClass *klass) -{ - CamelIndexCursorClass *cklass = (CamelIndexCursorClass *)klass; - - camel_text_index_cursor_parent = CAMEL_INDEX_CURSOR_CLASS(camel_type_get_global_classfuncs(camel_index_cursor_get_type())); - - cklass->next = text_index_cursor_next; - cklass->reset = text_index_cursor_reset; -} - -static void -camel_text_index_cursor_init(CamelTextIndexCursor *idc) -{ - CIC_PRIVATE(idc) = g_malloc0(sizeof(struct _CamelTextIndexCursorPrivate)); -} - -static void -camel_text_index_cursor_finalise(CamelTextIndexCursor *idc) -{ - struct _CamelTextIndexCursorPrivate *p = CIC_PRIVATE(idc); - - g_free(p->records); - g_free(p->current); - g_free(p); -} - -CamelType -camel_text_index_cursor_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_index_cursor_get_type(), "CamelTextIndexCursor", - sizeof (CamelTextIndexCursor), - sizeof (CamelTextIndexCursorClass), - (CamelObjectClassInitFunc) camel_text_index_cursor_class_init, - NULL, - (CamelObjectInitFunc) camel_text_index_cursor_init, - (CamelObjectFinalizeFunc) camel_text_index_cursor_finalise); - } - - return type; -} - -CamelTextIndexCursor * -camel_text_index_cursor_new(CamelTextIndex *idx, camel_block_t data) -{ - CamelTextIndexCursor *idc = (CamelTextIndexCursor *)camel_object_new(camel_text_index_cursor_get_type()); - CamelIndexCursor *cic = &idc->parent; - struct _CamelTextIndexCursorPrivate *p = CIC_PRIVATE(idc); - - cic->index = (CamelIndex *)idx; - camel_object_ref((CamelObject *)idx); - p->first = data; - p->next = data; - p->record_count = 0; - p->record_index = 0; - - return idc; -} - -/* ********************************************************************** */ -/* CamelTextIndexKeyCursor */ -/* ********************************************************************** */ - -static CamelIndexCursorClass *camel_text_index_key_cursor_parent; - -#define CIKC_CLASS(o) ((CamelTextIndexKeyCursorClass *)(((CamelObject *)o)->classfuncs)) -#define CIKC_PRIVATE(o) (((CamelTextIndexKeyCursor *)(o))->priv) - -static const char * -text_index_key_cursor_next(CamelIndexCursor *idc) -{ - struct _CamelTextIndexKeyCursorPrivate *p = CIKC_PRIVATE(idc); - - c(printf("Going to next cursor for keyid %08x\n", p->keyid)); - - g_free(p->current); - p->current = NULL; - - while ( (p->keyid = camel_key_table_next(p->table, p->keyid, &p->current, &p->flags, &p->data)) ) { - if ((p->flags & 1) == 0) { - return p->current; - } else { - g_free(p->current); - p->current = NULL; - } - } - - return NULL; -} - -static void -text_index_key_cursor_reset(CamelIndexCursor *idc) -{ - struct _CamelTextIndexKeyCursorPrivate *p = CIKC_PRIVATE(idc); - - p->keyid = 0; - p->flags = 0; - p->data = 0; - g_free(p->current); - p->current = NULL; -} - -static void -camel_text_index_key_cursor_class_init(CamelTextIndexKeyCursorClass *klass) -{ - CamelIndexCursorClass *cklass = (CamelIndexCursorClass *)klass; - - camel_text_index_key_cursor_parent = CAMEL_INDEX_CURSOR_CLASS(camel_type_get_global_classfuncs(camel_index_cursor_get_type())); - - cklass->next = text_index_key_cursor_next; - cklass->reset = text_index_key_cursor_reset; -} - -static void -camel_text_index_key_cursor_init(CamelTextIndexKeyCursor *idc) -{ - struct _CamelTextIndexKeyCursorPrivate *p; - - p = idc->priv = g_malloc0(sizeof(struct _CamelTextIndexKeyCursorPrivate)); - p->keyid = 0; - p->flags = 0; - p->data = 0; - p->current = NULL; -} - -static void -camel_text_index_key_cursor_finalise(CamelTextIndexKeyCursor *idc) -{ - struct _CamelTextIndexKeyCursorPrivate *p = CIKC_PRIVATE(idc); - - g_free(p->current); - if (p->table) - camel_object_unref((CamelObject *)p->table); - g_free(p); -} - -CamelType -camel_text_index_key_cursor_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_index_cursor_get_type(), "CamelTextIndexKeyCursor", - sizeof (CamelTextIndexKeyCursor), - sizeof (CamelTextIndexKeyCursorClass), - (CamelObjectClassInitFunc) camel_text_index_key_cursor_class_init, - NULL, - (CamelObjectInitFunc) camel_text_index_key_cursor_init, - (CamelObjectFinalizeFunc) camel_text_index_key_cursor_finalise); - } - - return type; -} - -CamelTextIndexKeyCursor * -camel_text_index_key_cursor_new(CamelTextIndex *idx, CamelKeyTable *table) -{ - CamelTextIndexKeyCursor *idc = (CamelTextIndexKeyCursor *)camel_object_new(camel_text_index_key_cursor_get_type()); - CamelIndexCursor *cic = &idc->parent; - struct _CamelTextIndexKeyCursorPrivate *p = CIKC_PRIVATE(idc); - - cic->index = (CamelIndex *)idx; - camel_object_ref((CamelObject *)idx); - p->table = table; - camel_object_ref((CamelObject *)table); - - return idc; -} - -/* ********************************************************************** */ - -#define m(x) - -#if 0 - -struct _CamelIndexRoot { - struct _CamelBlockRoot root; - - camel_block_t word_root; /* a keyindex containing the keyid -> word mapping */ - camel_block_t word_hash_root; /* a partitionindex containing word -> keyid mapping */ - - camel_block_t name_root; /* same, for names */ - camel_block_t name_hash_root; -}; - -char wordbuffer[] = "This is a buffer of multiple words. Some of the words are duplicates" -" while other words are the same, some are in difFerenT Different different case cAsE casE," -" with,with:with;with-with'with\"'\"various punctuation as well. So much for those Words. and 10" -" numbers in a row too 1,2,3,4,5,6,7,8,9,10! Yay!."; - -int main(int argc, char **argv) -{ -#if 0 - CamelBlockFile *bs; - CamelKeyTable *ki; - CamelPartitionTable *cpi; - CamelBlock *keyroot, *partroot; - struct _CamelIndexRoot *root; - FILE *fp; - char line[256], *key; - camel_key_t keyid; - int index = 0, flags, data; -#endif - CamelIndex *idx; - CamelIndexName *idn; - CamelIndexCursor *idc; - const char *word; - int i; - - printf("Camel text index tester!\n"); - - g_thread_init(NULL); - camel_init(NULL, 0); - - idx = (CamelIndex *)camel_text_index_new("textindex", O_CREAT|O_RDWR|O_TRUNC); - - -#if 1 - camel_index_compress(idx); - - return 0; -#endif - - for (i=0;i<100;i++) { - char name[16]; - - sprintf(name, "%d", i); - printf("Adding words to name '%s'\n", name); - idn = camel_index_add_name(idx, name); - camel_index_name_add_buffer(idn, wordbuffer, sizeof(wordbuffer)-1); - camel_index_write_name(idx, idn); - camel_object_unref((CamelObject *)idn); - } - - printf("Looking up which names contain word 'word'\n"); - idc = camel_index_find(idx, "words"); - while ( (word = camel_index_cursor_next(idc)) != NULL ) { - printf(" name is '%s'\n", word); - } - camel_object_unref((CamelObject *)idc); - printf("done.\n"); - - printf("Looking up which names contain word 'truncate'\n"); - idc = camel_index_find(idx, "truncate"); - while ( (word = camel_index_cursor_next(idc)) != NULL ) { - printf(" name is '%s'\n", word); - } - camel_object_unref((CamelObject *)idc); - printf("done.\n"); - - camel_index_sync(idx); - camel_object_unref((CamelObject *)idx); - -#if 0 - bs = camel_block_file_new("blocks", "TESTINDX", CAMEL_BLOCK_SIZE); - - root = (struct _CamelIndexRoot *)bs->root; - if (root->word_root == 0) { - keyroot = camel_block_file_new_block(bs); - root->word_root = keyroot->id; - camel_block_file_touch_block(bs, bs->root_block); - } - if (root->word_hash_root == 0) { - partroot = camel_block_file_new_block(bs); - root->word_hash_root = partroot->id; - camel_block_file_touch_block(bs, bs->root_block); - } - - ki = camel_key_table_new(bs, root->word_root); - cpi = camel_partition_table_new(bs, root->word_hash_root); - - fp = fopen("/usr/dict/words", "r"); - if (fp == NULL) { - perror("fopen"); - return 1; - } - - while (fgets(line, sizeof(line), fp) != NULL) { - line[strlen(line)-1] = 0; - - /* see if its already there */ - keyid = camel_partition_table_lookup(cpi, line); - if (keyid == 0) { - m(printf("Adding word '%s' %d\n", line, index)); - - keyid = camel_key_table_add(ki, line, index, 0); - m(printf(" key = %08x\n", keyid)); - - camel_partition_table_add(cpi, line, keyid); - - m(printf("Lookup word '%s'\n", line)); - keyid = camel_partition_table_lookup(cpi, line); - m(printf(" key = %08x\n", keyid)); - } - - m(printf("Lookup key %08x\n", keyid)); - - camel_key_table_set_flags(ki, keyid, index, 1); - - data = camel_key_table_lookup(ki, keyid, &key, &flags); - m(printf(" word = '%s' %d %04x\n", key, data, flags)); - - g_assert(data == index && strcmp(key, line) == 0); - - g_free(key); - - index++; - } - - printf("Scanning again\n"); - fseek(fp, SEEK_SET, 0); - index = 0; - while (fgets(line, sizeof(line), fp) != NULL) { - line[strlen(line)-1] = 0; - m(printf("Lookup word '%s' %d\n", line, index)); - keyid = camel_partition_table_lookup(cpi, line); - m(printf(" key = %08d\n", keyid)); - - m(printf("Lookup key %08x\n", keyid)); - data = camel_key_table_lookup(ki, keyid, &key, &flags); - m(printf(" word = '%s' %d\n", key, data)); - - g_assert(data == index && strcmp(key, line) == 0); - - g_free(key); - - index++; - } - - printf("Freeing partition index\n"); - camel_partition_table_free(cpi); - - printf("Syncing block file\n"); - camel_block_file_sync(bs); -#endif - return 0; -} - -#endif diff --git a/camel/camel-text-index.h b/camel/camel-text-index.h deleted file mode 100644 index fd9e6aa116..0000000000 --- a/camel/camel-text-index.h +++ /dev/null @@ -1,114 +0,0 @@ - -/* - * Copyright (C) 2001 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_TEXT_INDEX_H -#define _CAMEL_TEXT_INDEX_H - -#include -#include -#include "camel-index.h" - -#define CAMEL_TEXT_INDEX(obj) CAMEL_CHECK_CAST (obj, camel_text_index_get_type (), CamelTextIndex) -#define CAMEL_TEXT_INDEX_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_text_index_get_type (), CamelTextIndexClass) -#define CAMEL_IS_TEXT_INDEX(obj) CAMEL_CHECK_TYPE (obj, camel_text_index_get_type ()) - -typedef struct _CamelTextIndex CamelTextIndex; -typedef struct _CamelTextIndexClass CamelTextIndexClass; - -typedef struct _CamelTextIndexName CamelTextIndexName; -typedef struct _CamelTextIndexNameClass CamelTextIndexNameClass; - -typedef struct _CamelTextIndexCursor CamelTextIndexCursor; -typedef struct _CamelTextIndexCursorClass CamelTextIndexCursorClass; - -typedef struct _CamelTextIndexKeyCursor CamelTextIndexKeyCursor; -typedef struct _CamelTextIndexKeyCursorClass CamelTextIndexKeyCursorClass; - -typedef void (*CamelTextIndexFunc)(CamelTextIndex *idx, const char *word, char *buffer); - -/* ********************************************************************** */ - -struct _CamelTextIndexCursor { - CamelIndexCursor parent; - - struct _CamelTextIndexCursorPrivate *priv; -}; - -struct _CamelTextIndexCursorClass { - CamelIndexCursorClass parent; -}; - -CamelType camel_text_index_cursor_get_type(void); - -/* ********************************************************************** */ - -struct _CamelTextIndexKeyCursor { - CamelIndexCursor parent; - - struct _CamelTextIndexKeyCursorPrivate *priv; -}; - -struct _CamelTextIndexKeyCursorClass { - CamelIndexCursorClass parent; -}; - -CamelType camel_text_index_key_cursor_get_type(void); - -/* ********************************************************************** */ - -struct _CamelTextIndexName { - CamelIndexName parent; - - struct _CamelTextIndexNamePrivate *priv; -}; - -struct _CamelTextIndexNameClass { - CamelIndexNameClass parent; -}; - -CamelType camel_text_index_name_get_type(void); - -/* ********************************************************************** */ - -struct _CamelTextIndex { - CamelIndex parent; - - struct _CamelTextIndexPrivate *priv; -}; - -struct _CamelTextIndexClass { - CamelIndexClass parent_class; -}; - -CamelType camel_text_index_get_type (void); -CamelTextIndex *camel_text_index_new(const char *path, int flags); - -/* static utility functions */ -int camel_text_index_check(const char *path); -int camel_text_index_rename(const char *old, const char *new); -int camel_text_index_remove(const char *old); - -void camel_text_index_dump(CamelTextIndex *idx); -void camel_text_index_info(CamelTextIndex *idx); -void camel_text_index_validate(CamelTextIndex *idx); - -#endif /* ! _CAMEL_TEXT_INDEX_H */ - diff --git a/camel/camel-transport.c b/camel/camel-transport.c deleted file mode 100644 index a708b1757d..0000000000 --- a/camel/camel-transport.c +++ /dev/null @@ -1,141 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-transport.c : Abstract class for an email transport */ - -/* - * - * Author : - * Dan Winship - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "camel-transport.h" -#include "camel-address.h" -#include "camel-mime-message.h" -#include "camel-private.h" - -static CamelServiceClass *parent_class = NULL; - -/* Returns the class for a CamelTransport */ -#define CT_CLASS(so) CAMEL_TRANSPORT_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static int transport_setv (CamelObject *object, CamelException *ex, CamelArgV *args); -static int transport_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args); - - -static void -camel_transport_class_init (CamelTransportClass *camel_transport_class) -{ - CamelObjectClass *camel_object_class = CAMEL_OBJECT_CLASS (camel_transport_class); - - parent_class = CAMEL_SERVICE_CLASS (camel_type_get_global_classfuncs (camel_service_get_type ())); - - /* virtual method overload */ - camel_object_class->setv = transport_setv; - camel_object_class->getv = transport_getv; -} - -static void -camel_transport_init (gpointer object, gpointer klass) -{ - CamelTransport *xport = object; - - xport->priv = g_malloc0 (sizeof (struct _CamelTransportPrivate)); - xport->priv->send_lock = g_mutex_new (); -} - -static void -camel_transport_finalize (CamelObject *object) -{ - CamelTransport *xport = CAMEL_TRANSPORT (object); - - g_mutex_free (xport->priv->send_lock); - g_free (xport->priv); -} - -CamelType -camel_transport_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (CAMEL_SERVICE_TYPE, - "CamelTransport", - sizeof (CamelTransport), - sizeof (CamelTransportClass), - (CamelObjectClassInitFunc) camel_transport_class_init, - NULL, - (CamelObjectInitFunc) camel_transport_init, - (CamelObjectFinalizeFunc) camel_transport_finalize); - } - - return type; -} - - -static int -transport_setv (CamelObject *object, CamelException *ex, CamelArgV *args) -{ - /* CamelTransport doesn't currently have anything to set */ - return CAMEL_OBJECT_CLASS (parent_class)->setv (object, ex, args); -} - -static int -transport_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args) -{ - /* CamelTransport doesn't currently have anything to get */ - return CAMEL_OBJECT_CLASS (parent_class)->getv (object, ex, args); -} - - -/** - * camel_transport_send_to: - * @transport: the transport - * @message: the message - * @from: from address - * @recipients: the recipients - * @ex: a CamelException - * - * Sends the message to the given recipients, regardless of the contents - * of @message. If the message contains a "Bcc" header, the transport - * is responsible for stripping it. - * - * Return value: success or failure. - **/ -gboolean -camel_transport_send_to (CamelTransport *transport, CamelMimeMessage *message, - CamelAddress *from, CamelAddress *recipients, - CamelException *ex) -{ - gboolean sent; - - g_return_val_if_fail (CAMEL_IS_TRANSPORT (transport), FALSE); - g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE); - g_return_val_if_fail (CAMEL_IS_ADDRESS (from), FALSE); - g_return_val_if_fail (CAMEL_IS_ADDRESS (recipients), FALSE); - - CAMEL_TRANSPORT_LOCK (transport, send_lock); - sent = CT_CLASS (transport)->send_to (transport, message, - from, recipients, ex); - CAMEL_TRANSPORT_UNLOCK (transport, send_lock); - - return sent; -} diff --git a/camel/camel-transport.h b/camel/camel-transport.h deleted file mode 100644 index d2c1e5b72c..0000000000 --- a/camel/camel-transport.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-transport.h : Abstract class for an email transport */ - -/* - * - * Author : - * Dan Winship - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_TRANSPORT_H -#define CAMEL_TRANSPORT_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include - -#define CAMEL_TRANSPORT_TYPE (camel_transport_get_type ()) -#define CAMEL_TRANSPORT(obj) (CAMEL_CHECK_CAST((obj), CAMEL_TRANSPORT_TYPE, CamelTransport)) -#define CAMEL_TRANSPORT_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_TRANSPORT_TYPE, CamelTransportClass)) -#define CAMEL_IS_TRANSPORT(o) (CAMEL_CHECK_TYPE((o), CAMEL_TRANSPORT_TYPE)) - - -enum { - CAMEL_TRANSPORT_ARG_FIRST = CAMEL_SERVICE_ARG_FIRST + 100, -}; - -struct _CamelTransport -{ - CamelService parent_object; - - struct _CamelTransportPrivate *priv; -}; - - - -typedef struct { - CamelServiceClass parent_class; - - gboolean (*send_to) (CamelTransport *transport, - CamelMimeMessage *message, - CamelAddress *from, CamelAddress *recipients, - CamelException *ex); -} CamelTransportClass; - - -/* public methods */ -gboolean camel_transport_send_to (CamelTransport *transport, - CamelMimeMessage *message, - CamelAddress *from, - CamelAddress *recipients, - CamelException *ex); - -/* Standard Camel function */ -CamelType camel_transport_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_TRANSPORT_H */ diff --git a/camel/camel-types.h b/camel/camel-types.h deleted file mode 100644 index 8345bbf206..0000000000 --- a/camel/camel-types.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_TYPES_H -#define CAMEL_TYPES_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -typedef struct _CamelAddress CamelAddress; -typedef struct _CamelDigestFolder CamelDigestFolder; -typedef struct _CamelDigestStore CamelDigestStore; -typedef struct _CamelDiscoDiary CamelDiscoDiary; -typedef struct _CamelDiscoFolder CamelDiscoFolder; -typedef struct _CamelDiscoStore CamelDiscoStore; -typedef struct _CamelDataWrapper CamelDataWrapper; -typedef struct _CamelException CamelException; -typedef struct _CamelFilterDriver CamelFilterDriver; -typedef struct _CamelFolder CamelFolder; -typedef struct _CamelFolderSearch CamelFolderSearch; -typedef struct _CamelFolderSummary CamelFolderSummary; -typedef struct _CamelInternetAddress CamelInternetAddress; -typedef struct _CamelMedium CamelMedium; -typedef struct _CamelMessageContentInfo CamelMessageContentInfo; -typedef struct _CamelMessageInfo CamelMessageInfo; -typedef struct _CamelMimeFilter CamelMimeFilter; -typedef struct _CamelMimeFilterBasic CamelMimeFilterBasic; -typedef struct _CamelMimeFilterBestenc CamelMimeFilterBestenc; -typedef struct _CamelMimeFilterCharset CamelMimeFilterCharset; -typedef struct _CamelMimeFilterChomp CamelMimeFilterChomp; -typedef struct _CamelMimeFilterIndex CamelMimeFilterIndex; -typedef struct _CamelMimeFilterLinewrap CamelMimeFilterLinewrap; -typedef struct _CamelMimeFilterSave CamelMimeFilterSave; -typedef struct _CamelMimeFilterCRLF CamelMimeFilterCRLF; -typedef struct _CamelMimeMessage CamelMimeMessage; -typedef struct _CamelMimeParser CamelMimeParser; -typedef struct _CamelMimePart CamelMimePart; -typedef struct _CamelMultipart CamelMultipart; -typedef struct _CamelNewsAddress CamelNewsAddress; -typedef struct _CamelSeekableStream CamelSeekableStream; -typedef struct _CamelSeekableSubstream CamelSeekableSubstream; -typedef struct _CamelService CamelService; -typedef struct _CamelSession CamelSession; -typedef struct _CamelSimpleDataWrapper CamelSimpleDataWrapper; -typedef struct _CamelStore CamelStore; -typedef struct _CamelStream CamelStream; -typedef struct _CamelStreamNull CamelStreamNull; -typedef struct _CamelStreamBuffer CamelStreamBuffer; -typedef struct _CamelStreamDataWrapper CamelStreamDataWrapper; -typedef struct _CamelStreamFilter CamelStreamFilter; -typedef struct _CamelStreamFs CamelStreamFs; -typedef struct _CamelStreamMem CamelStreamMem; -typedef struct _CamelTcpStream CamelTcpStream; -typedef struct _CamelTcpStreamRaw CamelTcpStreamRaw; -typedef struct _CamelTcpStreamSSL CamelTcpStreamSSL; -typedef struct _CamelTcpStreamOpenSSL CamelTcpStreamOpenSSL; -typedef struct _CamelHttpStream CamelHttpStream; -typedef struct _CamelTransport CamelTransport; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_TYPES_H */ diff --git a/camel/camel-uid-cache.c b/camel/camel-uid-cache.c deleted file mode 100644 index 2a2a52daeb..0000000000 --- a/camel/camel-uid-cache.c +++ /dev/null @@ -1,334 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-uid-cache.c: UID caching code. */ - -/* - * Authors: - * Dan Winship - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "camel-uid-cache.h" -#include "camel-file-utils.h" - -struct _uid_state { - int level; - gboolean save; -}; - - -/** - * camel_uid_cache_new: - * @filename: path to load the cache from - * - * Creates a new UID cache, initialized from @filename. If @filename - * doesn't already exist, the UID cache will be empty. Otherwise, if - * it does exist but can't be read, the function will return %NULL. - * - * Return value: a new UID cache, or %NULL - **/ -CamelUIDCache * -camel_uid_cache_new (const char *filename) -{ - CamelUIDCache *cache; - struct stat st; - char *dirname, *buf, **uids; - int fd, i; - - dirname = g_path_get_dirname (filename); - if (camel_mkdir (dirname, 0777) == -1) { - g_free (dirname); - return NULL; - } - - g_free (dirname); - - if ((fd = open (filename, O_RDONLY | O_CREAT, 0666)) == -1) - return NULL; - - if (fstat (fd, &st) == -1) { - close (fd); - return NULL; - } - - buf = g_malloc (st.st_size + 1); - - if (st.st_size > 0 && camel_read (fd, buf, st.st_size) == -1) { - close (fd); - g_free (buf); - return NULL; - } - - buf[st.st_size] = '\0'; - - close (fd); - - cache = g_new (CamelUIDCache, 1); - cache->uids = g_hash_table_new (g_str_hash, g_str_equal); - cache->filename = g_strdup (filename); - cache->level = 1; - cache->expired = 0; - cache->size = 0; - cache->fd = -1; - - uids = g_strsplit (buf, "\n", 0); - g_free (buf); - for (i = 0; uids[i]; i++) { - struct _uid_state *state; - - state = g_new (struct _uid_state, 1); - state->level = cache->level; - state->save = TRUE; - - g_hash_table_insert (cache->uids, uids[i], state); - } - - g_free (uids); - - return cache; -} - - -static void -maybe_write_uid (gpointer key, gpointer value, gpointer data) -{ - CamelUIDCache *cache = data; - struct _uid_state *state = value; - - if (cache->fd == -1) - return; - - if (state && state->level == cache->level && state->save) { - if (camel_write (cache->fd, key, strlen (key)) == -1 || - camel_write (cache->fd, "\n", 1) == -1) { - cache->fd = -1; - } else { - cache->size += strlen (key) + 1; - } - } else { - /* keep track of how much space the expired uids would - * have taken up in the cache */ - cache->expired += strlen (key) + 1; - } -} - - -/** - * camel_uid_cache_save: - * @cache: a CamelUIDCache - * - * Attempts to save @cache back to disk. - * - * Return value: success or failure - **/ -gboolean -camel_uid_cache_save (CamelUIDCache *cache) -{ - char *filename; - int errnosav; - int fd; - - filename = g_strdup_printf ("%s~", cache->filename); - if ((fd = open (filename, O_WRONLY | O_CREAT | O_EXCL, 0666)) == -1) { - g_free (filename); - return FALSE; - } - - cache->fd = fd; - cache->size = 0; - cache->expired = 0; - g_hash_table_foreach (cache->uids, maybe_write_uid, cache); - - if (cache->fd == -1) - goto exception; - - if (fsync (fd) == -1) - goto exception; - - close (fd); - fd = -1; - - if (rename (filename, cache->filename) == -1) - goto exception; - - g_free (filename); - - return TRUE; - - exception: - - errnosav = errno; - -#ifdef ENABLE_SPASMOLYTIC - if (fd != -1) { - /** - * If our new cache size is larger than the old cache, - * even if we haven't finished writing it out - * successfully, we should still attempt to replace - * the old cache with the new cache because it will at - * least avoid re-downloading a few extra messages - * than if we just kept the old cache. - * - * Similarly, even if the new cache size is smaller - * than the old cache size, but we've expired enough - * uids to make up for the difference in size (or - * more), then we should replace the old cache with - * the new cache as well. - **/ - - if (stat (cache->filename, &st) == 0 && - (cache->size > st.st_size || cache->size + cache->expired > st.st_size)) { - if (ftruncate (fd, (off_t) cache->size) != -1) { - cache->size = 0; - cache->expired = 0; - goto overwrite; - } - } - - close (fd); - } -#endif - - unlink (filename); - g_free (filename); - - errno = errnosav; - - return FALSE; -} - - -static void -free_uid (gpointer key, gpointer value, gpointer data) -{ - g_free (key); - g_free (value); -} - - -/** - * camel_uid_cache_destroy: - * @cache: a CamelUIDCache - * - * Destroys @cache and frees its data. - **/ -void -camel_uid_cache_destroy (CamelUIDCache *cache) -{ - g_hash_table_foreach (cache->uids, free_uid, NULL); - g_hash_table_destroy (cache->uids); - g_free (cache->filename); - g_free (cache); -} - - -/** - * camel_uid_cache_get_new_uids: - * @cache: a CamelUIDCache - * @uids: an array of UIDs - * - * Returns an array of UIDs from @uids that are not in @cache, and - * removes UIDs from @cache that aren't in @uids. - * - * Return value: an array of new UIDs, which must be freed with - * camel_uid_cache_free_uids(). - **/ -GPtrArray * -camel_uid_cache_get_new_uids (CamelUIDCache *cache, GPtrArray *uids) -{ - GPtrArray *new_uids; - gpointer old_uid; - char *uid; - int i; - - new_uids = g_ptr_array_new (); - cache->level++; - - for (i = 0; i < uids->len; i++) { - struct _uid_state *state; - - uid = uids->pdata[i]; - if (g_hash_table_lookup_extended (cache->uids, uid, (void **)&old_uid, (void **)&state)) { - g_hash_table_remove (cache->uids, uid); - g_free (old_uid); - } else { - g_ptr_array_add (new_uids, g_strdup (uid)); - state = g_new (struct _uid_state, 1); - state->save = FALSE; - } - - state->level = cache->level; - g_hash_table_insert (cache->uids, g_strdup (uid), state); - } - - return new_uids; -} - - -/** - * camel_uid_cache_save_uid: - * @cache: a CamelUIDCache - * @uid: a uid to save - * - * Marks a uid for saving. - **/ -void -camel_uid_cache_save_uid (CamelUIDCache *cache, const char *uid) -{ - struct _uid_state *state; - gpointer old_uid; - - g_return_if_fail (uid != NULL); - - if (g_hash_table_lookup_extended (cache->uids, uid, (void **)&old_uid, (void **)&state)) { - state->save = TRUE; - state->level = cache->level; - } else { - state = g_new (struct _uid_state, 1); - state->save = TRUE; - state->level = cache->level; - - g_hash_table_insert (cache->uids, g_strdup (uid), state); - } -} - - -/** - * camel_uid_cache_free_uids: - * @uids: an array returned from camel_uid_cache_get_new_uids() - * - * Frees the array of UIDs. - **/ -void -camel_uid_cache_free_uids (GPtrArray *uids) -{ - int i; - - for (i = 0; i < uids->len; i++) - g_free (uids->pdata[i]); - g_ptr_array_free (uids, TRUE); -} diff --git a/camel/camel-uid-cache.h b/camel/camel-uid-cache.h deleted file mode 100644 index 37d90c89e6..0000000000 --- a/camel/camel-uid-cache.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-uid-cache.h: UID caching code. */ - -/* - * Authors: - * Bertrand Guiheneuf - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_UID_CACHE_H -#define CAMEL_UID_CACHE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include - -#include -#include - -typedef struct { - char *filename; - GHashTable *uids; - unsigned int level; - size_t expired; - size_t size; - int fd; -} CamelUIDCache; - -CamelUIDCache *camel_uid_cache_new (const char *filename); -gboolean camel_uid_cache_save (CamelUIDCache *cache); -void camel_uid_cache_destroy (CamelUIDCache *cache); - -GPtrArray *camel_uid_cache_get_new_uids (CamelUIDCache *cache, GPtrArray *uids); - -void camel_uid_cache_save_uid (CamelUIDCache *cache, const char *uid); -void camel_uid_cache_free_uids (GPtrArray *uids); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_UID_CACHE_H */ diff --git a/camel/camel-url-scanner.c b/camel/camel-url-scanner.c deleted file mode 100644 index 8a43b05aee..0000000000 --- a/camel/camel-url-scanner.c +++ /dev/null @@ -1,450 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "e-util/e-trie.h" -#include "camel-url-scanner.h" - - -struct _CamelUrlScanner { - GPtrArray *patterns; - ETrie *trie; -}; - - -CamelUrlScanner * -camel_url_scanner_new (void) -{ - CamelUrlScanner *scanner; - - scanner = g_new (CamelUrlScanner, 1); - scanner->patterns = g_ptr_array_new (); - scanner->trie = e_trie_new (TRUE); - - return scanner; -} - - -void -camel_url_scanner_free (CamelUrlScanner *scanner) -{ - g_return_if_fail (scanner != NULL); - - g_ptr_array_free (scanner->patterns, TRUE); - e_trie_free (scanner->trie); - g_free (scanner); -} - - -void -camel_url_scanner_add (CamelUrlScanner *scanner, urlpattern_t *pattern) -{ - g_return_if_fail (scanner != NULL); - - e_trie_add (scanner->trie, pattern->pattern, scanner->patterns->len); - g_ptr_array_add (scanner->patterns, pattern); -} - - -gboolean -camel_url_scanner_scan (CamelUrlScanner *scanner, const char *in, size_t inlen, urlmatch_t *match) -{ - const char *pos, *inend; - urlpattern_t *pat; - int pattern; - - g_return_val_if_fail (scanner != NULL, FALSE); - g_return_val_if_fail (in != NULL, FALSE); - - if (!(pos = e_trie_search (scanner->trie, in, inlen, &pattern))) - return FALSE; - - pat = g_ptr_array_index (scanner->patterns, pattern); - - match->pattern = pat->pattern; - match->prefix = pat->prefix; - - inend = in + inlen; - if (!pat->start (in, pos, inend, match)) - return FALSE; - - if (!pat->end (in, pos, inend, match)) - return FALSE; - - return TRUE; -} - - -static unsigned char url_scanner_table[256] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 1, 1, 9, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 24,128,160,128,128,128,128,128,160,160,128,128,160,192,160,160, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,160,160, 32,128, 32,128, - 160, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, - 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,160,160,160,128,128, - 128, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, - 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,128,128,128,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, 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, 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 -}; - -enum { - IS_CTRL = (1 << 0), - IS_ALPHA = (1 << 1), - IS_DIGIT = (1 << 2), - IS_LWSP = (1 << 3), - IS_SPACE = (1 << 4), - IS_SPECIAL = (1 << 5), - IS_DOMAIN = (1 << 6), - IS_URLSAFE = (1 << 7), -}; - -#define is_ctrl(x) ((url_scanner_table[(unsigned char)(x)] & IS_CTRL) != 0) -#define is_lwsp(x) ((url_scanner_table[(unsigned char)(x)] & IS_LWSP) != 0) -#define is_atom(x) ((url_scanner_table[(unsigned char)(x)] & (IS_SPECIAL|IS_SPACE|IS_CTRL)) == 0) -#define is_alpha(x) ((url_scanner_table[(unsigned char)(x)] & IS_ALPHA) != 0) -#define is_digit(x) ((url_scanner_table[(unsigned char)(x)] & IS_DIGIT) != 0) -#define is_domain(x) ((url_scanner_table[(unsigned char)(x)] & IS_DOMAIN) != 0) -#define is_urlsafe(x) ((url_scanner_table[(unsigned char)(x)] & (IS_ALPHA|IS_DIGIT|IS_URLSAFE)) != 0) - - -gboolean -camel_url_addrspec_start (const char *in, const char *pos, const char *inend, urlmatch_t *match) -{ - register const char *inptr = pos; - - g_assert (*inptr == '@'); - - inptr--; - - while (inptr > in) { - if (is_atom (*inptr)) - inptr--; - else - break; - - while (inptr > in && is_atom (*inptr)) - inptr--; - - if (inptr > in && *inptr == '.') - inptr--; - } - - if (!is_atom (*inptr)) - inptr++; - - if (inptr == pos) - return FALSE; - - match->um_so = (inptr - in); - - return TRUE; -} - -gboolean -camel_url_addrspec_end (const char *in, const char *pos, const char *inend, urlmatch_t *match) -{ - const char *inptr = pos; - int parts = 0, digits; - - g_assert (*inptr == '@'); - - inptr++; - - if (*inptr == '[') { - /* domain literal */ - do { - inptr++; - - digits = 0; - while (inptr < inend && is_digit (*inptr) && digits < 3) { - inptr++; - digits++; - } - - parts++; - - if (*inptr != '.' && parts != 4) - return FALSE; - } while (parts < 4); - - if (*inptr == ']') - inptr++; - else - return FALSE; - } else { - while (inptr < inend) { - if (is_domain (*inptr)) - inptr++; - else - break; - - while (inptr < inend && is_domain (*inptr)) - inptr++; - - if (inptr < inend && *inptr == '.' && is_domain (inptr[1])) - inptr++; - } - } - - if (inptr == pos + 1) - return FALSE; - - match->um_eo = (inptr - in); - - return TRUE; -} - -static struct { - char open; - char close; -} url_braces[] = { - { '(', ')' }, - { '{', '}' }, - { '[', ']' }, - { '<', '>' }, -}; - -static char -url_stop_at_brace (const char *in, size_t so) -{ - int i; - - if (so > 0) { - for (i = 0; i < 4; i++) { - if (in[so - 1] == url_braces[i].open) - return url_braces[i].close; - } - } - - return '\0'; -} - -gboolean -camel_url_file_start (const char *in, const char *pos, const char *inend, urlmatch_t *match) -{ - match->um_so = (pos - in); - - return TRUE; -} - -gboolean -camel_url_file_end (const char *in, const char *pos, const char *inend, urlmatch_t *match) -{ - register const char *inptr = pos; - char close_brace; - - inptr += strlen (match->pattern); - - if (*inptr == '/') - inptr++; - - close_brace = url_stop_at_brace (in, match->um_so); - - while (inptr < inend && is_urlsafe (*inptr) && *inptr != close_brace) - inptr++; - - if (inptr == pos) - return FALSE; - - match->um_eo = (inptr - in); - - return TRUE; -} - -gboolean -camel_url_web_start (const char *in, const char *pos, const char *inend, urlmatch_t *match) -{ - match->um_so = (pos - in); - - return TRUE; -} - -gboolean -camel_url_web_end (const char *in, const char *pos, const char *inend, urlmatch_t *match) -{ - register const char *inptr = pos; - int parts = 0, digits, port; - char close_brace; - - inptr += strlen (match->pattern); - - close_brace = url_stop_at_brace (in, match->um_so); - - /* find the end of the domain */ - if (is_digit (*inptr)) { - /* domain-literal */ - do { - digits = 0; - while (inptr < inend && is_digit (*inptr) && digits < 3) { - inptr++; - digits++; - } - - parts++; - - if (*inptr != '.' && parts != 4) - return FALSE; - else if (*inptr == '.') - inptr++; - - } while (parts < 4); - } else if (is_domain (*inptr)) { - while (inptr < inend) { - if (is_domain (*inptr)) - inptr++; - else - break; - - while (inptr < inend && is_domain (*inptr)) - inptr++; - - if (inptr < inend && *inptr == '.' && is_domain (inptr[1])) - inptr++; - } - } else { - return FALSE; - } - - if (inptr < inend) { - switch (*inptr) { - case ':': /* port notation */ - inptr++; - port = 0; - - while (inptr < inend && is_digit (*inptr) && port < 65536) - port = (port * 10) + (*inptr++ - '0'); - - if (port >= 65536) - inptr--; - - if (inptr >= inend || *inptr != '/') - break; - - /* we have a '/' so there could be a path - fall through */ - case '/': /* we've detected a path component to our url */ - inptr++; - - while (inptr < inend && is_urlsafe (*inptr) && *inptr != close_brace) - inptr++; - - /* urls are extremely unlikely to end with any - * punctuation, so strip any trailing - * punctuation off. Also strip off any closing - * braces. */ - while (inptr > pos && strchr (",.?!)}]", inptr[-1])) - inptr--; - - break; - default: - break; - } - } - - match->um_eo = (inptr - in); - - return TRUE; -} - - - -#ifdef BUILD_TABLE - -#include - -/* got these from rfc1738 */ -#define CHARS_LWSP " \t\n\r" /* linear whitespace chars */ -#define CHARS_SPECIAL "()<>@,;:\\\".[]" - -/* got these from rfc1738 */ -#define CHARS_URLSAFE "$-_.+!*'(),{}|\\^~[]`#%\";/?:@&=" - - -static void -table_init_bits (unsigned int mask, const unsigned char *vals) -{ - int i; - - for (i = 0; vals[i] != '\0'; i++) - url_scanner_table[vals[i]] |= mask; -} - -static void -url_scanner_table_init (void) -{ - int i; - - for (i = 0; i < 256; i++) { - url_scanner_table[i] = 0; - if (i < 32) - url_scanner_table[i] |= IS_CTRL; - if ((i >= '0' && i <= '9')) - url_scanner_table[i] |= IS_DIGIT | IS_DOMAIN; - if ((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z')) - url_scanner_table[i] |= IS_ALPHA | IS_DOMAIN; - if (i >= 127) - url_scanner_table[i] |= IS_CTRL; - } - - url_scanner_table[' '] |= IS_SPACE; - url_scanner_table['-'] |= IS_DOMAIN; - - /* not defined to be special in rfc0822, but when scanning - backwards to find the beginning of the email address we do - not want to include this char if we come accross it - so - this is kind of a hack */ - url_scanner_table['/'] |= IS_SPECIAL; - - table_init_bits (IS_LWSP, CHARS_LWSP); - table_init_bits (IS_SPECIAL, CHARS_SPECIAL); - table_init_bits (IS_URLSAFE, CHARS_URLSAFE); -} - -int main (int argc, char **argv) -{ - int i; - - url_scanner_table_init (); - - printf ("static unsigned char url_scanner_table[256] = {"); - for (i = 0; i < 256; i++) { - printf ("%s%3d%s", (i % 16) ? "" : "\n\t", - url_scanner_table[i], i != 255 ? "," : "\n"); - } - printf ("};\n\n"); - - return 0; -} - -#endif /* BUILD_TABLE */ diff --git a/camel/camel-url-scanner.h b/camel/camel-url-scanner.h deleted file mode 100644 index d464c2dbf0..0000000000 --- a/camel/camel-url-scanner.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __CAMEL_URL_SCANNER_H__ -#define __CAMEL_URL_SCANNER_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include - - -typedef struct { - const char *pattern; - const char *prefix; - off_t um_so; - off_t um_eo; -} urlmatch_t; - -typedef gboolean (*CamelUrlScanFunc) (const char *in, const char *pos, const char *inend, urlmatch_t *match); - -/* some default CamelUrlScanFunc's */ -gboolean camel_url_file_start (const char *in, const char *pos, const char *inend, urlmatch_t *match); -gboolean camel_url_file_end (const char *in, const char *pos, const char *inend, urlmatch_t *match); -gboolean camel_url_web_start (const char *in, const char *pos, const char *inend, urlmatch_t *match); -gboolean camel_url_web_end (const char *in, const char *pos, const char *inend, urlmatch_t *match); -gboolean camel_url_addrspec_start (const char *in, const char *pos, const char *inend, urlmatch_t *match); -gboolean camel_url_addrspec_end (const char *in, const char *pos, const char *inend, urlmatch_t *match); - -typedef struct { - char *pattern; - char *prefix; - CamelUrlScanFunc start; - CamelUrlScanFunc end; -} urlpattern_t; - -typedef struct _CamelUrlScanner CamelUrlScanner; - -CamelUrlScanner *camel_url_scanner_new (void); -void camel_url_scanner_free (CamelUrlScanner *scanner); - -void camel_url_scanner_add (CamelUrlScanner *scanner, urlpattern_t *pattern); - -gboolean camel_url_scanner_scan (CamelUrlScanner *scanner, const char *in, size_t inlen, urlmatch_t *match); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_URL_SCANNER_H__ */ diff --git a/camel/camel-url.c b/camel/camel-url.c deleted file mode 100644 index 86eb4fa104..0000000000 --- a/camel/camel-url.c +++ /dev/null @@ -1,584 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-url.c : utility functions to parse URLs */ - -/* - * Authors: - * Dan Winship - * Jeffrey Stedfast - * - * Copyright 1999-2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "camel-url.h" -#include "camel-exception.h" -#include "camel-mime-utils.h" -#include "camel-object.h" -#include "camel-string-utils.h" - -static void copy_param (GQuark key_id, gpointer data, gpointer user_data); -static void output_param (GQuark key_id, gpointer data, gpointer user_data); - -static void append_url_encoded (GString *str, const char *in, const char *extra_enc_chars); - -/** - * camel_url_new_with_base: - * @base: a base URL - * @url_string: the URL - * - * Parses @url_string relative to @base. - * - * Return value: a parsed CamelURL. - **/ -CamelURL * -camel_url_new_with_base (CamelURL *base, const char *url_string) -{ - CamelURL *url; - const char *end, *hash, *colon, *semi, *at, *slash, *question; - const char *p; - - url = g_new0 (CamelURL, 1); - - /* See RFC1808 for details. IF YOU CHANGE ANYTHING IN THIS - * FUNCTION, RUN tests/misc/url AFTERWARDS. - */ - - /* Find fragment. */ - end = hash = strchr (url_string, '#'); - if (hash && hash[1]) { - url->fragment = g_strdup (hash + 1); - camel_url_decode (url->fragment); - } else - end = url_string + strlen (url_string); - - /* Find protocol: initial [a-z+.-]* substring until ":" */ - p = url_string; - while (p < end && (isalnum ((unsigned char)*p) || - *p == '.' || *p == '+' || *p == '-')) - p++; - - if (p > url_string && *p == ':') { - url->protocol = g_strndup (url_string, p - url_string); - camel_strdown (url->protocol); - url_string = p + 1; - } - - if (!*url_string && !base) - return url; - - /* Check for authority */ - if (strncmp (url_string, "//", 2) == 0) { - url_string += 2; - - slash = url_string + strcspn (url_string, "/#"); - at = strchr (url_string, '@'); - if (at && at < slash) { - colon = strchr (url_string, ':'); - if (colon && colon < at) { - url->passwd = g_strndup (colon + 1, - at - colon - 1); - camel_url_decode (url->passwd); - } else { - url->passwd = NULL; - colon = at; - } - - semi = strchr(url_string, ';'); - if (semi && semi < colon && - !strncasecmp (semi, ";auth=", 6)) { - url->authmech = g_strndup (semi + 6, - colon - semi - 6); - camel_url_decode (url->authmech); - } else { - url->authmech = NULL; - semi = colon; - } - - url->user = g_strndup (url_string, semi - url_string); - camel_url_decode (url->user); - url_string = at + 1; - } else - url->user = url->passwd = url->authmech = NULL; - - /* Find host and port. */ - colon = strchr (url_string, ':'); - if (colon && colon < slash) { - url->host = g_strndup (url_string, colon - url_string); - url->port = strtoul (colon + 1, NULL, 10); - } else { - url->host = g_strndup (url_string, slash - url_string); - camel_url_decode (url->host); - url->port = 0; - } - - url_string = slash; - } - - /* Find query */ - question = memchr (url_string, '?', end - url_string); - if (question) { - if (question[1]) { - url->query = g_strndup (question + 1, - end - (question + 1)); - camel_url_decode (url->query); - } - end = question; - } - - /* Find parameters */ - semi = memchr (url_string, ';', end - url_string); - if (semi) { - if (semi[1]) { - const char *cur, *p, *eq; - char *name, *value; - - for (cur = semi + 1; cur < end; cur = p + 1) { - p = memchr (cur, ';', end - cur); - if (!p) - p = end; - eq = memchr (cur, '=', p - cur); - if (eq) { - name = g_strndup (cur, eq - cur); - value = g_strndup (eq + 1, p - (eq + 1)); - camel_url_decode (value); - } else { - name = g_strndup (cur, p - cur); - value = g_strdup (""); - } - camel_url_decode (name); - g_datalist_set_data_full (&url->params, name, - value, g_free); - g_free (name); - } - } - end = semi; - } - - if (end != url_string) { - url->path = g_strndup (url_string, end - url_string); - camel_url_decode (url->path); - } - - /* Apply base URL. Again, this is spelled out in RFC 1808. */ - if (base && !url->protocol && url->host) - url->protocol = g_strdup (base->protocol); - else if (base && !url->protocol) { - if (!url->user && !url->authmech && !url->passwd && - !url->host && !url->port && !url->path && - !url->params && !url->query && !url->fragment) - url->fragment = g_strdup (base->fragment); - - url->protocol = g_strdup (base->protocol); - url->user = g_strdup (base->user); - url->authmech = g_strdup (base->authmech); - url->passwd = g_strdup (base->passwd); - url->host = g_strdup (base->host); - url->port = base->port; - - if (!url->path) { - url->path = g_strdup (base->path); - if (!url->params) { - g_datalist_foreach (&base->params, copy_param, - &url->params); - if (!url->query) - url->query = g_strdup (base->query); - } - } else if (*url->path != '/') { - char *newpath, *last, *p, *q; - - last = strrchr (base->path, '/'); - if (last) { - newpath = g_strdup_printf ("%.*s/%s", - last - base->path, - base->path, - url->path); - } else - newpath = g_strdup_printf ("/%s", url->path); - - /* Remove "./" where "." is a complete segment. */ - for (p = newpath + 1; *p; ) { - if (*(p - 1) == '/' && - *p == '.' && *(p + 1) == '/') - memmove (p, p + 2, strlen (p + 2) + 1); - else - p++; - } - /* Remove "." at end. */ - if (p > newpath + 2 && - *(p - 1) == '.' && *(p - 2) == '/') - *(p - 1) = '\0'; - /* Remove "/../" where != ".." */ - for (p = newpath + 1; *p; ) { - if (!strncmp (p, "../", 3)) { - p += 3; - continue; - } - q = strchr (p + 1, '/'); - if (!q) - break; - if (strncmp (q, "/../", 4) != 0) { - p = q + 1; - continue; - } - memmove (p, q + 4, strlen (q + 4) + 1); - p = newpath + 1; - } - /* Remove "/.." at end */ - q = strrchr (newpath, '/'); - if (q && !strcmp (q, "/..")) { - p = q - 1; - while (p > newpath && *p != '/') - p--; - if (strncmp (p, "/../", 4) != 0) - *(p + 1) = 0; - } - g_free (url->path); - url->path = newpath; - } - } - - return url; -} - -static void -copy_param (GQuark key_id, gpointer data, gpointer user_data) -{ - GData **copy = user_data; - - g_datalist_id_set_data_full (copy, key_id, g_strdup (data), g_free); -} - -/** - * camel_url_new: - * @url_string: a URL - * @ex: a CamelException - * - * Parses an absolute URL. - * - * Return value: a CamelURL, or %NULL. - **/ -CamelURL * -camel_url_new (const char *url_string, CamelException *ex) -{ - CamelURL *url = camel_url_new_with_base (NULL, url_string); - - if (!url->protocol) { - camel_url_free (url); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID, - _("Could not parse URL `%s'"), - url_string); - return NULL; - } - return url; -} - -/** - * camel_url_to_string: - * @url: a CamelURL - * @flags: additional translation options. - * - * Return value: a string representing @url, which the caller must free. - **/ -char * -camel_url_to_string (CamelURL *url, guint32 flags) -{ - GString *str; - char *return_result; - - /* IF YOU CHANGE ANYTHING IN THIS FUNCTION, RUN - * tests/misc/url AFTERWARD. - */ - - str = g_string_sized_new (20); - - if (url->protocol) - g_string_append_printf (str, "%s:", url->protocol); - - if (url->host) { - g_string_append (str, "//"); - if (url->user) { - append_url_encoded (str, url->user, ":;@/"); - if (url->authmech && *url->authmech) { - g_string_append (str, ";auth="); - append_url_encoded (str, url->authmech, ":@/"); - } - if (url->passwd && !(flags & CAMEL_URL_HIDE_PASSWORD)) { - g_string_append_c (str, ':'); - append_url_encoded (str, url->passwd, "@/"); - } - g_string_append_c (str, '@'); - } - append_url_encoded (str, url->host, ":/"); - if (url->port) - g_string_append_printf (str, ":%d", url->port); - if (!url->path && (url->params || url->query || url->fragment)) - g_string_append_c (str, '/'); - } - - if (url->path) - append_url_encoded (str, url->path, ";?"); - if (url->params && !(flags & CAMEL_URL_HIDE_PARAMS)) - g_datalist_foreach (&url->params, output_param, str); - if (url->query) { - g_string_append_c (str, '?'); - append_url_encoded (str, url->query, NULL); - } - if (url->fragment) { - g_string_append_c (str, '#'); - append_url_encoded (str, url->fragment, NULL); - } - - return_result = str->str; - g_string_free (str, FALSE); - - return return_result; -} - -static void -output_param (GQuark key_id, gpointer data, gpointer user_data) -{ - GString *str = user_data; - - g_string_append_c (str, ';'); - append_url_encoded (str, g_quark_to_string (key_id), "?="); - if (*(char *)data) { - g_string_append_c (str, '='); - append_url_encoded (str, data, "?"); - } -} - -/** - * camel_url_free: - * @url: a CamelURL - * - * Frees @url - **/ -void -camel_url_free (CamelURL *url) -{ - if (url) { - g_free (url->protocol); - g_free (url->user); - g_free (url->authmech); - g_free (url->passwd); - g_free (url->host); - g_free (url->path); - g_datalist_clear (&url->params); - g_free (url->query); - g_free (url->fragment); - - g_free (url); - } -} - - -#define DEFINE_CAMEL_URL_SET(part) \ -void \ -camel_url_set_##part (CamelURL *url, const char *part) \ -{ \ - g_free (url->part); \ - url->part = g_strdup (part); \ -} - -DEFINE_CAMEL_URL_SET (protocol) -DEFINE_CAMEL_URL_SET (user) -DEFINE_CAMEL_URL_SET (authmech) -DEFINE_CAMEL_URL_SET (passwd) -DEFINE_CAMEL_URL_SET (host) -DEFINE_CAMEL_URL_SET (path) -DEFINE_CAMEL_URL_SET (query) -DEFINE_CAMEL_URL_SET (fragment) - -void -camel_url_set_port (CamelURL *url, int port) -{ - url->port = port; -} - -void -camel_url_set_param (CamelURL *url, const char *name, const char *value) -{ - g_datalist_set_data_full (&url->params, name, value ? g_strdup (value) : NULL, g_free); -} - -const char * -camel_url_get_param (CamelURL *url, const char *name) -{ - return g_datalist_get_data (&url->params, name); -} - -/* From RFC 2396 2.4.3, the characters that should always be encoded */ -static const char url_encoded_char[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x00 - 0x0f */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x10 - 0x1f */ - 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ' ' - '/' */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* '0' - '?' */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* '@' - 'O' */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 'P' - '_' */ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* '`' - 'o' */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 'p' - 0x7f */ - 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, 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, 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 -}; - -static void -append_url_encoded (GString *str, const char *in, const char *extra_enc_chars) -{ - const unsigned char *s = (const unsigned char *)in; - - while (*s) { - if (url_encoded_char[*s] || - (extra_enc_chars && strchr (extra_enc_chars, *s))) - g_string_append_printf (str, "%%%02x", (int)*s++); - else - g_string_append_c (str, *s++); - } -} - -/** - * camel_url_encode: - * @part: a URL part - * @escape_extra: additional characters beyond " \"%#<>{}|\^[]`" - * to escape (or %NULL) - * - * This %-encodes the given URL part and returns the escaped version - * in allocated memory, which the caller must free when it is done. - **/ -char * -camel_url_encode (const char *part, const char *escape_extra) -{ - GString *str; - char *encoded; - - str = g_string_new (NULL); - append_url_encoded (str, part, escape_extra); - encoded = str->str; - g_string_free (str, FALSE); - - return encoded; -} - -/** - * camel_url_decode: - * @part: a URL part - * - * %-decodes the passed-in URL *in place*. The decoded version is - * never longer than the encoded version, so there does not need to - * be any additional space at the end of the string. - */ -void -camel_url_decode (char *part) -{ - unsigned char *s, *d; - -#define XDIGIT(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - 'A' + 10) - - s = d = (unsigned char *)part; - do { - if (*s == '%' && isxdigit(s[1]) && isxdigit(s[2])) { - *d++ = (XDIGIT (s[1]) << 4) + XDIGIT (s[2]); - s += 2; - } else - *d++ = *s; - } while (*s++); -} - - -guint -camel_url_hash (const void *v) -{ - const CamelURL *u = v; - guint hash = 0; - -#define ADD_HASH(s) if (s) hash ^= g_str_hash (s); - - ADD_HASH (u->protocol); - ADD_HASH (u->user); - ADD_HASH (u->authmech); - ADD_HASH (u->host); - ADD_HASH (u->path); - ADD_HASH (u->query); - hash ^= u->port; - - return hash; -} - -static int -check_equal (char *s1, char *s2) -{ - if (s1 == NULL) { - if (s2 == NULL) - return TRUE; - else - return FALSE; - } - - if (s2 == NULL) - return FALSE; - - return strcmp (s1, s2) == 0; -} - -int -camel_url_equal(const void *v, const void *v2) -{ - const CamelURL *u1 = v, *u2 = v2; - - return check_equal(u1->protocol, u2->protocol) - && check_equal(u1->user, u2->user) - && check_equal(u1->authmech, u2->authmech) - && check_equal(u1->host, u2->host) - && check_equal(u1->path, u2->path) - && check_equal(u1->query, u2->query) - && u1->port == u2->port; -} - -CamelURL * -camel_url_copy(const CamelURL *in) -{ - CamelURL *out; - - out = g_malloc(sizeof(*out)); - out->protocol = g_strdup(in->protocol); - out->user = g_strdup(in->user); - out->authmech = g_strdup(in->authmech); - out->passwd = g_strdup(in->passwd); - out->host = g_strdup(in->host); - out->port = in->port; - out->path = g_strdup(in->path); - out->params = NULL; - if (in->params) - g_datalist_foreach(&((CamelURL *)in)->params, copy_param, &out->params); - out->query = g_strdup(in->query); - out->fragment = g_strdup(in->fragment); - - return out; -} diff --git a/camel/camel-url.h b/camel/camel-url.h deleted file mode 100644 index 4efa315b3f..0000000000 --- a/camel/camel-url.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-url.h : utility functions to parse URLs */ - -/* - * Authors: - * Bertrand Guiheneuf - * Dan Winship - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_URL_H -#define CAMEL_URL_H 1 - -#include -#include - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* if this changes, remember to change camel_url_copy */ -typedef struct _CamelURL { - char *protocol; - char *user; - char *authmech; - char *passwd; - char *host; - int port; - char *path; - GData *params; - char *query; - char *fragment; -} CamelURL; - -#define CAMEL_URL_HIDE_PASSWORD (1 << 0) -#define CAMEL_URL_HIDE_PARAMS (1 << 1) -#define CAMEL_URL_HIDE_AUTH (1 << 2) - -#define CAMEL_URL_HIDE_ALL (CAMEL_URL_HIDE_PASSWORD | CAMEL_URL_HIDE_PARAMS | CAMEL_URL_HIDE_AUTH) - -CamelURL *camel_url_new_with_base (CamelURL *base, const char *url_string); -CamelURL *camel_url_new (const char *url_string, CamelException *ex); -char *camel_url_to_string (CamelURL *url, guint32 flags); -void camel_url_free (CamelURL *url); - -char *camel_url_encode (const char *part, const char *escape_extra); -void camel_url_decode (char *part); - -/* for editing url's */ -void camel_url_set_protocol (CamelURL *url, const char *protocol); -void camel_url_set_user (CamelURL *url, const char *user); -void camel_url_set_authmech (CamelURL *url, const char *authmech); -void camel_url_set_passwd (CamelURL *url, const char *passwd); -void camel_url_set_host (CamelURL *url, const char *host); -void camel_url_set_port (CamelURL *url, int port); -void camel_url_set_path (CamelURL *url, const char *path); -void camel_url_set_param (CamelURL *url, const char *name, const char *value); -void camel_url_set_query (CamelURL *url, const char *query); -void camel_url_set_fragment (CamelURL *url, const char *fragment); - -const char *camel_url_get_param (CamelURL *url, const char *name); - -/* for putting url's into hash tables */ -guint camel_url_hash (const void *v); -int camel_url_equal(const void *v, const void *v2); -CamelURL *camel_url_copy(const CamelURL *in); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -#endif /* URL_UTIL_H */ diff --git a/camel/camel-utf8.c b/camel/camel-utf8.c deleted file mode 100644 index 8fd422c944..0000000000 --- a/camel/camel-utf8.c +++ /dev/null @@ -1,400 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Michael Zucchi - * - * Copyright 2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include -#include "camel-utf8.h" - -#include - -/** - * camel_utf8_putc: - * @ptr: - * @c: - * - * Output a 32 bit unicode character as utf8 octets. At most 4 octets will - * be written to @ptr. @ptr will be advanced to the next character position. - **/ -void -camel_utf8_putc(unsigned char **ptr, guint32 c) -{ - register unsigned char *p = *ptr; - - if (c <= 0x7f) - *p++ = c; - else if (c <= 0x7ff) { - *p++ = 0xc0 | c >> 6; - *p++ = 0x80 | (c & 0x3f); - } else if (c <= 0xffff) { - *p++ = 0xe0 | c >> 12; - *p++ = 0x80 | ((c >> 6) & 0x3f); - *p++ = 0x80 | (c & 0x3f); - } else { - /* see unicode standard 3.0, S 3.8, max 4 octets */ - *p++ = 0xf0 | c >> 18; - *p++ = 0x80 | ((c >> 12) & 0x3f); - *p++ = 0x80 | ((c >> 6) & 0x3f); - *p++ = 0x80 | (c & 0x3f); - } - - *ptr = p; -} - -/** - * camel_utf8_getc: - * @ptr: - * - * Get a Unicode character from a utf8 stream. @ptr will be advanced - * to the next character position. Invalid utf8 characters will be - * silently skipped. @ptr should point to a NUL terminated array. - * - * Return value: The next Unicode character. @ptr will be advanced to - * the next character always. - **/ -guint32 -camel_utf8_getc(const unsigned char **ptr) -{ - register unsigned char *p = (unsigned char *)*ptr; - register unsigned char c, r; - register guint32 v, m; - -again: - r = *p++; -loop: - if (r < 0x80) { - *ptr = p; - v = r; - } else if (r < 0xf8) { /* valid start char? (max 4 octets) */ - v = r; - m = 0x7f80; /* used to mask out the length bits */ - do { - c = *p++; - if ((c & 0xc0) != 0x80) { - r = c; - goto loop; - } - v = (v<<6) | (c & 0x3f); - r<<=1; - m<<=5; - } while (r & 0x40); - - *ptr = p; - - v &= ~m; - } else { - goto again; - } - - return v; -} - -/** - * camel_utf8_getc_limit: - * @ptr: - * @end: must not be NULL. - * - * Get the next utf8 char at @ptr, and return it, advancing @ptr to - * the next character. If @end is reached before a full utf8 - * character can be read, then the invalid Unicode char 0xffff is - * returned as a sentinel (Unicode 3.1, section 2.7), and @ptr is not - * advanced. - * - * Return value: The next utf8 char, or 0xffff. - **/ -guint32 -camel_utf8_getc_limit(const unsigned char **ptr, const unsigned char *end) -{ - register unsigned char *p = (unsigned char *)*ptr; - register unsigned char c, r; - register guint32 v = 0xffff, m; - -again: - while (p < end) { - r = *p++; -loop: - if (r < 0x80) { - *ptr = p; - return r; - } else if (r < 0xf8) { /* valid start char? (max 4 octets) */ - v = r; - m = 0x7f80; /* used to mask out the length bits */ - do { - if (p >= end) - return 0xffff; - - c = *p++; - if ((c & 0xc0) != 0x80) { - r = c; - goto loop; - } - v = (v<<6) | (c & 0x3f); - r<<=1; - m<<=5; - } while (r & 0x40); - - *ptr = p; - - v &= ~m; - return v; - } else { - goto again; - } - } - - return 0xffff; -} - -void -g_string_append_u(GString *out, guint32 c) -{ - unsigned char buffer[8]; - unsigned char *p = buffer; - - camel_utf8_putc(&p, c); - *p = 0; - g_string_append(out, buffer); -} - -static char *utf7_alphabet = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; - -static unsigned char utf7_rank[256] = { - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3e,0x3f,0xff,0xff,0xff, - 0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, - 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0xff,0xff,0xff,0xff,0xff, - 0xff,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28, - 0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -}; - -/** - * camel_utf7_utf8: - * @ptr: - * - * Convert a modified utf7 string to utf8. If the utf7 string - * contains 8 bit characters, they are treated as iso-8859-1. - * - * The IMAP rules [rfc2060] are used in the utf7 encoding. - * - * Return value: The converted string. - **/ -char * -camel_utf7_utf8(const char *ptr) -{ - const unsigned char *p = (unsigned char *)ptr; - unsigned int c; - guint32 v=0, x; - GString *out; - int i=0; - int state = 0; - char *ret; - - out = g_string_new(""); - do { - c = *p++; - switch(state) { - case 0: - if (c == '&') - state = 1; - else - g_string_append_u(out, c); - break; - case 1: - if (c == '-') { - g_string_append_c(out, '&'); - state = 0; - } else if (utf7_rank[c] != 0xff) { - v = utf7_rank[c]; - i = 6; - state = 2; - } else { - /* invalid */ - g_string_append(out, "&-"); - state = 0; - } - break; - case 2: - if (c == '-') { - state = 0; - } else if (utf7_rank[c] != 0xff) { - v = (v<<6) | utf7_rank[c]; - i+=6; - if (i >= 16) { - x = (v >> (i-16)) & 0xffff; - g_string_append_u(out, x); - i-=16; - } - } else { - g_string_append_u(out, c); - state = 0; - } - break; - } - } while (c); - - ret = g_strdup(out->str); - g_string_free(out, TRUE); - - return ret; -} - -static void utf7_closeb64(GString *out, guint32 v, guint32 i) -{ - guint32 x; - - if (i>0) { - x = (v << (6-i)) & 0x3f; - g_string_append_c(out, utf7_alphabet[x]); - } - g_string_append_c(out, '-'); -} - -/** - * camel_utf8_utf7: - * @ptr: - * - * Convert a utf8 string to a modified utf7 format. - * - * The IMAP rules [rfc2060] are used in the utf7 encoding. - * - * Return value: - **/ -char * -camel_utf8_utf7(const char *ptr) -{ - const unsigned char *p = (unsigned char *)ptr; - unsigned int c; - guint32 x, v = 0; - int state = 0; - GString *out; - int i = 0; - char *ret; - - out = g_string_new(""); - - while ( (c = camel_utf8_getc(&p)) ) { - if (c >= 0x20 && c <= 0x7e) { - if (state == 1) { - utf7_closeb64(out, v, i); - state = 0; - i = 0; - } - if (c == '&') - g_string_append(out, "&-"); - else - g_string_append_c(out, c); - } else { - if (state == 0) { - g_string_append_c(out, '&'); - state = 1; - } - v = (v << 16) | c; - i += 16; - while (i >= 6) { - x = (v >> (i-6)) & 0x3f; - g_string_append_c(out, utf7_alphabet[x]); - i -= 6; - } - } - } - - if (state == 1) - utf7_closeb64(out, v, i); - - ret = g_strdup(out->str); - g_string_free(out, TRUE); - - return ret; -} - -/** - * camel_utf8_ucs2: - * @ptr: - * - * Convert a utf8 string into a ucs2 one. The ucs string will be in - * network byte order, and terminated with a 16 bit NULL. - * - * Return value: - **/ -char * -camel_utf8_ucs2(const char *ptr) -{ - GByteArray *work = g_byte_array_new(); - guint32 c; - char *out; - - /* what if c is > 0xffff ? */ - - while ( (c = camel_utf8_getc((const unsigned char **)&ptr)) ) { - guint16 s = htons(c); - - g_byte_array_append(work, (char *)&s, 2); - } - - g_byte_array_append(work, "\000\000", 2); - out = g_malloc(work->len); - memcpy(out, work->data, work->len); - g_byte_array_free(work, TRUE); - - return out; -} - -/** - * camel_ucs2_utf8: - * @ptr: - * - * Convert a ucs2 string into a utf8 one. The ucs2 string is treated - * as network byte ordered, and terminated with a 16 bit NUL. - * - * Return value: - **/ -char *camel_ucs2_utf8(const char *ptr) -{ - guint16 *ucs = (guint16 *)ptr; - guint32 c; - GString *work = g_string_new(""); - char *out; - - while ( (c = *ucs++) ) - g_string_append_u(work, ntohs(c)); - - out = g_strdup(work->str); - g_string_free(work, TRUE); - - return out; -} diff --git a/camel/camel-utf8.h b/camel/camel-utf8.h deleted file mode 100644 index fadce2c7e6..0000000000 --- a/camel/camel-utf8.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Michael Zucchi - * - * Copyright 2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef _CAMEL_UTF8_H -#define _CAMEL_UTF8_H - -void camel_utf8_putc(unsigned char **ptr, guint32 c); -guint32 camel_utf8_getc(const unsigned char **ptr); -guint32 camel_utf8_getc_limit (const unsigned char **ptr, const unsigned char *end); - -/* utility func for utf8 gstrings */ -void g_string_append_u(GString *out, guint32 c); - -/* convert utf7 to/from utf8, actually this is modified IMAP utf7 */ -char *camel_utf7_utf8(const char *ptr); -char *camel_utf8_utf7(const char *ptr); - -/* convert ucs2 to/from utf8 */ -char *camel_utf8_ucs2(const char *ptr); -char *camel_ucs2_utf8(const char *ptr); - -#endif /* ! _CAMEL_UTF8_H */ diff --git a/camel/camel-vee-folder.c b/camel/camel-vee-folder.c deleted file mode 100644 index f7ceb12d59..0000000000 --- a/camel/camel-vee-folder.c +++ /dev/null @@ -1,1683 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000-2003 Ximian Inc. - * - * Authors: Michael Zucchi - * Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "camel-exception.h" -#include "camel-vee-folder.h" -#include "camel-store.h" -#include "camel-folder-summary.h" -#include "camel-mime-message.h" -#include "camel-folder-search.h" - -#include "camel-session.h" -#include "camel-vee-store.h" /* for open flags */ -#include "camel-private.h" - -#include "e-util/md5-utils.h" - -#if defined (DOEPOOLV) || defined (DOESTRV) -#include "e-util/e-memory.h" -#endif - -#define d(x) -extern int camel_verbose_debug; -#define dd(x) (camel_verbose_debug?(x):0) - -#define _PRIVATE(o) (((CamelVeeFolder *)(o))->priv) - -static void vee_refresh_info(CamelFolder *folder, CamelException *ex); - -static void vee_sync (CamelFolder *folder, gboolean expunge, CamelException *ex); -static void vee_expunge (CamelFolder *folder, CamelException *ex); - -static void vee_freeze (CamelFolder *folder); -static void vee_thaw (CamelFolder *folder); - -static CamelMimeMessage *vee_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex); -static void vee_append_message(CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, char **appended_uid, CamelException *ex); -static void vee_transfer_messages_to(CamelFolder *source, GPtrArray *uids, CamelFolder *dest, GPtrArray **transferred_uids, gboolean delete_originals, CamelException *ex); - -static GPtrArray *vee_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex); -static GPtrArray *vee_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex); - -static void vee_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, guint32 set); -static void vee_set_message_user_flag (CamelFolder *folder, const char *uid, const char *name, gboolean value); -static void vee_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value); -static void vee_rename(CamelFolder *folder, const char *new); - -static void camel_vee_folder_class_init (CamelVeeFolderClass *klass); -static void camel_vee_folder_init (CamelVeeFolder *obj); -static void camel_vee_folder_finalise (CamelObject *obj); - -static int vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex); -static void vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source, int killun); - -static void message_changed(CamelFolder *f, const char *uid, CamelVeeFolder *vf); -static void folder_changed(CamelFolder *sub, CamelFolderChangeInfo *changes, CamelVeeFolder *vf); -static void subfolder_deleted(CamelFolder *f, void *event_data, CamelVeeFolder *vf); - -static void folder_changed_remove_uid(CamelFolder *sub, const char *uid, const char hash[8], int keep, CamelVeeFolder *vf); - -static CamelFolderClass *camel_vee_folder_parent; - -/* a vfolder for unmatched messages */ -/* use folder_unmatched->summary_lock for access to unmatched_uids or appropriate internals, for consistency */ -static CamelVeeFolder *folder_unmatched; -static GHashTable *unmatched_uids; /* a refcount of uid's that are matched by any rules */ -static pthread_mutex_t unmatched_lock = PTHREAD_MUTEX_INITIALIZER; -/* only used to initialise folder_unmatched */ -#define UNMATCHED_LOCK() pthread_mutex_lock(&unmatched_lock) -#define UNMATCHED_UNLOCK() pthread_mutex_unlock(&unmatched_lock) - - -CamelType -camel_vee_folder_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_folder_get_type (), "CamelVeeFolder", - sizeof (CamelVeeFolder), - sizeof (CamelVeeFolderClass), - (CamelObjectClassInitFunc) camel_vee_folder_class_init, - NULL, - (CamelObjectInitFunc) camel_vee_folder_init, - (CamelObjectFinalizeFunc) camel_vee_folder_finalise); - } - - return type; -} - -static void -camel_vee_folder_class_init (CamelVeeFolderClass *klass) -{ - CamelFolderClass *folder_class = (CamelFolderClass *) klass; - - camel_vee_folder_parent = CAMEL_FOLDER_CLASS(camel_type_get_global_classfuncs (camel_folder_get_type ())); - - folder_class->refresh_info = vee_refresh_info; - folder_class->sync = vee_sync; - folder_class->expunge = vee_expunge; - - folder_class->get_message = vee_get_message; - folder_class->append_message = vee_append_message; - folder_class->transfer_messages_to = vee_transfer_messages_to; - - folder_class->search_by_expression = vee_search_by_expression; - folder_class->search_by_uids = vee_search_by_uids; - - folder_class->set_message_flags = vee_set_message_flags; - folder_class->set_message_user_flag = vee_set_message_user_flag; - folder_class->set_message_user_tag = vee_set_message_user_tag; - - folder_class->rename = vee_rename; - - folder_class->freeze = vee_freeze; - folder_class->thaw = vee_thaw; -} - -static void -camel_vee_folder_init (CamelVeeFolder *obj) -{ - struct _CamelVeeFolderPrivate *p; - CamelFolder *folder = (CamelFolder *)obj; - - p = _PRIVATE(obj) = g_malloc0(sizeof(*p)); - - folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | - CAMEL_FOLDER_HAS_SEARCH_CAPABILITY); - - /* FIXME: what to do about user flags if the subfolder doesn't support them? */ - folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | - CAMEL_MESSAGE_DELETED | - CAMEL_MESSAGE_DRAFT | - CAMEL_MESSAGE_FLAGGED | - CAMEL_MESSAGE_SEEN; - - obj->changes = camel_folder_change_info_new(); - obj->search = camel_folder_search_new(); - - p->summary_lock = g_mutex_new(); - p->subfolder_lock = g_mutex_new(); - p->changed_lock = g_mutex_new(); -} - -static void -camel_vee_folder_finalise (CamelObject *obj) -{ - CamelVeeFolder *vf = (CamelVeeFolder *)obj; - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); - GList *node; - - /* FIXME: check leaks */ - node = p->folders; - while (node) { - CamelFolder *f = node->data; - - if (vf != folder_unmatched) { - camel_object_unhook_event((CamelObject *)f, "folder_changed", (CamelObjectEventHookFunc) folder_changed, vf); - camel_object_unhook_event((CamelObject *)f, "message_changed", (CamelObjectEventHookFunc) message_changed, vf); - camel_object_unhook_event((CamelObject *)f, "deleted", (CamelObjectEventHookFunc) subfolder_deleted, vf); - /* this updates the vfolder */ - if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) - vee_folder_remove_folder(vf, f, FALSE); - } - camel_object_unref((CamelObject *)f); - - node = g_list_next(node); - } - - g_free(vf->expression); - g_free(vf->vname); - - g_list_free(p->folders); - g_list_free(p->folders_changed); - - camel_folder_change_info_free(vf->changes); - camel_object_unref((CamelObject *)vf->search); - - g_mutex_free(p->summary_lock); - g_mutex_free(p->subfolder_lock); - g_mutex_free(p->changed_lock); - - g_free(p); -} - -static void -vee_folder_construct (CamelVeeFolder *vf, CamelStore *parent_store, const char *name, guint32 flags) -{ - CamelFolder *folder = (CamelFolder *)vf; - char *tmp; - - vf->flags = flags; - vf->vname = g_strdup(name); - tmp = strrchr(vf->vname, '/'); - if (tmp) - tmp++; - else - tmp = vf->vname; - camel_folder_construct(folder, parent_store, vf->vname, tmp); - - /* should CamelVeeMessageInfo be subclassable ..? */ - folder->summary = camel_folder_summary_new(); - folder->summary->message_info_size = sizeof(CamelVeeMessageInfo); -} - -void -camel_vee_folder_construct(CamelVeeFolder *vf, CamelStore *parent_store, const char *name, guint32 flags) -{ - UNMATCHED_LOCK(); - - /* setup unmatched folder if we haven't yet */ - if (folder_unmatched == NULL) { - unmatched_uids = g_hash_table_new (g_str_hash, g_str_equal); - folder_unmatched = (CamelVeeFolder *)camel_object_new (camel_vee_folder_get_type ()); - d(printf("created foldeer unmatched %p\n", folder_unmatched)); - - vee_folder_construct (folder_unmatched, parent_store, CAMEL_UNMATCHED_NAME, CAMEL_STORE_FOLDER_PRIVATE); - } - - UNMATCHED_UNLOCK(); - - vee_folder_construct (vf, parent_store, name, flags); -} - -/** - * camel_vee_folder_new: - * @parent_store: the parent CamelVeeStore - * @name: the vfolder name - * @ex: a CamelException - * - * Create a new CamelVeeFolder object. - * - * Return value: A new CamelVeeFolder widget. - **/ -CamelFolder * -camel_vee_folder_new(CamelStore *parent_store, const char *name, guint32 flags) -{ - CamelVeeFolder *vf; - - UNMATCHED_LOCK(); - - /* setup unmatched folder if we haven't yet */ - if (folder_unmatched == NULL) { - unmatched_uids = g_hash_table_new(g_str_hash, g_str_equal); - folder_unmatched = vf = (CamelVeeFolder *)camel_object_new(camel_vee_folder_get_type()); - d(printf("created foldeer unmatched %p\n", folder_unmatched)); - vee_folder_construct (vf, parent_store, CAMEL_UNMATCHED_NAME, CAMEL_STORE_FOLDER_PRIVATE); - } - - UNMATCHED_UNLOCK(); - - if (strcmp(name, CAMEL_UNMATCHED_NAME) == 0) { - camel_object_ref((CamelObject *)folder_unmatched); - d(printf("returning unmatched %p, count = %d\n", folder_unmatched, camel_folder_get_message_count((CamelFolder *)folder_unmatched))); - return (CamelFolder *)folder_unmatched; - } - - vf = (CamelVeeFolder *)camel_object_new(camel_vee_folder_get_type()); - vee_folder_construct(vf, parent_store, name, flags); - - d(printf("returning folder %s %p, count = %d\n", name, vf, camel_folder_get_message_count((CamelFolder *)vf))); - - return (CamelFolder *)vf; -} - -void -camel_vee_folder_set_expression(CamelVeeFolder *vf, const char *query) -{ - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); - GList *node; - - CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); - - /* no change, do nothing */ - if ((vf->expression && query && strcmp(vf->expression, query) == 0) - || (vf->expression == NULL && query == NULL)) { - CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); - return; - } - - g_free(vf->expression); - if (query) - vf->expression = g_strdup(query); - - node = p->folders; - while (node) { - CamelFolder *f = node->data; - - if (vee_folder_build_folder(vf, f, NULL) == -1) - break; - - node = node->next; - } - - CAMEL_VEE_FOLDER_LOCK(vf, changed_lock); - g_list_free(p->folders_changed); - p->folders_changed = NULL; - CAMEL_VEE_FOLDER_UNLOCK(vf, changed_lock); - - CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); -} - -/** - * camel_vee_folder_add_folder: - * @vf: Virtual Folder object - * @sub: source CamelFolder to add to @vf - * - * Adds @sub as a source folder to @vf. - **/ -void -camel_vee_folder_add_folder(CamelVeeFolder *vf, CamelFolder *sub) -{ - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf), *up = _PRIVATE(folder_unmatched); - int i; - - if (vf == (CamelVeeFolder *)sub) { - g_warning("Adding a virtual folder to itself as source, ignored"); - return; - } - - CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); - - /* for normal vfolders we want only unique ones, for unmatched we want them all recorded */ - if (g_list_find(p->folders, sub) == NULL) { - camel_object_ref((CamelObject *)sub); - p->folders = g_list_append(p->folders, sub); - - /* update the freeze state of 'sub' to match our freeze state */ - for (i = 0; i < p->freeze_count; i++) - camel_folder_freeze (sub); - } - if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER(sub)) { - camel_object_ref((CamelObject *)sub); - up->folders = g_list_append(up->folders, sub); - /* update the freeze state of 'sub' to match Unmatched's freeze state */ - for (i = 0; i < up->freeze_count; i++) - camel_folder_freeze (sub); - } - - CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); - - d(printf("camel_vee_folder_add_folde(%p, %p)\n", vf, sub)); - - camel_object_hook_event((CamelObject *)sub, "folder_changed", (CamelObjectEventHookFunc)folder_changed, vf); - camel_object_hook_event((CamelObject *)sub, "message_changed", (CamelObjectEventHookFunc)message_changed, vf); - camel_object_hook_event((CamelObject *)sub, "deleted", (CamelObjectEventHookFunc)subfolder_deleted, vf); - - vee_folder_build_folder(vf, sub, NULL); -} - -/** - * camel_vee_folder_remove_folder: - * @vf: Virtual Folder object - * @sub: source CamelFolder to remove from @vf - * - * Removed the source folder, @sub, from the virtual folder, @vf. - **/ -void -camel_vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) -{ - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf), *up = _PRIVATE(folder_unmatched); - int killun = FALSE; - int i; - - CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); - - CAMEL_VEE_FOLDER_LOCK(vf, changed_lock); - p->folders_changed = g_list_remove(p->folders_changed, sub); - CAMEL_VEE_FOLDER_UNLOCK(vf, changed_lock); - - if (g_list_find(p->folders, sub) == NULL) { - CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); - return; - } - - camel_object_unhook_event((CamelObject *)sub, "folder_changed", (CamelObjectEventHookFunc) folder_changed, vf); - camel_object_unhook_event((CamelObject *)sub, "message_changed", (CamelObjectEventHookFunc) message_changed, vf); - camel_object_unhook_event((CamelObject *)sub, "deleted", (CamelObjectEventHookFunc) subfolder_deleted, vf); - - p->folders = g_list_remove(p->folders, sub); - - /* undo the freeze state that we have imposed on this source folder */ - for (i = 0; i < p->freeze_count; i++) - camel_folder_thaw (sub); - - CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); - - CAMEL_VEE_FOLDER_LOCK(folder_unmatched, subfolder_lock); - /* if folder deleted, then blow it away from unmatched always, and remove all refs to it */ - if (sub->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED) { - while (g_list_find(up->folders, sub)) { - killun = TRUE; - up->folders = g_list_remove(up->folders, sub); - camel_object_unref((CamelObject *)sub); - - /* undo the freeze state that Unmatched has imposed on this source folder */ - for (i = 0; i < up->freeze_count; i++) - camel_folder_thaw (sub); - } - } else if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) { - if (g_list_find(up->folders, sub) != NULL) { - up->folders = g_list_remove(up->folders, sub); - camel_object_unref((CamelObject *)sub); - - /* undo the freeze state that Unmatched has imposed on this source folder */ - for (i = 0; i < up->freeze_count; i++) - camel_folder_thaw (sub); - } - if (g_list_find(up->folders, sub) == NULL) { - killun = TRUE; - } - } - CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, subfolder_lock); - - vee_folder_remove_folder(vf, sub, killun); - - camel_object_unref((CamelObject *)sub); -} - -static void -remove_folders(CamelFolder *folder, CamelFolder *foldercopy, CamelVeeFolder *vf) -{ - camel_vee_folder_remove_folder(vf, folder); - camel_object_unref((CamelObject *)folder); -} - -/** - * camel_vee_folder_set_folders: - * @vf: - * @folders: - * - * Set the whole list of folder sources on a vee folder. - **/ -void -camel_vee_folder_set_folders(CamelVeeFolder *vf, GList *folders) -{ - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); - GHashTable *remove = g_hash_table_new(NULL, NULL); - GList *l; - CamelFolder *folder; - int changed; - - /* setup a table of all folders we have currently */ - CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); - l = p->folders; - while (l) { - g_hash_table_insert(remove, l->data, l->data); - camel_object_ref((CamelObject *)l->data); - l = l->next; - } - CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); - - /* if we already have the folder, ignore it, otherwise add it */ - l = folders; - while (l) { - if ((folder = g_hash_table_lookup(remove, l->data))) { - g_hash_table_remove(remove, folder); - camel_object_unref((CamelObject *)folder); - - /* if this was a changed folder, re-update it while we're here */ - CAMEL_VEE_FOLDER_LOCK(vf, changed_lock); - changed = g_list_find(p->folders_changed, folder) != NULL; - if (changed) - p->folders_changed = g_list_remove(p->folders_changed, folder); - CAMEL_VEE_FOLDER_UNLOCK(vf, changed_lock); - if (changed) - vee_folder_build_folder(vf, folder, NULL); - } else { - camel_vee_folder_add_folder(vf, l->data); - } - l = l->next; - } - - /* then remove any we still have */ - g_hash_table_foreach(remove, (GHFunc)remove_folders, vf); - g_hash_table_destroy(remove); -} - -/** - * camel_vee_folder_hash_folder: - * @folder: - * @: - * - * Create a hash string representing the folder name, which should be - * unique, and remain static for a given folder. - **/ -void -camel_vee_folder_hash_folder(CamelFolder *folder, char buffer[8]) -{ - MD5Context ctx; - unsigned char digest[16]; - unsigned int state = 0, save = 0; - char *tmp; - int i; - - md5_init(&ctx); - tmp = camel_service_get_url((CamelService *)folder->parent_store); - md5_update(&ctx, tmp, strlen(tmp)); - g_free(tmp); - md5_update(&ctx, folder->full_name, strlen(folder->full_name)); - md5_final(&ctx, digest); - camel_base64_encode_close(digest, 6, FALSE, buffer, &state, &save); - - for (i=0;i<8;i++) { - if (buffer[i] == '+') - buffer[i] = '.'; - if (buffer[i] == '/') - buffer[i] = '_'; - } -} - -/** - * camel_vee_folder_get_location: - * @vf: - * @vinfo: - * @realuid: if not NULL, set to the uid of the real message, must be - * g_free'd by caller. - * - * Find the real folder (and uid) - * - * Return value: - **/ -CamelFolder * -camel_vee_folder_get_location(CamelVeeFolder *vf, const CamelVeeMessageInfo *vinfo, char **realuid) -{ - /* locking? yes? no? although the vfolderinfo is valid when obtained - the folder in it might not necessarily be so ...? */ - if (CAMEL_IS_VEE_FOLDER(vinfo->folder)) { - CamelFolder *folder; - const CamelVeeMessageInfo *vfinfo; - - vfinfo = (CamelVeeMessageInfo *)camel_folder_get_message_info(vinfo->folder, camel_message_info_uid(vinfo)+8); - folder = camel_vee_folder_get_location((CamelVeeFolder *)vinfo->folder, vfinfo, realuid); - camel_folder_free_message_info(vinfo->folder, (CamelMessageInfo *)vfinfo); - return folder; - } else { - if (realuid) - *realuid = g_strdup(camel_message_info_uid(vinfo)+8); - - return vinfo->folder; - } -} - -static void vee_refresh_info(CamelFolder *folder, CamelException *ex) -{ - CamelVeeFolder *vf = (CamelVeeFolder *)folder; - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); - GList *node, *list; - - CAMEL_VEE_FOLDER_LOCK(vf, changed_lock); - list = p->folders_changed; - p->folders_changed = NULL; - CAMEL_VEE_FOLDER_UNLOCK(vf, changed_lock); - - node = list; - while (node) { - CamelFolder *f = node->data; - - if (vee_folder_build_folder(vf, f, ex) == -1) - break; - - node = node->next; - } - - g_list_free(list); -} - -static void -vee_sync(CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - CamelVeeFolder *vf = (CamelVeeFolder *)folder; - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); - GList *node; - - CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); - - node = p->folders; - while (node) { - CamelFolder *f = node->data; - - camel_folder_sync(f, expunge, ex); - if (camel_exception_is_set(ex)) { - char *desc; - - camel_object_get(f, NULL, CAMEL_OBJECT_DESCRIPTION, &desc, NULL); - camel_exception_setv(ex, ex->id, _("Error storing `%s': %s"), desc, ex->desc); - break; - } - - if (vee_folder_build_folder(vf, f, ex) == -1) - break; - - node = node->next; - } - - if (node == NULL) { - CAMEL_VEE_FOLDER_LOCK(vf, changed_lock); - g_list_free(p->folders_changed); - p->folders_changed = NULL; - CAMEL_VEE_FOLDER_UNLOCK(vf, changed_lock); - } - - CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); -} - -static void -vee_expunge (CamelFolder *folder, CamelException *ex) -{ - ((CamelFolderClass *)((CamelObject *)folder)->klass)->sync(folder, TRUE, ex); -} - -static CamelMimeMessage * -vee_get_message(CamelFolder *folder, const char *uid, CamelException *ex) -{ - CamelVeeMessageInfo *mi; - CamelMimeMessage *msg = NULL; - - mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, uid); - if (mi) { - msg = camel_folder_get_message(mi->folder, camel_message_info_uid(mi)+8, ex); - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); - } else { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("No such message %s in %s"), uid, - folder->name); - } - - return msg; -} - -static GPtrArray * -vee_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex) -{ - GList *node; - GPtrArray *matches, *result = g_ptr_array_new (); - char *expr; - CamelVeeFolder *vf = (CamelVeeFolder *)folder; - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); - GHashTable *searched = g_hash_table_new(NULL, NULL); - - CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); - - if (vf != folder_unmatched) - expr = g_strdup_printf ("(and %s %s)", vf->expression, expression); - else - expr = g_strdup (expression); - - node = p->folders; - while (node) { - CamelFolder *f = node->data; - int i; - char hash[8]; - - /* make sure we only search each folder once - for unmatched folder to work right */ - if (g_hash_table_lookup(searched, f) == NULL) { - camel_vee_folder_hash_folder(f, hash); - /* FIXME: shouldn't ignore search exception */ - matches = camel_folder_search_by_expression(f, expression, NULL); - if (matches) { - for (i = 0; i < matches->len; i++) { - char *uid = matches->pdata[i], *vuid; - - vuid = g_malloc(strlen(uid)+9); - memcpy(vuid, hash, 8); - strcpy(vuid+8, uid); - g_ptr_array_add(result, vuid); - } - camel_folder_search_free(f, matches); - } - g_hash_table_insert(searched, f, f); - } - node = g_list_next(node); - } - - g_free(expr); - CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); - - g_hash_table_destroy(searched); - - return result; -} - -static GPtrArray * -vee_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex) -{ - GList *node; - GPtrArray *matches, *result = g_ptr_array_new (); - GPtrArray *folder_uids = g_ptr_array_new(); - char *expr; - CamelVeeFolder *vf = (CamelVeeFolder *)folder; - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); - GHashTable *searched = g_hash_table_new(NULL, NULL); - - CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); - - expr = g_strdup_printf("(and %s %s)", vf->expression, expression); - node = p->folders; - while (node) { - CamelFolder *f = node->data; - int i; - char hash[8]; - - /* make sure we only search each folder once - for unmatched folder to work right */ - if (g_hash_table_lookup(searched, f) == NULL) { - camel_vee_folder_hash_folder(f, hash); - - /* map the vfolder uid's to the source folder uid's first */ - g_ptr_array_set_size(folder_uids, 0); - for (i=0;ilen;i++) { - char *uid = uids->pdata[i]; - - if (strlen(uid) >= 8 && strncmp(uid, hash, 8) == 0) - g_ptr_array_add(folder_uids, uid+8); - } - if (folder_uids->len > 0) { - matches = camel_folder_search_by_uids(f, expression, folder_uids, ex); - if (matches) { - for (i = 0; i < matches->len; i++) { - char *uid = matches->pdata[i], *vuid; - - vuid = g_malloc(strlen(uid)+9); - memcpy(vuid, hash, 8); - strcpy(vuid+8, uid); - g_ptr_array_add(result, vuid); - } - camel_folder_search_free(f, matches); - } else { - g_warning("Search failed: %s", camel_exception_get_description(ex)); - } - } - g_hash_table_insert(searched, f, f); - } - node = g_list_next(node); - } - - g_free(expr); - CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); - - g_hash_table_destroy(searched); - g_ptr_array_free(folder_uids, 0); - - return result; -} - -static void -vee_set_message_flags(CamelFolder *folder, const char *uid, guint32 flags, guint32 set) -{ - CamelVeeMessageInfo *mi; - - mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, uid); - if (mi) { - camel_folder_set_message_flags(mi->folder, camel_message_info_uid(mi) + 8, flags, set); - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); - ((CamelFolderClass *)camel_vee_folder_parent)->set_message_flags(folder, uid, flags, set); - } -} - -static void -vee_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value) -{ - CamelVeeMessageInfo *mi; - - mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, uid); - if (mi) { - camel_folder_set_message_user_flag(mi->folder, camel_message_info_uid(mi) + 8, name, value); - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); - ((CamelFolderClass *)camel_vee_folder_parent)->set_message_user_flag(folder, uid, name, value); - } -} - -static void -vee_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value) -{ - CamelVeeMessageInfo *mi; - - mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, uid); - if (mi) { - camel_folder_set_message_user_tag(mi->folder, camel_message_info_uid(mi) + 8, name, value); - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); - ((CamelFolderClass *)camel_vee_folder_parent)->set_message_user_tag(folder, uid, name, value); - } -} - -static void -vee_append_message(CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, char **appended_uid, CamelException *ex) -{ - camel_exception_set(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot copy or move messages into a Virtual Folder")); -} - -static void -vee_transfer_messages_to (CamelFolder *folder, GPtrArray *uids, CamelFolder *dest, GPtrArray **transferred_uids, gboolean delete_originals, CamelException *ex) -{ - camel_exception_set(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot copy or move messages into a Virtual Folder")); -} - -static void vee_rename(CamelFolder *folder, const char *new) -{ - CamelVeeFolder *vf = (CamelVeeFolder *)folder; - - g_free(vf->vname); - vf->vname = g_strdup(new); - - ((CamelFolderClass *)camel_vee_folder_parent)->rename(folder, new); -} - -/* ********************************************************************** * - utility functions */ - -/* must be called with summary_lock held */ -static CamelVeeMessageInfo * -vee_folder_add_info(CamelVeeFolder *vf, CamelFolder *f, CamelMessageInfo *info, const char hash[8]) -{ - CamelVeeMessageInfo *mi; - char *vuid; - const char *uid; - CamelFolder *folder = (CamelFolder *)vf; - CamelMessageInfo *dinfo; - - uid = camel_message_info_uid(info); - vuid = alloca(strlen(uid)+9); - memcpy(vuid, hash, 8); - strcpy(vuid+8, uid); - dinfo = camel_folder_summary_uid(folder->summary, vuid); - if (dinfo) { - d(printf("w:clash, we already have '%s' in summary\n", vuid)); - camel_folder_summary_info_free(folder->summary, dinfo); - return NULL; - } - - d(printf("adding vuid %s to %s\n", vuid, vf->vname)); - - mi = (CamelVeeMessageInfo *)camel_folder_summary_info_new(folder->summary); - camel_message_info_dup_to(info, (CamelMessageInfo *)mi); -#ifdef DOEPOOLV - mi->info.strings = e_poolv_set(mi->info.strings, CAMEL_MESSAGE_INFO_UID, vuid, FALSE); -#elif defined (DOESTRV) - mi->info.strings = e_strv_set_ref(mi->info.strings, CAMEL_MESSAGE_INFO_UID, vuid); - mi->info.strings = e_strv_pack(mi->info.strings); -#else - g_free(mi->info.uid); - mi->info.uid = g_strdup(vuid); -#endif - mi->folder = f; - camel_folder_summary_add(folder->summary, (CamelMessageInfo *)mi); - - return mi; -} - -/* must be called with summary_lock held */ -static CamelVeeMessageInfo * -vee_folder_add_uid(CamelVeeFolder *vf, CamelFolder *f, const char *inuid, const char hash[8]) -{ - CamelMessageInfo *info; - CamelVeeMessageInfo *mi = NULL; - - info = camel_folder_get_message_info(f, inuid); - if (info) { - mi = vee_folder_add_info(vf, f, info, hash); - camel_folder_free_message_info(f, info); - } - return mi; -} - -static void -vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source, int killun) -{ - int i, count, n, still, start, last; - char *oldkey; - CamelFolder *folder = (CamelFolder *)vf; - char hash[8]; - /*struct _CamelVeeFolderPrivate *p = _PRIVATE(vf);*/ - CamelFolderChangeInfo *vf_changes = NULL, *unmatched_changes = NULL; - - if (vf == folder_unmatched) - return; - - /* check if this folder is still to be part of unmatched */ - if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !killun) { - CAMEL_VEE_FOLDER_LOCK(folder_unmatched, subfolder_lock); - still = g_list_find(_PRIVATE(folder_unmatched)->folders, source) != NULL; - CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, subfolder_lock); - camel_vee_folder_hash_folder(source, hash); - } else { - still = FALSE; - } - - CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); - CAMEL_VEE_FOLDER_LOCK(folder_unmatched, summary_lock); - - /* See if we just blow all uid's from this folder away from unmatched, regardless */ - if (killun) { - start = -1; - last = -1; - count = camel_folder_summary_count(((CamelFolder *)folder_unmatched)->summary); - for (i=0;isummary, i); - - if (mi) { - if (mi->folder == source) { - camel_folder_change_info_remove_uid(folder_unmatched->changes, camel_message_info_uid(mi)); - if (last == -1) { - last = start = i; - } else if (last+1 == i) { - last = i; - } else { - camel_folder_summary_remove_range(((CamelFolder *)folder_unmatched)->summary, start, last); - i -= (last-start)+1; - start = last = i; - } - } - camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)mi); - } - } - if (last != -1) - camel_folder_summary_remove_range(((CamelFolder *)folder_unmatched)->summary, start, last); - } - - start = -1; - last = -1; - count = camel_folder_summary_count(folder->summary); - for (i=0;isummary, i); - if (mi) { - if (mi->folder == source) { - const char *uid = camel_message_info_uid(mi); - - camel_folder_change_info_remove_uid(vf->changes, uid); - - if (last == -1) { - last = start = i; - } else if (last+1 == i) { - last = i; - } else { - camel_folder_summary_remove_range(folder->summary, start, last); - i -= (last-start)+1; - start = last = i; - } - if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) { - if (still) { - if (g_hash_table_lookup_extended(unmatched_uids, uid, (void **)&oldkey, (void **)&n)) { - if (n == 1) { - g_hash_table_remove(unmatched_uids, oldkey); - if (vee_folder_add_uid(folder_unmatched, source, oldkey+8, hash)) - camel_folder_change_info_add_uid(folder_unmatched->changes, oldkey); - g_free(oldkey); - } else { - g_hash_table_insert(unmatched_uids, oldkey, GINT_TO_POINTER(n-1)); - } - } - } else { - if (g_hash_table_lookup_extended(unmatched_uids, camel_message_info_uid(mi), (void **)&oldkey, (void **)&n)) { - g_hash_table_remove(unmatched_uids, oldkey); - g_free(oldkey); - } - } - } - } - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); - } - } - - if (last != -1) - camel_folder_summary_remove_range(folder->summary, start, last); - - if (camel_folder_change_info_changed(folder_unmatched->changes)) { - unmatched_changes = folder_unmatched->changes; - folder_unmatched->changes = camel_folder_change_info_new(); - } - - if (camel_folder_change_info_changed(vf->changes)) { - vf_changes = vf->changes; - vf->changes = camel_folder_change_info_new(); - } - - CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, summary_lock); - CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); - - if (unmatched_changes) { - camel_object_trigger_event((CamelObject *)folder_unmatched, "folder_changed", unmatched_changes); - camel_folder_change_info_free(unmatched_changes); - } - - if (vf_changes) { - camel_object_trigger_event((CamelObject *)vf, "folder_changed", vf_changes); - camel_folder_change_info_free(vf_changes); - } -} - -struct _update_data { - CamelFolder *source; - CamelVeeFolder *vf; - char hash[8]; -}; - -static void -unmatched_check_uid(char *uidin, void *value, struct _update_data *u) -{ - char *uid; - int n; - - uid = alloca(strlen(uidin)+9); - memcpy(uid, u->hash, 8); - strcpy(uid+8, uidin); - n = GPOINTER_TO_INT(g_hash_table_lookup(unmatched_uids, uid)); - if (n == 0) { - if (vee_folder_add_uid(folder_unmatched, u->source, uidin, u->hash)) - camel_folder_change_info_add_uid(folder_unmatched->changes, uid); - } else { - CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(((CamelFolder *)folder_unmatched)->summary, uid); - if (mi) { - camel_folder_summary_remove(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)mi); - camel_folder_change_info_remove_uid(folder_unmatched->changes, uid); - camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)mi); - } - } -} - -static void -folder_added_uid(char *uidin, void *value, struct _update_data *u) -{ - CamelVeeMessageInfo *mi; - char *oldkey; - int n; - - if ( (mi = vee_folder_add_uid(u->vf, u->source, uidin, u->hash)) ) { - camel_folder_change_info_add_uid(u->vf->changes, camel_message_info_uid(mi)); - - if (!CAMEL_IS_VEE_FOLDER(u->source)) { - if (g_hash_table_lookup_extended(unmatched_uids, camel_message_info_uid(mi), (void **)&oldkey, (void **)&n)) { - g_hash_table_insert(unmatched_uids, oldkey, GINT_TO_POINTER(n+1)); - } else { - g_hash_table_insert(unmatched_uids, g_strdup(camel_message_info_uid(mi)), GINT_TO_POINTER(1)); - } - } - } -} - -/* build query contents for a single folder */ -static int -vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex) -{ - GPtrArray *match, *all; - GHashTable *allhash, *matchhash; - CamelFolder *f = source; - CamelFolder *folder = (CamelFolder *)vf; - int i, n, count, start, last; - struct _update_data u; - CamelFolderChangeInfo *vf_changes = NULL, *unmatched_changes = NULL; - - if (vf == folder_unmatched) - return 0; - - /* if we have no expression, or its been cleared, then act as if no matches */ - if (vf->expression == NULL) { - match = g_ptr_array_new(); - } else { - match = camel_folder_search_by_expression(f, vf->expression, ex); - if (match == NULL) - return -1; - } - - u.source = source; - u.vf = vf; - camel_vee_folder_hash_folder(source, u.hash); - - CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); - - /* we build 2 hash tables, one for all uid's not matched, the other for all matched uid's, - we just ref the real memory */ - matchhash = g_hash_table_new(g_str_hash, g_str_equal); - for (i=0;ilen;i++) - g_hash_table_insert(matchhash, match->pdata[i], (void *)1); - - allhash = g_hash_table_new(g_str_hash, g_str_equal); - all = camel_folder_get_uids(f); - for (i=0;ilen;i++) - if (g_hash_table_lookup(matchhash, all->pdata[i]) == NULL) - g_hash_table_insert(allhash, all->pdata[i], (void *)1); - - CAMEL_VEE_FOLDER_LOCK(folder_unmatched, summary_lock); - - /* scan, looking for "old" uid's to be removed */ - start = -1; - last = -1; - count = camel_folder_summary_count(folder->summary); - for (i=0;isummary, i); - - if (mi) { - if (mi->folder == source) { - char *uid = (char *)camel_message_info_uid(mi), *oldkey; - - if (g_hash_table_lookup(matchhash, uid+8) == NULL) { - if (last == -1) { - last = start = i; - } else if (last+1 == i) { - last = i; - } else { - camel_folder_summary_remove_range(folder->summary, start, last); - i -= (last-start)+1; - start = last = i; - } - camel_folder_change_info_remove_uid(vf->changes, camel_message_info_uid(mi)); - if (!CAMEL_IS_VEE_FOLDER(source) - && g_hash_table_lookup_extended(unmatched_uids, uid, (void **)&oldkey, (void **)&n)) { - if (n == 1) { - g_hash_table_remove(unmatched_uids, oldkey); - g_free(oldkey); - } else { - g_hash_table_insert(unmatched_uids, oldkey, GINT_TO_POINTER(n-1)); - } - } - } else { - g_hash_table_remove(matchhash, uid+8); - } - } - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); - } - } - if (last != -1) - camel_folder_summary_remove_range(folder->summary, start, last); - - /* now matchhash contains any new uid's, add them, etc */ - g_hash_table_foreach(matchhash, (GHFunc)folder_added_uid, &u); - - /* scan unmatched, remove any that have vanished, etc */ - count = camel_folder_summary_count(((CamelFolder *)folder_unmatched)->summary); - for (i=0;isummary, i); - - if (mi) { - if (mi->folder == source) { - char *uid = (char *)camel_message_info_uid(mi); - - if (g_hash_table_lookup(allhash, uid+8) == NULL) { - /* no longer exists at all, just remove it entirely */ - camel_folder_summary_remove_index(((CamelFolder *)folder_unmatched)->summary, i); - camel_folder_change_info_remove_uid(folder_unmatched->changes, camel_message_info_uid(mi)); - i--; - } else { - g_hash_table_remove(allhash, uid+8); - } - } - camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)mi); - } - } - - /* now allhash contains all potentially new uid's for the unmatched folder, process */ - if (!CAMEL_IS_VEE_FOLDER(source)) - g_hash_table_foreach(allhash, (GHFunc)unmatched_check_uid, &u); - - /* copy any changes so we can raise them outside the lock */ - if (camel_folder_change_info_changed(folder_unmatched->changes)) { - unmatched_changes = folder_unmatched->changes; - folder_unmatched->changes = camel_folder_change_info_new(); - } - - if (camel_folder_change_info_changed(vf->changes)) { - vf_changes = vf->changes; - vf->changes = camel_folder_change_info_new(); - } - - CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, summary_lock); - CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); - - g_hash_table_destroy(matchhash); - g_hash_table_destroy(allhash); - /* if expression not set, we only had a null list */ - if (vf->expression == NULL) - g_ptr_array_free(match, TRUE); - else - camel_folder_search_free(f, match); - camel_folder_free_uids(f, all); - - if (unmatched_changes) { - camel_object_trigger_event((CamelObject *)folder_unmatched, "folder_changed", unmatched_changes); - camel_folder_change_info_free(unmatched_changes); - } - - if (vf_changes) { - camel_object_trigger_event((CamelObject *)vf, "folder_changed", vf_changes); - camel_folder_change_info_free(vf_changes); - } - - return 0; -} - -/* - - (match-folder "folder1" "folder2") - - */ - - -/* Hold all these with summary lock and unmatched summary lock held */ -static void -folder_changed_add_uid(CamelFolder *sub, const char *uid, const char hash[8], CamelVeeFolder *vf) -{ - CamelVeeMessageInfo *vinfo; - const char *vuid; - char *oldkey; - int n; - - vinfo = vee_folder_add_uid(vf, sub, uid, hash); - if (vinfo == NULL) - return; - - vuid = camel_message_info_uid(vinfo); - camel_folder_change_info_add_uid(vf->changes, vuid); - - if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER(sub)) { - if (g_hash_table_lookup_extended(unmatched_uids, vuid, (void **)&oldkey, (void **)&n)) { - g_hash_table_insert(unmatched_uids, oldkey, GINT_TO_POINTER(n+1)); - } else { - g_hash_table_insert(unmatched_uids, g_strdup(vuid), (void *)1); - } - vinfo = (CamelVeeMessageInfo *)camel_folder_get_message_info((CamelFolder *)folder_unmatched, vuid); - if (vinfo) { - camel_folder_change_info_remove_uid(folder_unmatched->changes, vuid); - camel_folder_summary_remove(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)vinfo); - camel_folder_free_message_info((CamelFolder *)folder_unmatched, (CamelMessageInfo *)vinfo); - } - } -} - -static void -folder_changed_remove_uid(CamelFolder *sub, const char *uid, const char hash[8], int keep, CamelVeeFolder *vf) -{ - CamelFolder *folder = (CamelFolder *)vf; - char *vuid, *oldkey; - int n; - CamelVeeMessageInfo *vinfo; - - vuid = alloca(strlen(uid)+9); - memcpy(vuid, hash, 8); - strcpy(vuid+8, uid); - - vinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, vuid); - if (vinfo) { - camel_folder_change_info_remove_uid(vf->changes, vuid); - camel_folder_summary_remove(folder->summary, (CamelMessageInfo *)vinfo); - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo); - } - - if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER(sub)) { - if (keep) { - if (g_hash_table_lookup_extended(unmatched_uids, vuid, (void **)&oldkey, (void **)&n)) { - if (n == 1) { - g_hash_table_remove(unmatched_uids, oldkey); - if (vee_folder_add_uid(folder_unmatched, sub, uid, hash)) - camel_folder_change_info_add_uid(folder_unmatched->changes, oldkey); - g_free(oldkey); - } else { - g_hash_table_insert(unmatched_uids, oldkey, GINT_TO_POINTER(n-1)); - } - } else { - if (vee_folder_add_uid(folder_unmatched, sub, uid, hash)) - camel_folder_change_info_add_uid(folder_unmatched->changes, oldkey); - } - } else { - if (g_hash_table_lookup_extended(unmatched_uids, vuid, (void **)&oldkey, (void **)&n)) { - g_hash_table_remove(unmatched_uids, oldkey); - g_free(oldkey); - } - - vinfo = (CamelVeeMessageInfo *)camel_folder_get_message_info((CamelFolder *)folder_unmatched, vuid); - if (vinfo) { - camel_folder_change_info_remove_uid(folder_unmatched->changes, vuid); - camel_folder_summary_remove_uid(((CamelFolder *)folder_unmatched)->summary, vuid); - camel_folder_free_message_info((CamelFolder *)folder_unmatched, (CamelMessageInfo *)vinfo); - } - } - } -} - -static void -folder_changed_change_uid(CamelFolder *sub, const char *uid, const char hash[8], CamelVeeFolder *vf) -{ - char *vuid; - CamelVeeMessageInfo *vinfo, *uinfo; - CamelMessageInfo *info; - CamelFolder *folder = (CamelFolder *)vf; - - vuid = alloca(strlen(uid)+9); - memcpy(vuid, hash, 8); - strcpy(vuid+8, uid); - - vinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, vuid); - uinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(((CamelFolder *)folder_unmatched)->summary, vuid); - if (vinfo || uinfo) { - info = camel_folder_get_message_info(sub, uid); - if (info) { - if (vinfo) { - int changed = FALSE; - - if (vinfo->info.flags != info->flags){ - vinfo->info.flags = info->flags; - changed = TRUE; - } - - changed |= camel_flag_list_copy(&vinfo->info.user_flags, &info->user_flags); - changed |= camel_tag_list_copy(&vinfo->info.user_tags, &info->user_tags); - if (changed) - camel_folder_change_info_change_uid(vf->changes, vuid); - - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo); - } - - if (uinfo) { - int changed = FALSE; - - if (uinfo->info.flags != info->flags){ - uinfo->info.flags = info->flags; - changed = TRUE; - } - - changed |= camel_flag_list_copy(&uinfo->info.user_flags, &info->user_flags); - changed |= camel_tag_list_copy(&uinfo->info.user_tags, &info->user_tags); - if (changed) - camel_folder_change_info_change_uid(folder_unmatched->changes, vuid); - - camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)uinfo); - } - - camel_folder_free_message_info(sub, info); - } else { - if (vinfo) { - folder_changed_remove_uid(sub, uid, hash, FALSE, vf); - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo); - } - if (uinfo) - camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)uinfo); - } - } -} - -struct _folder_changed_msg { - CamelSessionThreadMsg msg; - CamelFolderChangeInfo *changes; - CamelFolder *sub; - CamelVeeFolder *vf; -}; - -static void -folder_changed_change(CamelSession *session, CamelSessionThreadMsg *msg) -{ - struct _folder_changed_msg *m = (struct _folder_changed_msg *)msg; - CamelFolder *sub = m->sub; - CamelFolder *folder = (CamelFolder *)m->vf; - CamelVeeFolder *vf = m->vf; - CamelFolderChangeInfo *changes = m->changes; - char *vuid = NULL, hash[8]; - const char *uid; - CamelVeeMessageInfo *vinfo; - int i, vuidlen = 0; - CamelFolderChangeInfo *vf_changes = NULL, *unmatched_changes = NULL; - GPtrArray *matches_added = NULL, /* newly added, that match */ - *matches_changed = NULL, /* newly changed, that now match */ - *newchanged = NULL, - *changed; - GPtrArray *always_changed = NULL; - GHashTable *matches_hash; - - /* Check the folder hasn't beem removed while we weren't watching */ - CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); - if (g_list_find(_PRIVATE(vf)->folders, sub) == NULL) { - CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); - return; - } - - camel_vee_folder_hash_folder(sub, hash); - - /* Lookup anything before we lock anything, to avoid deadlock with build_folder */ - - /* Find newly added that match */ - if (changes->uid_added->len > 0) { - dd(printf(" Searching for added matches '%s'\n", vf->expression)); - matches_added = camel_folder_search_by_uids(sub, vf->expression, changes->uid_added, NULL); - } - - /* TODO: - In this code around here, we can work out if the search will affect the changes - we had, and only re-search against them if they might have */ - - /* Search for changed items that newly match, but only if we dont have them */ - changed = changes->uid_changed; - if (changed->len > 0) { - dd(printf(" Searching for changed matches '%s'\n", vf->expression)); - - if ((vf->flags & CAMEL_STORE_VEE_FOLDER_AUTO) == 0) { - newchanged = g_ptr_array_new(); - always_changed = g_ptr_array_new(); - for (i=0;ilen;i++) { - uid = changed->pdata[i]; - if (strlen(uid)+9 > vuidlen) { - vuidlen = strlen(uid)+64; - vuid = g_realloc(vuid, vuidlen); - } - memcpy(vuid, hash, 8); - strcpy(vuid+8, uid); - vinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, vuid); - if (vinfo == NULL) { - g_ptr_array_add(newchanged, (char *)uid); - } else { - g_ptr_array_add(always_changed, (char *)uid); - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo); - } - } - changed = newchanged; - } - - if (changed->len) - matches_changed = camel_folder_search_by_uids(sub, vf->expression, changed, NULL); - } - - CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); - CAMEL_VEE_FOLDER_LOCK(folder_unmatched, summary_lock); - - dd(printf("Vfolder '%s' subfolder changed '%s'\n", folder->full_name, sub->full_name)); - dd(printf(" changed %d added %d removed %d\n", changes->uid_changed->len, changes->uid_added->len, changes->uid_removed->len)); - - /* Always remove removed uid's, in any case */ - for (i=0;iuid_removed->len;i++) { - dd(printf(" removing uid '%s'\n", (char *)changes->uid_removed->pdata[i])); - folder_changed_remove_uid(sub, changes->uid_removed->pdata[i], hash, FALSE, vf); - } - - /* Add any newly matched or to unmatched folder if they dont */ - if (matches_added) { - matches_hash = g_hash_table_new(g_str_hash, g_str_equal); - for (i=0;ilen;i++) { - dd(printf(" %s", (char *)matches_added->pdata[i])); - g_hash_table_insert(matches_hash, matches_added->pdata[i], matches_added->pdata[i]); - } - for (i=0;iuid_added->len;i++) { - uid = changes->uid_added->pdata[i]; - if (g_hash_table_lookup(matches_hash, uid)) { - dd(printf(" adding uid '%s' [newly matched]\n", (char *)uid)); - folder_changed_add_uid(sub, uid, hash, vf); - } else if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) { - if (strlen(uid)+9 > vuidlen) { - vuidlen = strlen(uid)+64; - vuid = g_realloc(vuid, vuidlen); - } - memcpy(vuid, hash, 8); - strcpy(vuid+8, uid); - - if (!CAMEL_IS_VEE_FOLDER(sub) && g_hash_table_lookup(unmatched_uids, vuid) == NULL) { - dd(printf(" adding uid '%s' to Unmatched [newly unmatched]\n", (char *)uid)); - vinfo = (CamelVeeMessageInfo *)camel_folder_get_message_info((CamelFolder *)folder_unmatched, vuid); - if (vinfo == NULL) { - if (vee_folder_add_uid(folder_unmatched, sub, uid, hash)) - camel_folder_change_info_add_uid(folder_unmatched->changes, vuid); - } else { - camel_folder_free_message_info((CamelFolder *)folder_unmatched, (CamelMessageInfo *)vinfo); - } - } - } - } - g_hash_table_destroy(matches_hash); - } - - /* Change any newly changed */ - if (always_changed) { - for (i=0;ilen;i++) - folder_changed_change_uid(sub, always_changed->pdata[i], hash, vf); - g_ptr_array_free(always_changed, TRUE); - } - - /* Change/add/remove any changed */ - if (matches_changed) { - /* If we are auto-updating, then re-check changed uids still match */ - dd(printf(" Vfolder %supdate\nuids match:", (vf->flags & CAMEL_STORE_VEE_FOLDER_AUTO)?"auto-":"")); - matches_hash = g_hash_table_new(g_str_hash, g_str_equal); - for (i=0;ilen;i++) { - dd(printf(" %s", (char *)matches_changed->pdata[i])); - g_hash_table_insert(matches_hash, matches_changed->pdata[i], matches_changed->pdata[i]); - } - dd(printf("\n")); - for (i=0;ilen;i++) { - uid = changed->pdata[i]; - if (strlen(uid)+9 > vuidlen) { - vuidlen = strlen(uid)+64; - vuid = g_realloc(vuid, vuidlen); - } - memcpy(vuid, hash, 8); - strcpy(vuid+8, uid); - vinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, vuid); - if (vinfo == NULL) { - /* A uid we dont have, but now it matches, add it */ - if (g_hash_table_lookup(matches_hash, uid)) { - dd(printf(" adding uid '%s' [newly matched]\n", uid)); - folder_changed_add_uid(sub, uid, hash, vf); - } - } else { - if ((vf->flags & CAMEL_STORE_VEE_FOLDER_AUTO) == 0 - || g_hash_table_lookup(matches_hash, uid)) { - /* still match, or we're not auto-updating, change event, (if it changed) */ - dd(printf(" changing uid '%s' [still matches]\n", uid)); - folder_changed_change_uid(sub, uid, hash, vf); - } else { - /* No longer matches, remove it, but keep it in unmatched (potentially) */ - dd(printf(" removing uid '%s' [did match]\n", uid)); - folder_changed_remove_uid(sub, uid, hash, TRUE, vf); - } - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo); - } - } - g_hash_table_destroy(matches_hash); - } - - if (camel_folder_change_info_changed(folder_unmatched->changes)) { - unmatched_changes = folder_unmatched->changes; - folder_unmatched->changes = camel_folder_change_info_new(); - } - - if (camel_folder_change_info_changed(vf->changes)) { - vf_changes = vf->changes; - vf->changes = camel_folder_change_info_new(); - } - - CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, summary_lock); - CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); - - /* Cleanup stuff on our folder */ - if (matches_added) - camel_folder_search_free(sub, matches_added); - - if (matches_changed) - camel_folder_search_free(sub, matches_changed); - - CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); - - /* cleanup the rest */ - if (newchanged) - g_ptr_array_free(newchanged, TRUE); - - g_free(vuid); - - if (unmatched_changes) { - camel_object_trigger_event((CamelObject *)folder_unmatched, "folder_changed", unmatched_changes); - camel_folder_change_info_free(unmatched_changes); - } - - if (vf_changes) { - /* If not auto-updating, keep track of changed folders for later re-sync */ - if ((vf->flags & CAMEL_STORE_VEE_FOLDER_AUTO) == 0) { - CAMEL_VEE_FOLDER_LOCK(vf, changed_lock); - if (g_list_find(vf->priv->folders_changed, sub) != NULL) - vf->priv->folders_changed = g_list_prepend(vf->priv->folders_changed, sub); - CAMEL_VEE_FOLDER_UNLOCK(vf, changed_lock); - } - - camel_object_trigger_event((CamelObject *)vf, "folder_changed", vf_changes); - camel_folder_change_info_free(vf_changes); - } -} - -static void -folder_changed_free(CamelSession *session, CamelSessionThreadMsg *msg) -{ - struct _folder_changed_msg *m = (struct _folder_changed_msg *)msg; - - camel_folder_change_info_free(m->changes); - camel_object_unref((CamelObject *)m->vf); - camel_object_unref((CamelObject *)m->sub); -} - -static CamelSessionThreadOps folder_changed_ops = { - folder_changed_change, - folder_changed_free, -}; - -static void -folder_changed(CamelFolder *sub, CamelFolderChangeInfo *changes, CamelVeeFolder *vf) -{ - struct _folder_changed_msg *m; - CamelSession *session = ((CamelService *)((CamelFolder *)vf)->parent_store)->session; - - m = camel_session_thread_msg_new(session, &folder_changed_ops, sizeof(*m)); - m->changes = camel_folder_change_info_new(); - camel_folder_change_info_cat(m->changes, changes); - m->sub = sub; - camel_object_ref((CamelObject *)sub); - m->vf = vf; - camel_object_ref((CamelObject *)vf); - camel_session_thread_queue(session, &m->msg, 0); -} - -/* track flag changes in the summary, we just promote it to a folder_changed event */ -static void -message_changed(CamelFolder *f, const char *uid, CamelVeeFolder *vf) -{ - CamelFolderChangeInfo *changes; - - changes = camel_folder_change_info_new(); - camel_folder_change_info_change_uid(changes, uid); - folder_changed(f, changes, vf); - camel_folder_change_info_free(changes); -} - -/* track vanishing folders */ -static void -subfolder_deleted(CamelFolder *f, void *event_data, CamelVeeFolder *vf) -{ - camel_vee_folder_remove_folder(vf, f); -} - - -static void -vee_freeze (CamelFolder *folder) -{ - CamelVeeFolder *vfolder = (CamelVeeFolder *) folder; - struct _CamelVeeFolderPrivate *p = _PRIVATE (vfolder); - GList *node; - - CAMEL_VEE_FOLDER_LOCK (vfolder, subfolder_lock); - - p->freeze_count++; - - node = p->folders; - while (node) { - CamelFolder *f = node->data; - - camel_folder_freeze (f); - node = node->next; - } - - CAMEL_VEE_FOLDER_UNLOCK (vfolder, subfolder_lock); - - /* call parent implementation */ - CAMEL_FOLDER_CLASS (camel_vee_folder_parent)->freeze (folder); -} - -static void -vee_thaw (CamelFolder *folder) -{ - CamelVeeFolder *vfolder = (CamelVeeFolder *) folder; - struct _CamelVeeFolderPrivate *p = _PRIVATE (vfolder); - GList *node; - - CAMEL_VEE_FOLDER_LOCK (vfolder, subfolder_lock); - - p->freeze_count--; - - node = p->folders; - while (node) { - CamelFolder *f = node->data; - - camel_folder_thaw (f); - node = node->next; - } - - CAMEL_VEE_FOLDER_UNLOCK (vfolder, subfolder_lock); - - /* call parent implementation */ - CAMEL_FOLDER_CLASS (camel_vee_folder_parent)->thaw (folder); -} diff --git a/camel/camel-vee-folder.h b/camel/camel-vee-folder.h deleted file mode 100644 index 3339b3a1d9..0000000000 --- a/camel/camel-vee-folder.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_VEE_FOLDER_H -#define _CAMEL_VEE_FOLDER_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include - -#define CAMEL_VEE_FOLDER(obj) CAMEL_CHECK_CAST (obj, camel_vee_folder_get_type (), CamelVeeFolder) -#define CAMEL_VEE_FOLDER_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_vee_folder_get_type (), CamelVeeFolderClass) -#define CAMEL_IS_VEE_FOLDER(obj) CAMEL_CHECK_TYPE (obj, camel_vee_folder_get_type ()) - -typedef struct _CamelVeeFolder CamelVeeFolder; -typedef struct _CamelVeeFolderClass CamelVeeFolderClass; - -/* our message info includes the parent folder */ -typedef struct _CamelVeeMessageInfo { - CamelMessageInfo info; - CamelFolder *folder; -} CamelVeeMessageInfo; - -struct _CamelVeeFolder { - CamelFolder parent; - - struct _CamelVeeFolderPrivate *priv; - - char *expression; /* query expression */ - char *vname; /* local name */ - - guint32 flags; /* folder open flags */ - - CamelFolderChangeInfo *changes; - CamelFolderSearch *search; -}; - -struct _CamelVeeFolderClass { - CamelFolderClass parent_class; -}; - -#define CAMEL_UNMATCHED_NAME "UNMATCHED" - -CamelType camel_vee_folder_get_type (void); -CamelFolder *camel_vee_folder_new (CamelStore *parent_store, const char *name, guint32 flags); -void camel_vee_folder_construct (CamelVeeFolder *vf, CamelStore *parent_store, const char *name, guint32 flags); - -CamelFolder *camel_vee_folder_get_location(CamelVeeFolder *vf, const CamelVeeMessageInfo *vinfo, char **realuid); - -void camel_vee_folder_add_folder (CamelVeeFolder *vf, CamelFolder *sub); -void camel_vee_folder_remove_folder (CamelVeeFolder *vf, CamelFolder *sub); -void camel_vee_folder_set_folders (CamelVeeFolder *vf, GList *folders); -void camel_vee_folder_set_expression (CamelVeeFolder *vf, const char *expr); - -void camel_vee_folder_hash_folder (CamelFolder *folder, char buffer[8]); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_VEE_FOLDER_H */ diff --git a/camel/camel-vee-store.c b/camel/camel-vee-store.c deleted file mode 100644 index b13522b8de..0000000000 --- a/camel/camel-vee-store.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "camel-exception.h" -#include "camel-vee-store.h" -#include "camel-vee-folder.h" - -#include "camel-private.h" - -#include - -#define d(x) - -static CamelFolder *vee_get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex); -static void vee_delete_folder(CamelStore *store, const char *folder_name, CamelException *ex); -static void vee_rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex); -static void vee_init_trash (CamelStore *store); -static CamelFolder *vee_get_trash (CamelStore *store, CamelException *ex); -static void vee_init_junk (CamelStore *store); -static CamelFolder *vee_get_junk (CamelStore *store, CamelException *ex); - -static CamelFolderInfo *vee_get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelException *ex); - -static void camel_vee_store_class_init (CamelVeeStoreClass *klass); -static void camel_vee_store_init (CamelVeeStore *obj); -static void camel_vee_store_finalise (CamelObject *obj); - -static CamelStoreClass *camel_vee_store_parent; - -CamelType -camel_vee_store_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_store_get_type (), "CamelVeeStore", - sizeof (CamelVeeStore), - sizeof (CamelVeeStoreClass), - (CamelObjectClassInitFunc) camel_vee_store_class_init, - NULL, - (CamelObjectInitFunc) camel_vee_store_init, - (CamelObjectFinalizeFunc) camel_vee_store_finalise); - } - - return type; -} - -static void -camel_vee_store_class_init (CamelVeeStoreClass *klass) -{ - CamelStoreClass *store_class = (CamelStoreClass *) klass; - - camel_vee_store_parent = (CamelStoreClass *)camel_store_get_type(); - - /* virtual method overload */ - store_class->get_folder = vee_get_folder; - store_class->rename_folder = vee_rename_folder; - store_class->delete_folder = vee_delete_folder; - store_class->get_folder_info = vee_get_folder_info; - store_class->free_folder_info = camel_store_free_folder_info_full; - - store_class->init_trash = vee_init_trash; - store_class->get_trash = vee_get_trash; - store_class->init_junk = vee_init_junk; - store_class->get_junk = vee_get_junk; -} - -static void -camel_vee_store_init (CamelVeeStore *obj) -{ - CamelStore *store = (CamelStore *)obj; - - /* we dont want a vtrash/vjunk on this one */ - store->flags &= ~(CAMEL_STORE_VTRASH | CAMEL_STORE_VJUNK); -} - -static void -camel_vee_store_finalise (CamelObject *obj) -{ - ; -} - -/** - * camel_vee_store_new: - * - * Create a new CamelVeeStore object. - * - * Return value: A new CamelVeeStore widget. - **/ -CamelVeeStore * -camel_vee_store_new (void) -{ - CamelVeeStore *new = CAMEL_VEE_STORE(camel_object_new(camel_vee_store_get_type ())); - return new; -} - -/* flags - 1 = delete (0 = add) - 2 = noselect -*/ -#define CHANGE_ADD (0) -#define CHANGE_DELETE (1) -#define CHANGE_NOSELECT (2) - -static void -change_folder(CamelStore *store, const char *name, guint32 flags, int count) -{ - CamelFolderInfo *fi; - const char *tmp; - - fi = g_malloc0(sizeof(*fi)); - fi->full_name = g_strdup(name); - tmp = strrchr(name, '/'); - if (tmp == NULL) - tmp = name; - else - tmp++; - fi->name = g_strdup(tmp); - fi->url = g_strdup_printf("vfolder:%s%s#%s", ((CamelService *)store)->url->path, (flags&CHANGE_NOSELECT)?";noselect=yes":"", name); - fi->unread_message_count = count; - camel_folder_info_build_path(fi, '/'); - camel_object_trigger_event(store, (flags&CHANGE_DELETE)?"folder_deleted":"folder_created", fi); - camel_folder_info_free(fi); -} - -static CamelFolder * -vee_get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) -{ - CamelVeeFolder *vf; - CamelFolder *folder; - char *name, *p; - - vf = (CamelVeeFolder *)camel_vee_folder_new(store, folder_name, flags); - if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) { - /* Check that parents exist, if not, create dummy ones */ - name = alloca(strlen(vf->vname)+1); - strcpy(name, vf->vname); - p = name; - while ( (p = strchr(p, '/'))) { - *p = 0; - - folder = camel_object_bag_get(store->folders, name); - if (folder == NULL) - change_folder(store, name, CHANGE_ADD|CHANGE_NOSELECT, -1); - else - camel_object_unref(folder); - *p++='/'; - } - - change_folder(store, vf->vname, CHANGE_ADD, camel_folder_get_message_count((CamelFolder *)vf)); - } - - return (CamelFolder *)vf; -} - -static void -vee_init_trash (CamelStore *store) -{ - /* no-op */ - ; -} - -static CamelFolder * -vee_get_trash (CamelStore *store, CamelException *ex) -{ - return NULL; -} - -static void -vee_init_junk (CamelStore *store) -{ - /* no-op */ - ; -} - -static CamelFolder * -vee_get_junk (CamelStore *store, CamelException *ex) -{ - return NULL; -} - -static CamelFolderInfo * -vee_get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *info; - GPtrArray *folders, *infos; - int i; - - infos = g_ptr_array_new(); - folders = camel_object_bag_list(store->folders); - for (i=0;ilen;i++) { - CamelVeeFolder *folder = folders->pdata[i]; - int add = FALSE; - char *name = ((CamelFolder *)folder)->full_name; - - /* check we have to include this one */ - if (top) { - if (flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) { - int namelen = strlen(name); - int toplen = strlen(top); - - add = ((namelen == toplen && - strcmp(name, top) == 0) - || ((namelen > toplen) - && strncmp(name, top, toplen) == 0 - && name[toplen] == '/')); - } else { - add = strcmp(name, top) == 0; - } - } else { - if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) == 0) - add = strchr(name, '/') == NULL; - } - - if (add) { - /* ensures unread is correct */ - if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) - camel_folder_refresh_info((CamelFolder *)folder, NULL); - - info = g_malloc0(sizeof(*info)); - info->url = g_strdup_printf("vfolder:%s#%s", ((CamelService *)((CamelFolder *)folder)->parent_store)->url->path, - ((CamelFolder *)folder)->full_name); - info->full_name = g_strdup(((CamelFolder *)folder)->full_name); - info->name = g_strdup(((CamelFolder *)folder)->name); - info->unread_message_count = camel_folder_get_unread_message_count((CamelFolder *)folder); - g_ptr_array_add(infos, info); - } - camel_object_unref(folder); - } - g_ptr_array_free(folders, TRUE); - - /* and always add UNMATCHED, if scanning from top/etc */ - if (top == NULL || top[0] == 0 || strncmp(top, CAMEL_UNMATCHED_NAME, strlen(CAMEL_UNMATCHED_NAME)) == 0) { - info = g_malloc0(sizeof(*info)); - info->url = g_strdup_printf("vfolder:%s#%s", ((CamelService *)store)->url->path, CAMEL_UNMATCHED_NAME); - info->full_name = g_strdup(CAMEL_UNMATCHED_NAME); - info->name = g_strdup(CAMEL_UNMATCHED_NAME); - info->unread_message_count = -1; - camel_folder_info_build_path(info, '/'); - g_ptr_array_add(infos, info); - } - - /* convert it into a tree */ - info = camel_folder_info_build(infos, (top&&top[0])?top:"", '/', TRUE); - g_ptr_array_free(infos, TRUE); - - return info; -} - -static void -vee_delete_folder(CamelStore *store, const char *folder_name, CamelException *ex) -{ - CamelFolder *folder; - - if (strcmp(folder_name, CAMEL_UNMATCHED_NAME) == 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot delete folder: %s: Invalid operation"), folder_name); - return; - } - - folder = camel_object_bag_get(store->folders, folder_name); - if (folder) { - camel_object_bag_remove(store->folders, folder); - - if (store->vtrash) - camel_vee_folder_remove_folder((CamelVeeFolder *)store->vtrash, folder); - if (store->vjunk) - camel_vee_folder_remove_folder((CamelVeeFolder *)store->vjunk, folder); - - if ((((CamelVeeFolder *)folder)->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) { - /* what about now-empty parents? ignore? */ - change_folder(store, folder_name, CHANGE_DELETE, -1); - } - - camel_object_unref(folder); - } else { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot delete folder: %s: No such folder"), folder_name); - } -} - -static void -vee_rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex) -{ - CamelFolder *folder; - - d(printf("vee rename folder '%s' '%s'\n", old, new)); - - if (strcmp(old, CAMEL_UNMATCHED_NAME) == 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot rename folder: %s: Invalid operation"), old); - return; - } - - /* See if it exists, for vfolders, all folders are in the folders hash */ - folder = camel_object_bag_get(store->folders, old); - if (folder == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot rename folder: %s: No such folder"), old); - } else { - camel_object_unref(folder); - } -} diff --git a/camel/camel-vee-store.h b/camel/camel-vee-store.h deleted file mode 100644 index d0352046be..0000000000 --- a/camel/camel-vee-store.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_VEE_STORE_H -#define _CAMEL_VEE_STORE_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include - -#define CAMEL_VEE_STORE(obj) CAMEL_CHECK_CAST (obj, camel_vee_store_get_type (), CamelVeeStore) -#define CAMEL_VEE_STORE_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_vee_store_get_type (), CamelVeeStoreClass) -#define CAMEL_IS_VEE_STORE(obj) CAMEL_CHECK_TYPE (obj, camel_vee_store_get_type ()) - -typedef struct _CamelVeeStore CamelVeeStore; -typedef struct _CamelVeeStoreClass CamelVeeStoreClass; - -/* open mode for folder, vee folder auto-update */ -#define CAMEL_STORE_VEE_FOLDER_AUTO (1<<16) - -struct _CamelVeeStore { - CamelStore parent; - -}; - -struct _CamelVeeStoreClass { - CamelStoreClass parent_class; -}; - -CamelType camel_vee_store_get_type (void); -CamelVeeStore *camel_vee_store_new (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_VEE_STORE_H */ diff --git a/camel/camel-vtrash-folder.c b/camel/camel-vtrash-folder.c deleted file mode 100644 index aa21ce3c4c..0000000000 --- a/camel/camel-vtrash-folder.c +++ /dev/null @@ -1,209 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#include - -#include "camel-exception.h" -#include "camel-vtrash-folder.h" -#include "camel-store.h" -#include "camel-vee-store.h" -#include "camel-mime-message.h" - -#include - -/* Returns the class for a CamelFolder */ -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static CamelVeeFolderClass *camel_vtrash_folder_parent; - -static void vtrash_append_message (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex); -static void vtrash_transfer_messages_to (CamelFolder *folder, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, CamelException *ex); - -static void -camel_vtrash_folder_class_init (CamelVTrashFolderClass *klass) -{ - CamelFolderClass *folder_class = (CamelFolderClass *) klass; - - camel_vtrash_folder_parent = CAMEL_VEE_FOLDER_CLASS(camel_vee_folder_get_type()); - - folder_class->append_message = vtrash_append_message; - folder_class->transfer_messages_to = vtrash_transfer_messages_to; -} - -static void -camel_vtrash_folder_init (CamelVTrashFolder *vtrash) -{ - CamelFolder *folder = CAMEL_FOLDER (vtrash); - - folder->folder_flags |= CAMEL_FOLDER_IS_TRASH; -} - -CamelType -camel_vtrash_folder_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_vee_folder_get_type (), - "CamelVTrashFolder", - sizeof (CamelVTrashFolder), - sizeof (CamelVTrashFolderClass), - (CamelObjectClassInitFunc) camel_vtrash_folder_class_init, - NULL, - (CamelObjectInitFunc) camel_vtrash_folder_init, - NULL); - } - - return type; -} - -/** - * camel_vtrash_folder_new: - * @parent_store: the parent CamelVeeStore - * @name: the vfolder name - * @ex: a CamelException - * - * Create a new CamelVeeFolder object. - * - * Return value: A new CamelVeeFolder widget. - **/ -CamelFolder * -camel_vtrash_folder_new (CamelStore *parent_store, const char *name) -{ - CamelFolder *vtrash; - - vtrash = (CamelFolder *)camel_object_new (camel_vtrash_folder_get_type ()); - camel_vee_folder_construct (CAMEL_VEE_FOLDER (vtrash), parent_store, name, - CAMEL_STORE_FOLDER_PRIVATE | CAMEL_STORE_FOLDER_CREATE | CAMEL_STORE_VEE_FOLDER_AUTO); - camel_vee_folder_set_expression((CamelVeeFolder *)vtrash, "(match-all (system-flag \"Deleted\"))"); - - return vtrash; -} - -static void -vtrash_append_message (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex) -{ - /* no-op */ -} - -struct _transfer_data { - CamelFolder *folder; - CamelFolder *dest; - GPtrArray *uids; - gboolean delete; -}; - -static void -transfer_messages(CamelFolder *folder, struct _transfer_data *md, CamelException *ex) -{ - int i; - - if (!camel_exception_is_set (ex)) - camel_folder_transfer_messages_to(md->folder, md->uids, md->dest, NULL, md->delete, ex); - - for (i=0;iuids->len;i++) - g_free(md->uids->pdata[i]); - g_ptr_array_free(md->uids, TRUE); - camel_object_unref((CamelObject *)md->folder); - g_free(md); -} - -static void -vtrash_transfer_messages_to (CamelFolder *source, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, CamelException *ex) -{ - CamelVeeMessageInfo *mi; - int i; - GHashTable *batch = NULL; - const char *tuid; - struct _transfer_data *md; - - /* This is a special case of transfer_messages_to: Either the - * source or the destination is a vtrash folder (but not both - * since a store should never have more than one). - */ - - if (transferred_uids) - *transferred_uids = NULL; - - if (CAMEL_IS_VTRASH_FOLDER (dest)) { - /* Copy to trash is meaningless. */ - if (!delete_originals) - return; - - /* Move to trash is the same as deleting the message */ - for (i = 0; i < uids->len; i++) - camel_folder_delete_message (source, uids->pdata[i]); - return; - } - - g_return_if_fail (CAMEL_IS_VTRASH_FOLDER (source)); - - /* Moving/Copying from the trash to the original folder = undelete. - * Moving/Copying from the trash to a different folder = move/copy. - * - * Need to check this uid by uid, but we batch up the copies. - */ - - for (i = 0; i < uids->len; i++) { - mi = (CamelVeeMessageInfo *)camel_folder_get_message_info (source, uids->pdata[i]); - if (mi == NULL) { - g_warning ("Cannot find uid %s in source folder during transfer", (char *) uids->pdata[i]); - continue; - } - - if (dest == mi->folder) { - /* Just undelete the original message */ - camel_folder_set_message_flags (source, uids->pdata[i], CAMEL_MESSAGE_DELETED, 0); - } else { - if (batch == NULL) - batch = g_hash_table_new(NULL, NULL); - md = g_hash_table_lookup(batch, mi->folder); - if (md == NULL) { - md = g_malloc0(sizeof(*md)); - md->folder = mi->folder; - camel_object_ref((CamelObject *)md->folder); - md->uids = g_ptr_array_new(); - md->dest = dest; - g_hash_table_insert(batch, mi->folder, md); - } - - tuid = uids->pdata[i]; - if (strlen(tuid)>8) - tuid += 8; - g_ptr_array_add(md->uids, g_strdup(tuid)); - } - camel_folder_free_message_info (source, (CamelMessageInfo *)mi); - } - - if (batch) { - g_hash_table_foreach(batch, (GHFunc)transfer_messages, ex); - g_hash_table_destroy(batch); - } -} diff --git a/camel/camel-vtrash-folder.h b/camel/camel-vtrash-folder.h deleted file mode 100644 index 089c969e71..0000000000 --- a/camel/camel-vtrash-folder.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - - -#ifndef _CAMEL_VTRASH_FOLDER_H -#define _CAMEL_VTRASH_FOLDER_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include - -#define CAMEL_VTRASH_NAME "Trash" -#define CAMEL_VJUNK_NAME "Junk" - -#define CAMEL_VTRASH_FOLDER(obj) CAMEL_CHECK_CAST (obj, camel_vtrash_folder_get_type (), CamelVTrashFolder) -#define CAMEL_VTRASH_FOLDER_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_vtrash_folder_get_type (), CamelVTrashFolderClass) -#define CAMEL_IS_VTRASH_FOLDER(obj) CAMEL_CHECK_TYPE (obj, camel_vtrash_folder_get_type ()) - -typedef struct _CamelVTrashFolder CamelVTrashFolder; -typedef struct _CamelVTrashFolderClass CamelVTrashFolderClass; - -struct _CamelVTrashFolder { - CamelVeeFolder parent; - -}; - -struct _CamelVTrashFolderClass { - CamelVeeFolderClass parent_class; - -}; - -CamelType camel_vtrash_folder_get_type (void); - -CamelFolder *camel_vtrash_folder_new (CamelStore *parent_store, const char *name); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_VTRASH_FOLDER_H */ diff --git a/camel/camel.c b/camel/camel.c deleted file mode 100644 index ae99da74c2..0000000000 --- a/camel/camel.c +++ /dev/null @@ -1,115 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * Bertrand Guiheneuf - * - * Copyright 1999-2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#ifdef HAVE_NSS -#include -#include -#include "nss.h" /* Don't use <> here or it will include the system nss.h instead */ -#include -#endif /* HAVE_NSS */ - -#include "camel.h" -#include "camel-certdb.h" -#include "camel-mime-utils.h" - -gboolean camel_verbose_debug = FALSE; - -static void -camel_shutdown (void) -{ - CamelCertDB *certdb; - -#ifdef HAVE_NSS - NSS_Shutdown (); - - PR_Cleanup (); -#endif /* HAVE_NSS */ - - certdb = camel_certdb_get_default (); - if (certdb) { - camel_certdb_save (certdb); - camel_object_unref (certdb); - } -} - -int -camel_init (const char *configdir, gboolean nss_init) -{ - CamelCertDB *certdb; - char *path; - void camel_operation_init(void); - - if (getenv ("CAMEL_VERBOSE_DEBUG")) - camel_verbose_debug = TRUE; - - /* initialise global camel_object_type */ - camel_object_get_type (); - - camel_mime_utils_init (); - camel_operation_init(); - -#ifdef HAVE_NSS - if (nss_init) { - PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 10); - - if (NSS_InitReadWrite (configdir) == SECFailure) { - /* fall back on using volatile dbs? */ - if (NSS_NoDB_Init (configdir) == SECFailure) { - g_warning ("Failed to initialize NSS"); - return -1; - } - } - - NSS_SetDomesticPolicy (); - - SSL_OptionSetDefault (SSL_ENABLE_SSL2, PR_TRUE); - SSL_OptionSetDefault (SSL_ENABLE_SSL3, PR_TRUE); - SSL_OptionSetDefault (SSL_ENABLE_TLS, PR_TRUE); - SSL_OptionSetDefault (SSL_V2_COMPATIBLE_HELLO, PR_TRUE /* maybe? */); - } -#endif /* HAVE_NSS */ - - path = g_strdup_printf ("%s/camel-cert.db", configdir); - certdb = camel_certdb_new (); - camel_certdb_set_filename (certdb, path); - g_free (path); - - /* if we fail to load, who cares? it'll just be a volatile certdb */ - camel_certdb_load (certdb); - - /* set this certdb as the default db */ - camel_certdb_set_default (certdb); - - camel_object_unref (certdb); - - g_atexit (camel_shutdown); - - return 0; -} diff --git a/camel/camel.h b/camel/camel.h deleted file mode 100644 index 9aba4ebd1a..0000000000 --- a/camel/camel.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * - * Author : - * Bertrand Guiheneuf - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_H -#define CAMEL_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -gint camel_init (const char *certdb_dir, gboolean nss_init); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_H */ diff --git a/camel/devel-docs/camel-index.txt b/camel/devel-docs/camel-index.txt deleted file mode 100644 index 0ebc250db0..0000000000 --- a/camel/devel-docs/camel-index.txt +++ /dev/null @@ -1,407 +0,0 @@ - -The history of text-indexing in evolution. - -CamelTextIndex was written to address several shortcomings in the -existing libibex (referred to as libibex2), which had been written to -address shortcomings in the original libibex. - -Mail indexing characteristics - -First, i'll cover some of the scenarios that a mail indexing system -must cover. They are slightly different from other indexing systems, -at least we wanted them to be. - -1. Indexing a few new messages, they may potentially reference most of - the alphabet in the index. -2. Indexing a whole mailbox for the first time -3. Unindexing anywhere from a few to all existing messages during expunge. -4. Searching. - -Cases 1, 3, and 4 occur the most often, however 2 is the most noticeable -at first use, or if the index must be reset. So the code needs to -work fast in all cases, which generally leads to trade-offs being -made. Each implementation aimed to address or ignore these -requirements in different ways, with the final implementation probably -having the best balance so far. - -The main issue is that the indexing be performed real time. We index -as we add the messages. We index before we open the mailbox. We -index as we remove messages. Because of this we need to approach -things differently to many other indexing systems; most of which work -with static data in an off-line mode. This allows them to index the -whole body of content and use as much memory and cpu time as required. - -We probably need to look at doing offline, or at least delayed -indexing in the future - but this introduces some coherency problems -with vFolders and any body searches. However, having the indexing -library a base part of Camel helps in implementing a mechanism to -achieve this. - -Ibex the first - -The original ibex used a memory-based hash table to store words. This made -the index very fast for both lookups and modifications. However any -queries required a full load of the index into memory, and any updates -required a full write of the index to disk. After about 5-10 000 -messages occasionaly adding to the index became appreciably slower as -the whole index needed to be loaded into memory first. This obviously -took a toll on memory as well. - -I wont cover the algorithms used, they were all pretty basic, the only -real smarts were that index deletes were only flagged and that data -not written to disk when the index saved. - -Evolution 1.x, ibex 2. - -In an attempt to rectify the incremental update performance of -libibex, it was completely rewritten to use an on-disk block-based -filesystem. - -Note: the first attempt used libdb - however performance was so slow -and the indices were so large it was dropped in favour of a custom -filesystem-like data file. - -The motivation was that a few extra disk lookups during -retrieval wouldn't be noticeably slower, however it should be able to -scale up to many more messages with lower memory overhead and slower -startup time. - -The block filesystem contains 3 major components: - -1. A hash table that mapped message's to a word id sequence list. -2. A hash table that mapped word's to a message id sequence list. -3. A sequence filesystem that stored sequences of id's. - -The id's are 32 bit identifiers that are unique for each word or -message. They are also designed to be reversible and static. -That is, given the id, you can map it to the string identifier that it -represents directly, without having to look it up in the hash table. - -Other features of this design is that the database file should be -kept in sync at all times with the state of the index. The message to -wordid tables are used to remove the messageid's from the word's it -contains when the message is expunged, and so on. - -Indexing operation - -The indexing operation consists of the basic steps: - -1. Lookup the messageid from the message name, using the messageid table. -2. Generate a list of words in the message -3. For each word: -4. Lookup the wordid and sequence information -5. If the word doesn't exist, create a new word/wordid -6. Add the messageid to the word sequence. -7. Add the wordid to the message sequence. - -The initial implementation only used caching at the disk-block level. -Unfortunately, the simple hash table design chosen (fixed sized base -table with chained buckets) scaled very poorly above about 10 000 -messages. So this approach proved to be too i/o intensive for -practical use, and several other caches were added to improve -performance: - -1. Stage (1) above is done entirely in memory. At initial startup - the whole list of potential names is read into an in-memory hash - table. -2. Stage (4) above is also done entirely in memory. Even a large - cache provided little benefit due to wide distribution of potential - words. This cache is only created when adding to the index. -3. Stage (6) uses the table from stage (4) and concatenates upto - approximately one disk blocks worth of messageid's before writing - them out to the word sequence. -4. Stage (7) concatenates all wordid's for a given message before - writing them out at once. - -As you can see, the added complexity meant we nearly have to cache as -much as the original version! This also almost removed all of the -startup-time benefit for incremental update of the index, as the table -was not stored as compactly on disk as the original version. - -However, we only ever stored a subset of the index in memory, and only -during updates, with some tricks to reduce memory usage for very rare -words, so the overall memory use was still much lower. - -Removing a message - -Removing a message is fairly involved: - -1. Lookup the messageid and word sequence list from the messageid table. -2. For each wordid in the sequence list -3. Lookup the message sequence list directly from the wordid table. -4. Scan each block in the sequence, and remove any instances of the - messageid. -5. Remove the message to messageid mapping in the messageid table. - -Unfortunately caching helped very little here, particularly if many -messages were removed. Also note that the file could never shrink as -the data could be spread randomly over it. Removal is an extremely -expensive an unbounded process. Deleting all of the messages in a -mailbox is extremely i/o intensive, with blocks potentially being -accessed dozens of times. - -Performing a query - -Performing a query is fast: - -1. Lookup the messageid sequence list from the wordid table. -2. For each messageid -3. Lookup the message name directly from the messageid table. - -Even without caching this performs at a very acceptable level. - -Summary - -This index performs reasonably well upto about 10 000 messages for a -complete re-index. However with incremental updates it degrads much -faster, only a few thousand messages added and it becomes tiresomely -slow and i/o bound. The index becomes more fragmented with random -updates and removals and heavily bogs down the system as you go much -beyond those few thousand messages. - -The code is also very complicated and hard to follow. There are too -many special cases, and it is buggy. Detected on-disk structure -errors result in the index being reset, which although it shrinks the -index, is very slow. - -The indices created are bulky, and never shrink. Because of the -reverse index used for message removal, there is 50% redundant data at -all times. Some overly tricky techniques (very much like ReiserFS's -tail packing) are used to waste as little space as possible, with a -great impact on performance. - -One other problem is that because the index is disk based, we -use a file descriptor continuously. With some users having ->100 folders, they quickly run out of process file descriptors and -evolution fails. To get around this a cache of least recently used -index files is used to flush away and free file descriptors so they -can be re-used. This makes it hard to lock the files; this problem -still exists with the next implementation. - -Anyway, a better solution is required. - -CamelIndex - -The first problem to address was the api. It was starting to age. -Although adequate, the api wasn't terribly clean, reusable, or -scalable. The first thing was to objectise the library, and since we -needed to use it in Camel, the best way was to create a CamelObject. - -CamelIndex was born. A mostly abstract class that provides a simple -common interface for accessing indices, including cursors and utility -and maintenance functions. - -In addition, a number of the features in libibex2 were simplified or -rewritten and abstracted into the re-usable classes that follow. - -By providing simple cursors, more complex queries were easier to write -and can execute more efficiently; camel searching now does sub-string -searches for all body queries, and still runs at a very healthy speed -and uses less memory than before. - -CamelBlockFile - -This is basically the same block filesystem used in libibex2. It -handles disk i/o based on blocks (CamelBlock), flushing modified -blocks to disk, and caching of recently accessed blocks. It was -enhanced slightly to allow blocks to be locked in memory. - -CamelKeyFile - -This is a simple reverse-linked list of sequences of keyid's. - -The main property of this file is that updates are only ever appended -to the end of the file, which improves i/o characteristics markedly. - -When an existing keyid sequence is updated, it simply points back to -the start of the previous one, and provides a pointer to the new -entry. i.e. a simple linked list. - -CamelKeyTable - -This is taken from the libibex2 code for mapping keys, with few -changes. It uses a CamelBlockFile for its i/o. - -The key table is a linked list of blocks (CamelKeyBlock) which contain -key strings and and a data pointer and flags for each key. Each block -is a packed array of string descriptors (CamelKeyKey's). - -A keyid (camel_key_t) is a 32 bit descriptor which identifies this key -in a reversible way. In this case the bottom 10 bits are used to -identify the index of the key within the key block, and the top 22 -bits are used to identify the key block itself. In this way, given -the 32 bit key id, we can reference the block containing the key -directly (with at most 1 access), and access the flags and key string -using the key index. - -Keys can potentially be removed and their keyid's reused by simply -re-packing the key block. This was used in libibex2, but not in -CamelIndex. - -[diagram - camelkeyblock] - -CamelPartitionTable - -An implementation of a scalable, on-disk 'perfect' hash table. It -uses the CamelBlockFile to handle its i/o. This is a completely new -hash table implementation which was not present in libibex2. - -[FIXME: Reference the original paper the algorithm is based on.] - -A partition table consists of a list of mapping blocks -(CamelPartitionMapBlock), which is a compact table that maps a range -of hashid's to a partition block (CamelPartitionKeyBlock), which -contains hashid's of that range. - -[diagram - camelpartitiontable] - -The partition block only maps the hashid to a keyid (see CamelKeyTable) -which means it can store a lot of keys in each block. - -To add a new value to the partition table: - -1. Calculate the hash value of the key -2. Find out which partition block the key will fit into, using the - partition table. -3. If the partition block is full: -4. If there is room in the next or previous block: -5. Merge the 2 blocks together, and split at the half-way point -6. Update the partition table hash indices to match the blocks -7. Else -8. Create a new block, and split the existing block across it -9. Insert the new block into the partition table -10. Else -11. Just add the key to the end of the block. - -Steps 5 and 8 perform a sorting of the partition key entries by hashid -to find the midpoint. It may be beneficial to store the hashid's -sorted always, it would then not require a sort to split the blocks. -This would also benefit key lookups by being able to use a binary -search. However, the incremental sort may be more expensive. - -If the partition table itself fills up, then perform a similar -splitting function on its blocks, and store it over multiple blocks. -With a block size of 1024 bytes, we can fit 127 blocks pointers, each -with 127 keys in it - around 16000 keys. So we only need 1024 bytes -of memory for each 16000 on-disk keys (assuming full tables). - -Removal is basically the same, but if we end up with an empty block we -just remove it from the partition table. CamelTextIndex doesn't -actually use removal although it is implemented in -CamelPartitionTable. - -Lookup is very simple. We basically follow steps 1 and 2, and then -perform a linear search through the block to find a matching hash id. -That is our key. This is assuming a perfect hash, additionally the -code could use the keyid to lookup in a keytable to verify the key is -indeed the right one. This would require having to support duplicate -hashid's and would make block splitting slightly more complex, but -only by a couple of lines of code. This is something that will -probably have to be addressed in the future. - -Using a partition table means that we can tell with 1 disk access -whether or not a key exists (assuming a perfect hash function), and 1 -more access to look up all of the details of the key since the keyid -is reversible. Another feature is that the partition table is always -self-balancing for any data processed in any order. - -Yet one more feature is that it is quite easy to order the writes to -the partition table so that its structure is always consistent, even -in the event of program failure. Although this has been disabled in -the current code to take maximal advantage of the block cache. - -CamelTextIndex - -CamelTextIndex is the implementation of CamelIndex now used by camel -for indexing mail. It shares some features with the second -incarnation of libibex, but is generally simpler. It uses the -previously described classes to implement the CamelIndex interface. - -Indexing operation - -Indexing operation is similar to libibex2, but without the requirement -to maintain the reverse index. - -1. Lookup the messageid from the message name, using the messageid - partition table. -2. Generate a list of words in the message -3. For each word -4. Lookup the wordid and sequence information. -5. Append the messageid to the word sequence. - -In practice we also have a word cache which caches upto 32 messageid's -for each word before it is written to the key file. - -Removing a message - -Removal is not immediate. This is one of the major performance -improvements in CamelIndex. - -1. Lookup the messageid from the message name partition table -2. Use the messageid to set a flag in the message key table to - indicate the message has been deleted. -3. Remove the key hash from the partition table. - -This comes down to a maximum of 2 disk reads and 2 disk writes. -libibex2 had unbounded maximums, depending on the number of words in a -given message. The key file is not changed. - -Because data is not removed from the files at all, an additional -optional step is required, that of compressing the indices. - -Performing a query - -Performing a query is much the same as with libibex2. We usually have -slightly less disk i/o because of a more efficient and scalable hash -table implementation, and improved locality of reference of the key -table data. - -1. Lookup the messageid from the message name partition table -2. Use the messageid to get the data pointer directly from the key - table. -3. Iterate through the key file, reading blocks backwards through the - file. - -Compressing - -Although it could have benefited from it, libibex2 did not ever -compress indices - the only way to compress an index was to remove it -and have it be rebuilt. - -CamelIndex requires a compression stage as data is never removed from -it otherwise. Because of the much greater locality of reference, the -compression stage is actually much faster than an incremental removal -of data inside the data files. - -Compressing comprises the following steps: - -1. Open a new temporary index, an index block file and an index key - file. -2. For each message in the message partition table -3. If the message is not marked deleted, add it to the new message - partition table, and recored the old messageid to new messageid - mapping. -4. For each word in the word partition table -5. For each messageid's in the word sequence list -6. If the messageid maps to a new messageid, remap the messageid, - else discard it. -7. Concatenate upto 256 messageid's in a row before writing to the - key file, to improve lookups. -8. Create a new word in the new word key table -9. Add the wordid and new sequence id to the word partition table. - -Note that at step 8 we could (should?) also check if the word has any -messages associated with it, and discard the word from the new index. - -After compression, the name partition index only contains names which -are not deleted, and the key file is compressed into larger blocks -which takes up less space and is faster to retrieve. - -During index operations a number of statistics are taken which trigger -an automatic compress when the file fragmentation or number of deleted -messages exceed a threshold. So the index maintains itself, and does -not need manual compression. - - - - diff --git a/camel/devel-docs/camel_data_wrapper.dia b/camel/devel-docs/camel_data_wrapper.dia deleted file mode 100644 index 301563d1ee..0000000000 Binary files a/camel/devel-docs/camel_data_wrapper.dia and /dev/null differ diff --git a/camel/devel-docs/camel_parser_states.dia b/camel/devel-docs/camel_parser_states.dia deleted file mode 100644 index 556a5b1c49..0000000000 Binary files a/camel/devel-docs/camel_parser_states.dia and /dev/null differ diff --git a/camel/devel-docs/camel_stream.dia b/camel/devel-docs/camel_stream.dia deleted file mode 100644 index d91d1bb153..0000000000 Binary files a/camel/devel-docs/camel_stream.dia and /dev/null differ diff --git a/camel/providers/.cvsignore b/camel/providers/.cvsignore deleted file mode 100644 index 3dda72986f..0000000000 --- a/camel/providers/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -Makefile.in -Makefile diff --git a/camel/providers/Makefile.am b/camel/providers/Makefile.am deleted file mode 100644 index 119966aacb..0000000000 --- a/camel/providers/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ -## Process this file with automake to produce Makefile.in - -if ENABLE_NNTP -NNTP_DIR=nntp -endif - -if ENABLE_IMAPP -IMAPP_DIR=imapp -endif - -SUBDIRS = pop3 sendmail smtp imap $(NNTP_DIR) local $(IMAPP_DIR) - diff --git a/camel/providers/imap/.cvsignore b/camel/providers/imap/.cvsignore deleted file mode 100644 index 3fa8afaa38..0000000000 --- a/camel/providers/imap/.cvsignore +++ /dev/null @@ -1,11 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/imap/Makefile.am b/camel/providers/imap/Makefile.am deleted file mode 100644 index 1a2f46faf9..0000000000 --- a/camel/providers/imap/Makefile.am +++ /dev/null @@ -1,48 +0,0 @@ -## Process this file with automake to produce Makefile.in - -libcamelimapincludedir = $(privincludedir)/camel - -camel_provider_LTLIBRARIES = libcamelimap.la -camel_provider_DATA = libcamelimap.urls - -INCLUDES = -I.. \ - -I$(srcdir)/.. \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir) \ - $(CAMEL_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(GTK_INCLUDEDIR) \ - -DG_LOG_DOMAIN=\"camel-imap-provider\" - -libcamelimap_la_SOURCES = \ - camel-imap-command.c \ - camel-imap-folder.c \ - camel-imap-message-cache.c \ - camel-imap-provider.c \ - camel-imap-search.c \ - camel-imap-store.c \ - camel-imap-store-summary.c \ - camel-imap-summary.c \ - camel-imap-utils.c \ - camel-imap-wrapper.c - -libcamelimapinclude_HEADERS = \ - camel-imap-command.h \ - camel-imap-folder.h \ - camel-imap-message-cache.h \ - camel-imap-search.h \ - camel-imap-store.h \ - camel-imap-store-summary.h \ - camel-imap-summary.h \ - camel-imap-types.h \ - camel-imap-utils.h \ - camel-imap-wrapper.h - -libcamelimap_la_LDFLAGS = -avoid-version -module - -noinst_HEADERS = \ - camel-imap-private.h - -EXTRA_DIST = libcamelimap.urls diff --git a/camel/providers/imap/camel-imap-command.c b/camel/providers/imap/camel-imap-command.c deleted file mode 100644 index 45e5751b87..0000000000 --- a/camel/providers/imap/camel-imap-command.c +++ /dev/null @@ -1,822 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-command.c: IMAP command sending/parsing routines */ - -/* - * Authors: - * Dan Winship - * Jeffrey Stedfast - * - * Copyright 2000, 2001 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "camel-imap-command.h" -#include "camel-imap-utils.h" -#include "camel-imap-folder.h" -#include "camel-imap-store.h" -#include "camel-imap-store-summary.h" -#include "camel-imap-private.h" -#include -#include -#include -#include - - -extern int camel_verbose_debug; - -static gboolean imap_command_start (CamelImapStore *store, CamelFolder *folder, - const char *cmd, CamelException *ex); -CamelImapResponse *imap_read_response (CamelImapStore *store, - CamelException *ex); -static char *imap_read_untagged (CamelImapStore *store, char *line, - CamelException *ex); -static char *imap_command_strdup_vprintf (CamelImapStore *store, - const char *fmt, va_list ap); -static char *imap_command_strdup_printf (CamelImapStore *store, - const char *fmt, ...); - -/** - * camel_imap_command: - * @store: the IMAP store - * @folder: The folder to perform the operation in (or %NULL if not - * relevant). - * @ex: a CamelException - * @fmt: a sort of printf-style format string, followed by arguments - * - * This function calls camel_imap_command_start() to send the - * command, then reads the complete response to it using - * camel_imap_command_response() and returns a CamelImapResponse - * structure. - * - * As a special case, if @fmt is %NULL, it will just select @folder - * and return the response from doing so. - * - * See camel_imap_command_start() for details on @fmt. - * - * On success, the store's connect_lock will be locked. It will be freed - * when you call camel_imap_response_free. (The lock is recursive, so - * callers can grab and release it themselves if they need to run - * multiple commands atomically.) - * - * Return value: %NULL if an error occurred (in which case @ex will - * be set). Otherwise, a CamelImapResponse describing the server's - * response, which the caller must free with camel_imap_response_free(). - **/ -CamelImapResponse * -camel_imap_command (CamelImapStore *store, CamelFolder *folder, - CamelException *ex, const char *fmt, ...) -{ - va_list ap; - char *cmd; - - CAMEL_SERVICE_LOCK (store, connect_lock); - - if (fmt) { - va_start (ap, fmt); - cmd = imap_command_strdup_vprintf (store, fmt, ap); - va_end (ap); - } else { - if (store->current_folder) { - camel_object_unref (CAMEL_OBJECT (store->current_folder)); - store->current_folder = NULL; - } - store->current_folder = folder; - camel_object_ref (CAMEL_OBJECT (folder)); - cmd = imap_command_strdup_printf (store, "SELECT %F", - folder->full_name); - } - - if (!imap_command_start (store, folder, cmd, ex)) { - g_free (cmd); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return NULL; - } - g_free (cmd); - - return imap_read_response (store, ex); -} - -/** - * camel_imap_command_start: - * @store: the IMAP store - * @folder: The folder to perform the operation in (or %NULL if not - * relevant). - * @ex: a CamelException - * @fmt: a sort of printf-style format string, followed by arguments - * - * This function makes sure that @folder (if non-%NULL) is the - * currently-selected folder on @store and then sends the IMAP command - * specified by @fmt and the following arguments. - * - * @fmt can include the following %-escapes ONLY: - * %s, %d, %%: as with printf - * %S: an IMAP "string" (quoted string or literal) - * %F: an IMAP folder name - * - * %S strings will be passed as literals if the server supports LITERAL+ - * and quoted strings otherwise. (%S does not support strings that - * contain newlines.) - * - * %F will have the imap store's namespace prepended and then be processed - * like %S. - * - * On success, the store's connect_lock will be locked. It will be - * freed when %CAMEL_IMAP_RESPONSE_TAGGED or %CAMEL_IMAP_RESPONSE_ERROR - * is returned from camel_imap_command_response(). (The lock is - * recursive, so callers can grab and release it themselves if they - * need to run multiple commands atomically.) - * - * Return value: %TRUE if the command was sent successfully, %FALSE if - * an error occurred (in which case @ex will be set). - **/ -gboolean -camel_imap_command_start (CamelImapStore *store, CamelFolder *folder, - CamelException *ex, const char *fmt, ...) -{ - va_list ap; - char *cmd; - gboolean ok; - - va_start (ap, fmt); - cmd = imap_command_strdup_vprintf (store, fmt, ap); - va_end (ap); - - CAMEL_SERVICE_LOCK (store, connect_lock); - ok = imap_command_start (store, folder, cmd, ex); - g_free (cmd); - - if (!ok) - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return ok; -} - -static gboolean -imap_command_start (CamelImapStore *store, CamelFolder *folder, - const char *cmd, CamelException *ex) -{ - ssize_t nwritten; - - /* Check for current folder */ - if (folder && folder != store->current_folder) { - CamelImapResponse *response; - CamelException internal_ex; - - response = camel_imap_command (store, folder, ex, NULL); - if (!response) - return FALSE; - camel_exception_init (&internal_ex); - camel_imap_folder_selected (folder, response, &internal_ex); - camel_imap_response_free (store, response); - if (camel_exception_is_set (&internal_ex)) { - camel_exception_xfer (ex, &internal_ex); - return FALSE; - } - } - - /* Send the command */ - if (camel_verbose_debug) { - const char *mask; - - if (!strncmp ("LOGIN \"", cmd, 7)) - mask = "LOGIN \"xxx\" xxx"; - else if (!strncmp ("LOGIN {", cmd, 7)) - mask = "LOGIN {N+}\r\nxxx {N+}\r\nxxx"; - else if (!strncmp ("LOGIN ", cmd, 6)) - mask = "LOGIN xxx xxx"; - else - mask = cmd; - - fprintf (stderr, "sending : %c%.5d %s\r\n", store->tag_prefix, store->command, mask); - } - - nwritten = camel_stream_printf (store->ostream, "%c%.5d %s\r\n", - store->tag_prefix, store->command++, cmd); - - if (nwritten == -1) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Operation cancelled")); - else - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - g_strerror (errno)); - - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - return FALSE; - } - - return TRUE; -} - -/** - * camel_imap_command_continuation: - * @store: the IMAP store - * @cmd: buffer containing the response/request data - * @cmdlen: command length - * @ex: a CamelException - * - * This method is for sending continuing responses to the IMAP server - * after camel_imap_command() or camel_imap_command_response() returns - * a continuation response. - * - * This function assumes you have an exclusive lock on the imap stream. - * - * Return value: as for camel_imap_command(). On failure, the store's - * connect_lock will be released. - **/ -CamelImapResponse * -camel_imap_command_continuation (CamelImapStore *store, const char *cmd, - size_t cmdlen, CamelException *ex) -{ - if (!camel_imap_store_connected (store, ex)) - return NULL; - - if (camel_stream_write (store->ostream, cmd, cmdlen) == -1 || - camel_stream_write (store->ostream, "\r\n", 2) == -1) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Operation cancelled")); - else - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - g_strerror (errno)); - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return NULL; - } - - return imap_read_response (store, ex); -} - -/** - * camel_imap_command_response: - * @store: the IMAP store - * @response: a pointer to pass back the response data in - * @ex: a CamelException - * - * This reads a single tagged, untagged, or continuation response from - * @store into *@response. The caller must free the string when it is - * done with it. - * - * Return value: One of %CAMEL_IMAP_RESPONSE_CONTINUATION, - * %CAMEL_IMAP_RESPONSE_UNTAGGED, %CAMEL_IMAP_RESPONSE_TAGGED, or - * %CAMEL_IMAP_RESPONSE_ERROR. If either of the last two, @store's - * command lock will be unlocked. - **/ -CamelImapResponseType -camel_imap_command_response (CamelImapStore *store, char **response, - CamelException *ex) -{ - CamelImapResponseType type; - char *respbuf; - - if (camel_imap_store_readline (store, &respbuf, ex) < 0) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return CAMEL_IMAP_RESPONSE_ERROR; - } - - switch (*respbuf) { - case '*': - if (!strncasecmp (respbuf, "* BYE", 5)) { - /* Connection was lost, no more data to fetch */ - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Server unexpectedly disconnected: %s"), - _("Unknown error")); /* g_strerror (104)); FIXME after 1.0 is released */ - store->connected = FALSE; - g_free (respbuf); - respbuf = NULL; - type = CAMEL_IMAP_RESPONSE_ERROR; - break; - } - - /* Read the rest of the response. */ - type = CAMEL_IMAP_RESPONSE_UNTAGGED; - respbuf = imap_read_untagged (store, respbuf, ex); - if (!respbuf) - type = CAMEL_IMAP_RESPONSE_ERROR; - else if (!strncasecmp (respbuf, "* OK [ALERT]", 12)) { - char *msg; - - /* for imap ALERT codes, account user@host */ - msg = g_strdup_printf(_("Alert from IMAP server %s@%s:\n%s"), - ((CamelService *)store)->url->user, ((CamelService *)store)->url->host, respbuf+12); - camel_session_alert_user(((CamelService *)store)->session, CAMEL_SESSION_ALERT_WARNING, msg, FALSE); - g_free(msg); - } - - break; - case '+': - type = CAMEL_IMAP_RESPONSE_CONTINUATION; - break; - default: - type = CAMEL_IMAP_RESPONSE_TAGGED; - break; - } - *response = respbuf; - - if (type == CAMEL_IMAP_RESPONSE_ERROR || - type == CAMEL_IMAP_RESPONSE_TAGGED) - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - return type; -} - -CamelImapResponse * -imap_read_response (CamelImapStore *store, CamelException *ex) -{ - CamelImapResponse *response; - CamelImapResponseType type; - char *respbuf, *p; - - /* Get another lock so that when we reach the tagged - * response and camel_imap_command_response unlocks, - * we're still locked. This lock is owned by response - * and gets unlocked when response is freed. - */ - CAMEL_SERVICE_LOCK (store, connect_lock); - - response = g_new0 (CamelImapResponse, 1); - if (store->current_folder && camel_disco_store_status (CAMEL_DISCO_STORE (store)) != CAMEL_DISCO_STORE_RESYNCING) { - response->folder = store->current_folder; - camel_object_ref (CAMEL_OBJECT (response->folder)); - } - - response->untagged = g_ptr_array_new (); - while ((type = camel_imap_command_response (store, &respbuf, ex)) - == CAMEL_IMAP_RESPONSE_UNTAGGED) - g_ptr_array_add (response->untagged, respbuf); - - if (type == CAMEL_IMAP_RESPONSE_ERROR) { - camel_imap_response_free_without_processing (store, response); - return NULL; - } - - response->status = respbuf; - - /* Check for OK or continuation response. */ - if (*respbuf == '+') - return response; - p = strchr (respbuf, ' '); - if (p && !strncasecmp (p, " OK", 3)) - return response; - - /* We should never get BAD, or anything else but +, OK, or NO - * for that matter. - */ - if (!p || strncasecmp (p, " NO", 3) != 0) { - g_warning ("Unexpected response from IMAP server: %s", - respbuf); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Unexpected response from IMAP " - "server: %s"), respbuf); - camel_imap_response_free_without_processing (store, response); - return NULL; - } - - p += 3; - if (!*p++) - p = NULL; - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("IMAP command failed: %s"), - p ? p : _("Unknown error")); - camel_imap_response_free_without_processing (store, response); - return NULL; -} - -/* Given a line that is the start of an untagged response, read and - * return the complete response, which may include an arbitrary number - * of literals. - */ -static char * -imap_read_untagged (CamelImapStore *store, char *line, CamelException *ex) -{ - int fulllen, ldigits, nread, i; - unsigned int length; - GPtrArray *data; - GString *str; - char *end, *p, *s, *d; - - p = strrchr (line, '{'); - if (!p) - return line; - - data = g_ptr_array_new (); - fulllen = 0; - - while (1) { - str = g_string_new (line); - g_free (line); - fulllen += str->len; - g_ptr_array_add (data, str); - - p = strrchr (str->str, '{'); - if (!p) - break; - - length = strtoul (p + 1, &end, 10); - if (*end != '}' || *(end + 1) || end == p + 1 || length >= UINT_MAX - 2) - break; - ldigits = end - (p + 1); - - /* Read the literal */ - str = g_string_sized_new (length + 2); - str->str[0] = '\n'; - nread = camel_stream_read (store->istream, str->str + 1, length); - if (nread == -1) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Operation cancelled")); - else - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - g_strerror (errno)); - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - g_string_free (str, TRUE); - goto lose; - } - if (nread < length) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Server response ended too soon.")); - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - g_string_free (str, TRUE); - goto lose; - } - str->str[length + 1] = '\0'; - - /* Fix up the literal, turning CRLFs into LF. Also, if - * we find any embedded NULs, strip them. This is - * dubious, but: - * - The IMAP grammar says you can't have NULs here - * anyway, so this will not affect our behavior - * against any completely correct server. - * - WU-imapd 12.264 (at least) will cheerily pass - * NULs along if they are embedded in the message - */ - - s = d = str->str + 1; - end = str->str + 1 + length; - while (s < end) { - while (s < end && *s == '\0') { - s++; - length--; - } - if (*s == '\r' && *(s + 1) == '\n') { - s++; - length--; - } - *d++ = *s++; - } - *d = '\0'; - str->len = length + 1; - - /* p points to the "{" in the line that starts the - * literal. The length of the CR-less response must be - * less than or equal to the length of the response - * with CRs, therefore overwriting the old value with - * the new value cannot cause an overrun. However, we - * don't want it to be shorter either, because then the - * GString's length would be off... - */ - sprintf (p, "{%0*d}", ldigits, length); - - fulllen += str->len; - g_ptr_array_add (data, str); - - /* Read the next line. */ - if (camel_imap_store_readline (store, &line, ex) < 0) - goto lose; - } - - /* Now reassemble the data. */ - p = line = g_malloc (fulllen + 1); - for (i = 0; i < data->len; i++) { - str = data->pdata[i]; - memcpy (p, str->str, str->len); - p += str->len; - g_string_free (str, TRUE); - } - *p = '\0'; - g_ptr_array_free (data, TRUE); - return line; - - lose: - for (i = 0; i < data->len; i++) - g_string_free (data->pdata[i], TRUE); - g_ptr_array_free (data, TRUE); - return NULL; -} - - -/** - * camel_imap_response_free: - * @store: the CamelImapStore the response is from - * @response: a CamelImapResponse - * - * Frees all of the data in @response and processes any untagged - * EXPUNGE and EXISTS responses in it. Releases @store's connect_lock. - **/ -void -camel_imap_response_free (CamelImapStore *store, CamelImapResponse *response) -{ - int i, number, exists = 0; - GArray *expunged = NULL; - char *resp, *p; - - if (!response) - return; - - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i]; - - if (response->folder) { - /* Check if it's something we need to handle. */ - number = strtoul (resp + 2, &p, 10); - if (!strcasecmp (p, " EXISTS")) { - exists = number; - } else if (!strcasecmp (p, " EXPUNGE")) { - if (!expunged) { - expunged = g_array_new (FALSE, FALSE, - sizeof (int)); - } - g_array_append_val (expunged, number); - } - } - g_free (resp); - } - - g_ptr_array_free (response->untagged, TRUE); - g_free (response->status); - - if (response->folder) { - if (exists > 0 || expunged) { - /* Update the summary */ - camel_imap_folder_changed (response->folder, - exists, expunged, NULL); - if (expunged) - g_array_free (expunged, TRUE); - } - - camel_object_unref (CAMEL_OBJECT (response->folder)); - } - - g_free (response); - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} - -/** - * camel_imap_response_free_without_processing: - * @store: the CamelImapStore the response is from. - * @response: a CamelImapResponse: - * - * Frees all of the data in @response without processing any untagged - * responses. Releases @store's command lock. - **/ -void -camel_imap_response_free_without_processing (CamelImapStore *store, - CamelImapResponse *response) -{ - if (!response) - return; - - if (response->folder) { - camel_object_unref (CAMEL_OBJECT (response->folder)); - response->folder = NULL; - } - camel_imap_response_free (store, response); -} - -/** - * camel_imap_response_extract: - * @store: the store the response came from - * @response: the response data returned from camel_imap_command - * @type: the response type to extract - * @ex: a CamelException - * - * This checks that @response contains a single untagged response of - * type @type and returns just that response data. If @response - * doesn't contain the right information, the function will set @ex - * and return %NULL. Either way, @response will be freed and the - * store's connect_lock released. - * - * Return value: the desired response string, which the caller must free. - **/ -char * -camel_imap_response_extract (CamelImapStore *store, - CamelImapResponse *response, - const char *type, - CamelException *ex) -{ - int len = strlen (type), i; - char *resp; - - len = strlen (type); - - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i]; - /* Skip "* ", and initial sequence number, if present */ - strtoul (resp + 2, &resp, 10); - if (*resp == ' ') - resp = (char *) imap_next_word (resp); - - if (!strncasecmp (resp, type, len)) - break; - } - - if (i < response->untagged->len) { - resp = response->untagged->pdata[i]; - g_ptr_array_remove_index (response->untagged, i); - } else { - resp = NULL; - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("IMAP server response did not contain " - "%s information"), type); - } - - camel_imap_response_free (store, response); - return resp; -} - -/** - * camel_imap_response_extract_continuation: - * @store: the store the response came from - * @response: the response data returned from camel_imap_command - * @ex: a CamelException - * - * This checks that @response contains a continuation response, and - * returns just that data. If @response doesn't contain a continuation - * response, the function will set @ex, release @store's connect_lock, - * and return %NULL. Either way, @response will be freed. - * - * Return value: the desired response string, which the caller must free. - **/ -char * -camel_imap_response_extract_continuation (CamelImapStore *store, - CamelImapResponse *response, - CamelException *ex) -{ - char *status; - - if (response->status && *response->status == '+') { - status = response->status; - response->status = NULL; - camel_imap_response_free (store, response); - return status; - } - - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Unexpected OK response from IMAP server: %s"), - response->status); - camel_imap_response_free (store, response); - return NULL; -} - -static char * -imap_command_strdup_vprintf (CamelImapStore *store, const char *fmt, - va_list ap) -{ - GPtrArray *args; - const char *p, *start; - char *out, *outptr, *string; - int num, len, i, arglen; - - args = g_ptr_array_new (); - - /* Determine the length of the data */ - len = strlen (fmt); - p = start = fmt; - while (*p) { - p = strchr (start, '%'); - if (!p) - break; - - switch (*++p) { - case 'd': - num = va_arg (ap, int); - g_ptr_array_add (args, GINT_TO_POINTER (num)); - start = p + 1; - len += 10; - break; - case 's': - string = va_arg (ap, char *); - g_ptr_array_add (args, string); - start = p + 1; - len += strlen (string); - break; - case 'S': - case 'F': - string = va_arg (ap, char *); - if (*p == 'F') { - /* NB: this is freed during output */ - char *s = camel_imap_store_summary_full_from_path(store->summary, string); - string = s?s:camel_utf8_utf7(string); - } - arglen = strlen (string); - g_ptr_array_add (args, string); - if (imap_is_atom (string)) { - len += arglen; - } else { - if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS) - len += arglen + 15; - else - len += arglen * 2; - } - start = p + 1; - break; - case '%': - start = p; - break; - default: - g_warning ("camel-imap-command is not printf. I don't " - "know what '%%%c' means.", *p); - start = *p ? p + 1 : p; - break; - } - } - - /* Now write out the string */ - outptr = out = g_malloc (len + 1); - p = start = fmt; - i = 0; - while (*p) { - p = strchr (start, '%'); - if (!p) { - strcpy (outptr, start); - break; - } else { - strncpy (outptr, start, p - start); - outptr += p - start; - } - - switch (*++p) { - case 'd': - num = GPOINTER_TO_INT (args->pdata[i++]); - outptr += sprintf (outptr, "%d", num); - break; - - case 's': - string = args->pdata[i++]; - outptr += sprintf (outptr, "%s", string); - break; - case 'S': - case 'F': - string = args->pdata[i++]; - if (imap_is_atom (string)) { - outptr += sprintf (outptr, "%s", string); - } else { - if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS) { - outptr += sprintf (outptr, "{%d+}\r\n%s", strlen (string), string); - } else { - char *quoted = imap_quote_string (string); - - outptr += sprintf (outptr, "%s", quoted); - g_free (quoted); - } - } - - if (*p == 'F') - g_free (string); - break; - default: - *outptr++ = '%'; - *outptr++ = *p; - } - - start = *p ? p + 1 : p; - } - - return out; -} - -static char * -imap_command_strdup_printf (CamelImapStore *store, const char *fmt, ...) -{ - va_list ap; - char *result; - - va_start (ap, fmt); - result = imap_command_strdup_vprintf (store, fmt, ap); - va_end (ap); - - return result; -} diff --git a/camel/providers/imap/camel-imap-command.h b/camel/providers/imap/camel-imap-command.h deleted file mode 100644 index 3539ac63d2..0000000000 --- a/camel/providers/imap/camel-imap-command.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-command.h: IMAP command sending/parsing routines */ - -/* - * Authors: - * Dan Winship - * Jeffrey Stedfast - * - * Copyright (C) 2000, 2001 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAP_COMMAND_H -#define CAMEL_IMAP_COMMAND_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include "camel-imap-types.h" - -typedef enum { - CAMEL_IMAP_RESPONSE_ERROR, - CAMEL_IMAP_RESPONSE_CONTINUATION, - CAMEL_IMAP_RESPONSE_UNTAGGED, - CAMEL_IMAP_RESPONSE_TAGGED -} CamelImapResponseType; - -struct _CamelImapResponse { - CamelFolder *folder; - GPtrArray *untagged; - char *status; -}; - -CamelImapResponse *camel_imap_command (CamelImapStore *store, - CamelFolder *folder, - CamelException *ex, - const char *fmt, ...); -CamelImapResponse *camel_imap_command_continuation (CamelImapStore *store, - const char *cmd, - size_t cmdlen, - CamelException *ex); - -void camel_imap_response_free (CamelImapStore *store, - CamelImapResponse *response); -void camel_imap_response_free_without_processing (CamelImapStore *store, - CamelImapResponse *response); -char *camel_imap_response_extract (CamelImapStore *store, - CamelImapResponse *response, - const char *type, - CamelException *ex); -char *camel_imap_response_extract_continuation (CamelImapStore *store, - CamelImapResponse *response, - CamelException *ex); - -gboolean camel_imap_command_start (CamelImapStore *store, - CamelFolder *folder, - CamelException *ex, - const char *fmt, ...); -CamelImapResponseType camel_imap_command_response (CamelImapStore *store, - char **respbuf, - CamelException *ex); - -#endif /* CAMEL_IMAP_COMMAND_H */ diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c deleted file mode 100644 index 4db0c7a43f..0000000000 --- a/camel/providers/imap/camel-imap-folder.c +++ /dev/null @@ -1,2729 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-folder.c: class for an imap folder */ - -/* - * Authors: - * Dan Winship - * Jeffrey Stedfast - * - * Copyright (C) 2000, 2001 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "e-util/e-path.h" -#include "e-util/e-time-utils.h" - -#include "camel-imap-folder.h" -#include "camel-imap-command.h" -#include "camel-imap-message-cache.h" -#include "camel-imap-private.h" -#include "camel-imap-search.h" -#include "camel-imap-store.h" -#include "camel-imap-summary.h" -#include "camel-imap-utils.h" -#include "camel-imap-wrapper.h" -#include "camel-data-wrapper.h" -#include "camel-disco-diary.h" -#include "camel-exception.h" -#include "camel-mime-filter-crlf.h" -#include "camel-mime-filter-from.h" -#include "camel-mime-message.h" -#include "camel-mime-utils.h" -#include "camel-multipart.h" -#include "camel-multipart-signed.h" -#include "camel-multipart-encrypted.h" -#include "camel-operation.h" -#include "camel-session.h" -#include "camel-stream-buffer.h" -#include "camel-stream-filter.h" -#include "camel-stream-mem.h" -#include "camel-stream.h" -#include "camel-private.h" -#include "camel-string-utils.h" -#include "camel-file-utils.h" - - -#define d(x) - -/* set to -1 for infinite size */ -#define UID_SET_LIMIT (4096) - - -#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o))) -static CamelDiscoFolderClass *disco_folder_class = NULL; - -static void imap_finalize (CamelObject *object); -static int imap_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args); - -static void imap_rescan (CamelFolder *folder, int exists, CamelException *ex); -static void imap_refresh_info (CamelFolder *folder, CamelException *ex); -static void imap_sync_online (CamelFolder *folder, CamelException *ex); -static void imap_sync_offline (CamelFolder *folder, CamelException *ex); -static void imap_expunge_uids_online (CamelFolder *folder, GPtrArray *uids, CamelException *ex); -static void imap_expunge_uids_offline (CamelFolder *folder, GPtrArray *uids, CamelException *ex); -static void imap_expunge_uids_resyncing (CamelFolder *folder, GPtrArray *uids, CamelException *ex); -static void imap_cache_message (CamelDiscoFolder *disco_folder, const char *uid, CamelException *ex); -static void imap_rename (CamelFolder *folder, const char *new); - -/* message manipulation */ -static CamelMimeMessage *imap_get_message (CamelFolder *folder, const gchar *uid, - CamelException *ex); -static void imap_append_online (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex); -static void imap_append_offline (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex); -static void imap_append_resyncing (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex); - -static void imap_transfer_online (CamelFolder *source, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, - CamelException *ex); -static void imap_transfer_offline (CamelFolder *source, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, - CamelException *ex); -static void imap_transfer_resyncing (CamelFolder *source, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, - CamelException *ex); - -/* searching */ -static GPtrArray *imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex); -static GPtrArray *imap_search_by_uids (CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex); -static void imap_search_free (CamelFolder *folder, GPtrArray *uids); - -static void imap_thaw (CamelFolder *folder); - -static CamelObjectClass *parent_class; - -static GData *parse_fetch_response (CamelImapFolder *imap_folder, char *msg_att); - -static void -camel_imap_folder_class_init (CamelImapFolderClass *camel_imap_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_imap_folder_class); - CamelDiscoFolderClass *camel_disco_folder_class = CAMEL_DISCO_FOLDER_CLASS (camel_imap_folder_class); - - disco_folder_class = CAMEL_DISCO_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_disco_folder_get_type ())); - - /* virtual method overload */ - ((CamelObjectClass *)camel_imap_folder_class)->getv = imap_getv; - - camel_folder_class->get_message = imap_get_message; - camel_folder_class->rename = imap_rename; - camel_folder_class->search_by_expression = imap_search_by_expression; - camel_folder_class->search_by_uids = imap_search_by_uids; - camel_folder_class->search_free = imap_search_free; - camel_folder_class->thaw = imap_thaw; - - camel_disco_folder_class->refresh_info_online = imap_refresh_info; - camel_disco_folder_class->sync_online = imap_sync_online; - camel_disco_folder_class->sync_offline = imap_sync_offline; - /* We don't sync flags at resync time: the online code will - * deal with it eventually. - */ - camel_disco_folder_class->sync_resyncing = imap_sync_offline; - camel_disco_folder_class->expunge_uids_online = imap_expunge_uids_online; - camel_disco_folder_class->expunge_uids_offline = imap_expunge_uids_offline; - camel_disco_folder_class->expunge_uids_resyncing = imap_expunge_uids_resyncing; - camel_disco_folder_class->append_online = imap_append_online; - camel_disco_folder_class->append_offline = imap_append_offline; - camel_disco_folder_class->append_resyncing = imap_append_resyncing; - camel_disco_folder_class->transfer_online = imap_transfer_online; - camel_disco_folder_class->transfer_offline = imap_transfer_offline; - camel_disco_folder_class->transfer_resyncing = imap_transfer_resyncing; - camel_disco_folder_class->cache_message = imap_cache_message; -} - -static void -camel_imap_folder_init (gpointer object, gpointer klass) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object); - CamelFolder *folder = CAMEL_FOLDER (object); - - folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_DELETED | - CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN; - - folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | - CAMEL_FOLDER_HAS_SEARCH_CAPABILITY); - - imap_folder->priv = g_malloc0(sizeof(*imap_folder->priv)); -#ifdef ENABLE_THREADS - imap_folder->priv->search_lock = e_mutex_new(E_MUTEX_SIMPLE); - imap_folder->priv->cache_lock = e_mutex_new(E_MUTEX_REC); -#endif - - imap_folder->need_rescan = TRUE; -} - -CamelType -camel_imap_folder_get_type (void) -{ - static CamelType camel_imap_folder_type = CAMEL_INVALID_TYPE; - - if (camel_imap_folder_type == CAMEL_INVALID_TYPE) { - parent_class = camel_disco_folder_get_type(); - camel_imap_folder_type = - camel_type_register (parent_class, "CamelImapFolder", - sizeof (CamelImapFolder), - sizeof (CamelImapFolderClass), - (CamelObjectClassInitFunc) camel_imap_folder_class_init, - NULL, - (CamelObjectInitFunc) camel_imap_folder_init, - (CamelObjectFinalizeFunc) imap_finalize); - } - - return camel_imap_folder_type; -} - -CamelFolder * -camel_imap_folder_new (CamelStore *parent, const char *folder_name, - const char *folder_dir, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (parent); - CamelFolder *folder; - CamelImapFolder *imap_folder; - const char *short_name; - char *summary_file; - - if (camel_mkdir (folder_dir, S_IRWXU) != 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create directory %s: %s"), - folder_dir, g_strerror (errno)); - return NULL; - } - - folder = CAMEL_FOLDER (camel_object_new (camel_imap_folder_get_type ())); - short_name = strrchr (folder_name, imap_store->dir_sep); - if (short_name) - short_name++; - else - short_name = folder_name; - camel_folder_construct (folder, parent, folder_name, short_name); - - summary_file = g_strdup_printf ("%s/summary", folder_dir); - folder->summary = camel_imap_summary_new (summary_file); - g_free (summary_file); - if (!folder->summary) { - camel_object_unref (CAMEL_OBJECT (folder)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not load summary for %s"), - folder_name); - return NULL; - } - - imap_folder = CAMEL_IMAP_FOLDER (folder); - imap_folder->cache = camel_imap_message_cache_new (folder_dir, folder->summary, ex); - if (!imap_folder->cache) { - camel_object_unref (CAMEL_OBJECT (folder)); - return NULL; - } - - if ((imap_store->parameters & IMAP_PARAM_FILTER_INBOX) && - !strcasecmp (folder_name, "INBOX")) - folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT; - - imap_folder->search = camel_imap_search_new(folder_dir); - - return folder; -} - -/* Called with the store's connect_lock locked */ -void -camel_imap_folder_selected (CamelFolder *folder, CamelImapResponse *response, - CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - CamelImapSummary *imap_summary = CAMEL_IMAP_SUMMARY (folder->summary); - unsigned long exists = 0, validity = 0, val, uid; - CamelMessageInfo *info; - GData *fetch_data; - int i, count; - char *resp; - - CAMEL_SERVICE_ASSERT_LOCKED (folder->parent_store, connect_lock); - - count = camel_folder_summary_count (folder->summary); - - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i] + 2; - if (!strncasecmp (resp, "FLAGS ", 6) && - !folder->permanent_flags) { - resp += 6; - folder->permanent_flags = imap_parse_flag_list (&resp); - } else if (!strncasecmp (resp, "OK [PERMANENTFLAGS ", 19)) { - resp += 19; - folder->permanent_flags = imap_parse_flag_list (&resp); - } else if (!strncasecmp (resp, "OK [UIDVALIDITY ", 16)) { - validity = strtoul (resp + 16, NULL, 10); - } else if (isdigit ((unsigned char)*resp)) { - unsigned long num = strtoul (resp, &resp, 10); - - if (!strncasecmp (resp, " EXISTS", 7)) { - exists = num; - /* Remove from the response so nothing - * else tries to interpret it. - */ - g_free (response->untagged->pdata[i]); - g_ptr_array_remove_index (response->untagged, i--); - } - } - } - - if (camel_disco_store_status (CAMEL_DISCO_STORE (folder->parent_store)) == CAMEL_DISCO_STORE_RESYNCING) { - if (validity != imap_summary->validity) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_SUMMARY_INVALID, - _("Folder was destroyed and recreated on server.")); - return; - } - - /* FIXME: find missing UIDs ? */ - return; - } - - if (!imap_summary->validity) - imap_summary->validity = validity; - else if (validity != imap_summary->validity) { - imap_summary->validity = validity; - camel_folder_summary_clear (folder->summary); - CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock); - camel_imap_message_cache_clear (imap_folder->cache); - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - imap_folder->need_rescan = FALSE; - camel_imap_folder_changed (folder, exists, NULL, ex); - return; - } - - /* If we've lost messages, we have to rescan everything */ - if (exists < count) - imap_folder->need_rescan = TRUE; - else if (count != 0 && !imap_folder->need_rescan) { - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - - /* Similarly, if the UID of the highest message we - * know about has changed, then that indicates that - * messages have been both added and removed, so we - * have to rescan to find the removed ones. (We pass - * NULL for the folder since we know that this folder - * is selected, and we don't want camel_imap_command - * to worry about it.) - */ - response = camel_imap_command (store, NULL, ex, "FETCH %d UID", count); - if (!response) - return; - uid = 0; - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i]; - val = strtoul (resp + 2, &resp, 10); - if (val == 0) - continue; - if (!strcasecmp (resp, " EXISTS")) { - /* Another one?? */ - exists = val; - continue; - } - if (uid != 0 || val != count || strncasecmp (resp, " FETCH (", 8) != 0) - continue; - - fetch_data = parse_fetch_response (imap_folder, resp + 7); - uid = strtoul (g_datalist_get_data (&fetch_data, "UID"), NULL, 10); - g_datalist_clear (&fetch_data); - } - camel_imap_response_free_without_processing (store, response); - - info = camel_folder_summary_index (folder->summary, count - 1); - val = strtoul (camel_message_info_uid (info), NULL, 10); - camel_folder_summary_info_free (folder->summary, info); - if (uid == 0 || uid != val) - imap_folder->need_rescan = TRUE; - } - - /* Now rescan if we need to */ - if (imap_folder->need_rescan) { - imap_rescan (folder, exists, ex); - return; - } - - /* If we don't need to rescan completely, but new messages - * have been added, find out about them. - */ - if (exists > count) - camel_imap_folder_changed (folder, exists, NULL, ex); - - /* And we're done. */ -} - -static void -imap_finalize (CamelObject *object) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object); - - if (imap_folder->search) - camel_object_unref (CAMEL_OBJECT (imap_folder->search)); - if (imap_folder->cache) - camel_object_unref (CAMEL_OBJECT (imap_folder->cache)); - -#ifdef ENABLE_THREADS - e_mutex_destroy(imap_folder->priv->search_lock); - e_mutex_destroy(imap_folder->priv->cache_lock); -#endif - g_free(imap_folder->priv); -} - -static int -imap_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args) -{ - CamelFolder *folder = (CamelFolder *)object; - int i, count=args->argc; - guint32 tag; - - for (i=0;iargc;i++) { - CamelArgGet *arg = &args->argv[i]; - - tag = arg->tag; - - switch (tag & CAMEL_ARG_TAG) { - /* CamelObject args */ - case CAMEL_OBJECT_ARG_DESCRIPTION: - if (folder->description == NULL) { - CamelURL *uri = ((CamelService *)folder->parent_store)->url; - - /* what if the full name doesn't incclude /'s? does it matter? */ - folder->description = g_strdup_printf("%s@%s:%s", uri->user, uri->host, folder->full_name); - } - *arg->ca_str = folder->description; - break; - default: - count--; - continue; - } - - arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE; - } - - if (count) - return ((CamelObjectClass *)parent_class)->getv(object, ex, args); - - return 0; -} - -static void -imap_rename (CamelFolder *folder, const char *new) -{ - CamelImapFolder *imap_folder = (CamelImapFolder *)folder; - CamelImapStore *imap_store = (CamelImapStore *)folder->parent_store; - char *folder_dir, *summary_path; - char *folders; - - folders = g_strconcat (imap_store->storage_path, "/folders", NULL); - folder_dir = e_path_to_physical (folders, new); - g_free (folders); - summary_path = g_strdup_printf("%s/summary", folder_dir); - - CAMEL_IMAP_FOLDER_LOCK (folder, cache_lock); - camel_imap_message_cache_set_path(imap_folder->cache, folder_dir); - CAMEL_IMAP_FOLDER_UNLOCK (folder, cache_lock); - - camel_folder_summary_set_filename(folder->summary, summary_path); - - g_free(summary_path); - g_free(folder_dir); - - ((CamelFolderClass *)disco_folder_class)->rename(folder, new); -} - -static void -imap_refresh_info (CamelFolder *folder, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - CamelImapResponse *response; - - if (camel_disco_store_status (CAMEL_DISCO_STORE (imap_store)) == CAMEL_DISCO_STORE_OFFLINE) - return; - - if (camel_folder_is_frozen (folder)) { - imap_folder->need_refresh = TRUE; - return; - } - - /* If the folder isn't selected, select it (which will force - * a rescan if one is needed). - * Also, if this is the INBOX, some servers (cryus) wont tell - * us with a NOOP of new messages, so force a reselect which - * should do it. */ - CAMEL_SERVICE_LOCK (imap_store, connect_lock); - if (imap_store->current_folder != folder - || strcasecmp(folder->full_name, "INBOX") == 0) { - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - response = camel_imap_command (imap_store, folder, ex, NULL); - if (response) { - camel_imap_folder_selected (folder, response, ex); - camel_imap_response_free (imap_store, response); - } - return; - } - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - - /* Otherwise, if we need a rescan, do it, and if not, just do - * a NOOP to give the server a chance to tell us about new - * messages. - */ - if (imap_folder->need_rescan) - imap_rescan (folder, camel_folder_summary_count (folder->summary), ex); - else { -#if 0 - /* on some servers need to CHECKpoint INBOX to recieve new messages?? */ - /* rfc2060 suggests this, but havent seen a server that requires it */ - if (strcasecmp(folder->full_name, "INBOX") == 0) { - response = camel_imap_command (imap_store, folder, ex, "CHECK"); - camel_imap_response_free (imap_store, response); - } -#endif - response = camel_imap_command (imap_store, folder, ex, "NOOP"); - camel_imap_response_free (imap_store, response); - } -} - -/* Called with the store's connect_lock locked */ -static void -imap_rescan (CamelFolder *folder, int exists, CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - struct { - char *uid; - guint32 flags; - } *new; - char *resp; - CamelImapResponseType type; - int i, seq, summary_len, summary_got; - CamelMessageInfo *info; - CamelImapMessageInfo *iinfo; - GArray *removed; - gboolean ok; - CamelFolderChangeInfo *changes = NULL; - - CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock); - imap_folder->need_rescan = FALSE; - - summary_len = camel_folder_summary_count (folder->summary); - if (summary_len == 0) { - if (exists) - camel_imap_folder_changed (folder, exists, NULL, ex); - return; - } - - /* Check UIDs and flags of all messages we already know of. */ - camel_operation_start (NULL, _("Scanning for changed messages")); - info = camel_folder_summary_index (folder->summary, summary_len - 1); - ok = camel_imap_command_start (store, folder, ex, - "UID FETCH 1:%s (FLAGS)", - camel_message_info_uid (info)); - camel_folder_summary_info_free (folder->summary, info); - if (!ok) { - camel_operation_end (NULL); - return; - } - - new = g_malloc0 (summary_len * sizeof (*new)); - summary_got = 0; - while ((type = camel_imap_command_response (store, &resp, ex)) == CAMEL_IMAP_RESPONSE_UNTAGGED) { - GData *data; - char *uid; - guint32 flags; - - data = parse_fetch_response (imap_folder, resp); - g_free (resp); - if (!data) - continue; - - seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE")); - uid = g_datalist_get_data (&data, "UID"); - flags = GPOINTER_TO_UINT (g_datalist_get_data (&data, "FLAGS")); - - if (!uid || !seq || seq > summary_len) { - g_datalist_clear (&data); - continue; - } - - camel_operation_progress (NULL, ++summary_got * 100 / summary_len); - new[seq - 1].uid = g_strdup (uid); - new[seq - 1].flags = flags; - g_datalist_clear (&data); - } - - camel_operation_end (NULL); - if (type == CAMEL_IMAP_RESPONSE_ERROR) { - for (i = 0; i < summary_len && new[i].uid; i++) - g_free (new[i].uid); - g_free (new); - return; - } - - /* Free the final tagged response */ - g_free (resp); - - /* If we find a UID in the summary that doesn't correspond to - * the UID in the folder, then either: (a) it's a real UID, - * but the message was deleted on the server, or (b) it's a - * fake UID, and needs to be removed from the summary in order - * to sync up with the server. So either way, we remove it - * from the summary. - */ - removed = g_array_new (FALSE, FALSE, sizeof (int)); - for (i = 0; i < summary_len && new[i].uid; i++) { - info = camel_folder_summary_index (folder->summary, i); - iinfo = (CamelImapMessageInfo *)info; - - if (strcmp (camel_message_info_uid (info), new[i].uid) != 0) { - camel_folder_summary_info_free(folder->summary, info); - seq = i + 1; - g_array_append_val (removed, seq); - i--; - summary_len--; - continue; - } - - /* Update summary flags */ - if (new[i].flags != iinfo->server_flags) { - guint32 server_set, server_cleared; - - server_set = new[i].flags & ~iinfo->server_flags; - server_cleared = iinfo->server_flags & ~new[i].flags; - - info->flags = (info->flags | server_set) & ~server_cleared; - iinfo->server_flags = new[i].flags; - - if (changes == NULL) - changes = camel_folder_change_info_new(); - camel_folder_change_info_change_uid(changes, new[i].uid); - } - - camel_folder_summary_info_free (folder->summary, info); - g_free (new[i].uid); - } - - if (changes) { - camel_object_trigger_event(CAMEL_OBJECT (folder), "folder_changed", changes); - camel_folder_change_info_free(changes); - } - - seq = i + 1; - - /* Free remaining memory. */ - while (i < summary_len && new[i].uid) - g_free (new[i++].uid); - g_free (new); - - /* Remove any leftover cached summary messages. (Yes, we - * repeatedly add the same number to the removed array. - * See RFC2060 7.4.1) - */ - - for (i = seq; i <= summary_len; i++) - g_array_append_val (removed, seq); - - /* And finally update the summary. */ - camel_imap_folder_changed (folder, exists, removed, ex); - g_array_free (removed, TRUE); -} - -/* the max number of chars that an unsigned 32-bit int can be is 10 chars plus 1 for a possible : */ -#define UID_SET_FULL(setlen, maxlen) (maxlen > 0 ? setlen + 11 >= maxlen : FALSE) - -/* Find all messages in @folder with flags matching @flags and @mask. - * If no messages match, returns %NULL. Otherwise, returns an array of - * CamelMessageInfo and sets *@set to a message set corresponding the - * UIDs of the matched messages (up to @UID_SET_LIMIT bytes). The - * caller must free the infos, the array, and the set string. - */ -static GPtrArray * -get_matching (CamelFolder *folder, guint32 flags, guint32 mask, char **set) -{ - GPtrArray *matches; - CamelMessageInfo *info; - int i, max, range; - GString *gset; - - matches = g_ptr_array_new (); - gset = g_string_new (""); - max = camel_folder_summary_count (folder->summary); - range = -1; - for (i = 0; i < max && !UID_SET_FULL (gset->len, UID_SET_LIMIT); i++) { - info = camel_folder_summary_index (folder->summary, i); - if (!info) - continue; - if ((info->flags & mask) != flags) { - camel_folder_summary_info_free (folder->summary, info); - if (range != -1) { - if (range != i - 1) { - info = matches->pdata[matches->len - 1]; - g_string_append_printf (gset, ":%s", camel_message_info_uid (info)); - } - range = -1; - } - continue; - } - - g_ptr_array_add (matches, info); - if (range != -1) - continue; - range = i; - if (gset->len) - g_string_append_c (gset, ','); - g_string_append_printf (gset, "%s", camel_message_info_uid (info)); - } - - if (range != -1 && range != max - 1) { - info = matches->pdata[matches->len - 1]; - g_string_append_printf (gset, ":%s", camel_message_info_uid (info)); - } - - if (matches->len) { - *set = gset->str; - g_string_free (gset, FALSE); - return matches; - } else { - *set = NULL; - g_string_free (gset, TRUE); - g_ptr_array_free (matches, TRUE); - return NULL; - } -} - -static void -imap_sync_offline (CamelFolder *folder, CamelException *ex) -{ - camel_folder_summary_save (folder->summary); -} - -static void -imap_sync_online (CamelFolder *folder, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response = NULL; - CamelMessageInfo *info; - CamelException local_ex; - GPtrArray *matches; - char *set, *flaglist; - gboolean unset; - int i, j, max; - - camel_exception_init (&local_ex); - CAMEL_SERVICE_LOCK (store, connect_lock); - - /* Find a message with changed flags, find all of the other - * messages like it, sync them as a group, mark them as - * updated, and continue. - */ - max = camel_folder_summary_count (folder->summary); - for (i = 0; i < max; i++) { - info = camel_folder_summary_index (folder->summary, i); - if (!info) - continue; - if (!(info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) { - camel_folder_summary_info_free (folder->summary, info); - continue; - } - - /* Note: Cyrus is broken and will not accept an - empty-set of flags so... if this is true then we - want to unset the previously set flags.*/ - unset = !(info->flags & CAMEL_IMAP_SERVER_FLAGS); - - /* Note: get_matching() uses UID_SET_LIMIT to limit - the size of the uid-set string. We don't have to - loop here to flush all the matching uids because - they will be scooped up later by our parent loop (I - think?). -- Jeff */ - matches = get_matching (folder, info->flags & (CAMEL_IMAP_SERVER_FLAGS | CAMEL_MESSAGE_FOLDER_FLAGGED), - CAMEL_IMAP_SERVER_FLAGS | CAMEL_MESSAGE_FOLDER_FLAGGED, &set); - camel_folder_summary_info_free (folder->summary, info); - if (matches == NULL) - continue; - - /* FIXME: since we don't know the previously set flags, - if unset is TRUE then just unset all the flags? */ - flaglist = imap_create_flag_list (unset ? CAMEL_IMAP_SERVER_FLAGS : info->flags); - - /* Note: to `unset' flags, use -FLAGS.SILENT () */ - response = camel_imap_command (store, folder, &local_ex, - "UID STORE %s %sFLAGS.SILENT %s", - set, unset ? "-" : "", flaglist); - g_free (set); - g_free (flaglist); - - if (response) - camel_imap_response_free (store, response); - - if (!camel_exception_is_set (&local_ex)) { - for (j = 0; j < matches->len; j++) { - info = matches->pdata[j]; - info->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED; - ((CamelImapMessageInfo*)info)->server_flags = - info->flags & CAMEL_IMAP_SERVER_FLAGS; - } - camel_folder_summary_touch (folder->summary); - } - - for (j = 0; j < matches->len; j++) { - info = matches->pdata[j]; - camel_folder_summary_info_free (folder->summary, info); - } - g_ptr_array_free (matches, TRUE); - - /* We unlock here so that other threads can have a chance to grab the connect_lock */ - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - /* check for an exception */ - if (camel_exception_is_set (&local_ex)) { - camel_exception_xfer (ex, &local_ex); - return; - } - - /* Re-lock the connect_lock */ - CAMEL_SERVICE_LOCK (store, connect_lock); - } - - /* Save the summary */ - imap_sync_offline (folder, ex); - - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} - -static int -uid_compar (const void *va, const void *vb) -{ - const char **sa = (const char **)va, **sb = (const char **)vb; - unsigned long a, b; - - a = strtoul (*sa, NULL, 10); - b = strtoul (*sb, NULL, 10); - if (a < b) - return -1; - else if (a == b) - return 0; - else - return 1; -} - -static void -imap_expunge_uids_offline (CamelFolder *folder, GPtrArray *uids, CamelException *ex) -{ - CamelFolderChangeInfo *changes; - int i; - - qsort (uids->pdata, uids->len, sizeof (void *), uid_compar); - - changes = camel_folder_change_info_new (); - - for (i = 0; i < uids->len; i++) { - camel_folder_summary_remove_uid (folder->summary, uids->pdata[i]); - camel_folder_change_info_remove_uid (changes, uids->pdata[i]); - /* We intentionally don't remove it from the cache because - * the cached data may be useful in replaying a COPY later. - */ - } - camel_folder_summary_save (folder->summary); - - camel_disco_diary_log (CAMEL_DISCO_STORE (folder->parent_store)->diary, - CAMEL_DISCO_DIARY_FOLDER_EXPUNGE, folder, uids); - - camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", changes); - camel_folder_change_info_free (changes); -} - -static void -imap_expunge_uids_online (CamelFolder *folder, GPtrArray *uids, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - int uid = 0; - char *set; - - CAMEL_SERVICE_LOCK (store, connect_lock); - - if ((store->capabilities & IMAP_CAPABILITY_UIDPLUS) == 0) { - ((CamelFolderClass *)CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, 0, ex); - if (camel_exception_is_set(ex)) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - } - - qsort (uids->pdata, uids->len, sizeof (void *), uid_compar); - - while (uid < uids->len) { - set = imap_uid_array_to_set (folder->summary, uids, uid, UID_SET_LIMIT, &uid); - response = camel_imap_command (store, folder, ex, - "UID STORE %s +FLAGS.SILENT \\Deleted", - set); - if (response) - camel_imap_response_free (store, response); - if (camel_exception_is_set (ex)) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - g_free (set); - return; - } - - if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) { - response = camel_imap_command (store, folder, ex, - "UID EXPUNGE %s", set); - } else - response = camel_imap_command (store, folder, ex, "EXPUNGE"); - - if (response) - camel_imap_response_free (store, response); - } - - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} - -static void -imap_expunge_uids_resyncing (CamelFolder *folder, GPtrArray *uids, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - GPtrArray *keep_uids, *mark_uids; - CamelImapResponse *response; - char *result; - - if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) { - imap_expunge_uids_online (folder, uids, ex); - return; - } - - /* If we don't have UID EXPUNGE we need to avoid expunging any - * of the wrong messages. So we search for deleted messages, - * and any that aren't in our to-expunge list get temporarily - * marked un-deleted. - */ - - CAMEL_SERVICE_LOCK (store, connect_lock); - - ((CamelFolderClass *)CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, 0, ex); - if (camel_exception_is_set(ex)) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - - response = camel_imap_command (store, folder, ex, "UID SEARCH DELETED"); - if (!response) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - result = camel_imap_response_extract (store, response, "SEARCH", ex); - if (!result) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - - if (result[8] == ' ') { - char *uid, *lasts = NULL; - unsigned long euid, kuid; - int ei, ki; - - keep_uids = g_ptr_array_new (); - mark_uids = g_ptr_array_new (); - - /* Parse SEARCH response */ - for (uid = strtok_r (result + 9, " ", &lasts); uid; uid = strtok_r (NULL, " ", &lasts)) - g_ptr_array_add (keep_uids, uid); - qsort (keep_uids->pdata, keep_uids->len, - sizeof (void *), uid_compar); - - /* Fill in "mark_uids", empty out "keep_uids" as needed */ - for (ei = ki = 0; ei < uids->len; ei++) { - euid = strtoul (uids->pdata[ei], NULL, 10); - - for (kuid = 0; ki < keep_uids->len; ki++) { - kuid = strtoul (keep_uids->pdata[ki], NULL, 10); - - if (kuid >= euid) - break; - } - - if (euid == kuid) - g_ptr_array_remove_index (keep_uids, ki); - else - g_ptr_array_add (mark_uids, uids->pdata[ei]); - } - } else { - /* Empty SEARCH result, meaning nothing is marked deleted - * on server. - */ - - keep_uids = NULL; - mark_uids = uids; - } - - /* Unmark messages to be kept */ - - if (keep_uids) { - char *uidset; - int uid = 0; - - while (uid < keep_uids->len) { - uidset = imap_uid_array_to_set (folder->summary, keep_uids, uid, UID_SET_LIMIT, &uid); - - response = camel_imap_command (store, folder, ex, - "UID STORE %s -FLAGS.SILENT \\Deleted", - uidset); - - g_free (uidset); - - if (!response) { - g_ptr_array_free (keep_uids, TRUE); - g_ptr_array_free (mark_uids, TRUE); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - camel_imap_response_free (store, response); - } - } - - /* Mark any messages that still need to be marked */ - if (mark_uids) { - char *uidset; - int uid = 0; - - while (uid < mark_uids->len) { - uidset = imap_uid_array_to_set (folder->summary, mark_uids, uid, UID_SET_LIMIT, &uid); - - response = camel_imap_command (store, folder, ex, - "UID STORE %s +FLAGS.SILENT \\Deleted", - uidset); - - g_free (uidset); - - if (!response) { - g_ptr_array_free (keep_uids, TRUE); - g_ptr_array_free (mark_uids, TRUE); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - camel_imap_response_free (store, response); - } - - if (mark_uids != uids) - g_ptr_array_free (mark_uids, TRUE); - } - - /* Do the actual expunging */ - response = camel_imap_command (store, folder, ex, "EXPUNGE"); - if (response) - camel_imap_response_free (store, response); - - /* And fix the remaining messages if we mangled them */ - if (keep_uids) { - char *uidset; - int uid = 0; - - while (uid < keep_uids->len) { - uidset = imap_uid_array_to_set (folder->summary, keep_uids, uid, UID_SET_LIMIT, &uid); - - /* Don't pass ex if it's already been set */ - response = camel_imap_command (store, folder, - camel_exception_is_set (ex) ? NULL : ex, - "UID STORE %s +FLAGS.SILENT \\Deleted", - uidset); - - g_free (uidset); - if (response) - camel_imap_response_free (store, response); - } - - g_ptr_array_free (keep_uids, TRUE); - } - - /* now we can free this, now that we're done with keep_uids */ - g_free (result); - - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} - -static gchar * -get_temp_uid (void) -{ - gchar *res; - - static int counter = 0; - G_LOCK_DEFINE_STATIC (lock); - - G_LOCK (lock); - res = g_strdup_printf ("tempuid-%lx-%d", - (unsigned long) time (NULL), - counter++); - G_UNLOCK (lock); - - return res; -} - -static void -imap_append_offline (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapMessageCache *cache = CAMEL_IMAP_FOLDER (folder)->cache; - CamelFolderChangeInfo *changes; - char *uid; - - uid = get_temp_uid (); - - camel_imap_summary_add_offline (folder->summary, uid, message, info); - CAMEL_IMAP_FOLDER_LOCK (folder, cache_lock); - camel_imap_message_cache_insert_wrapper (cache, uid, "", - CAMEL_DATA_WRAPPER (message), ex); - CAMEL_IMAP_FOLDER_UNLOCK (folder, cache_lock); - - changes = camel_folder_change_info_new (); - camel_folder_change_info_add_uid (changes, uid); - camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", - changes); - camel_folder_change_info_free (changes); - - camel_disco_diary_log (CAMEL_DISCO_STORE (imap_store)->diary, - CAMEL_DISCO_DIARY_FOLDER_APPEND, folder, uid); - if (appended_uid) - *appended_uid = uid; - else - g_free (uid); -} - -static CamelImapResponse * -do_append (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **uid, - CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response, *response2; - CamelStream *memstream; - CamelMimeFilter *crlf_filter; - CamelStreamFilter *streamfilter; - GByteArray *ba; - char *flagstr, *end; - - /* create flag string param */ - if (info && info->flags) - flagstr = imap_create_flag_list (info->flags); - else - flagstr = NULL; - - /* encode any 8bit parts so we avoid sending embedded nul-chars and such */ - camel_mime_message_encode_8bit_parts (message); - - /* FIXME: We could avoid this if we knew how big the message was. */ - memstream = camel_stream_mem_new (); - ba = g_byte_array_new (); - camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (memstream), ba); - - streamfilter = camel_stream_filter_new_with_stream (memstream); - crlf_filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, - CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - camel_stream_filter_add (streamfilter, crlf_filter); - camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), - CAMEL_STREAM (streamfilter)); - camel_object_unref (CAMEL_OBJECT (streamfilter)); - camel_object_unref (CAMEL_OBJECT (crlf_filter)); - camel_object_unref (CAMEL_OBJECT (memstream)); - - response = camel_imap_command (store, NULL, ex, "APPEND %F%s%s {%d}", - folder->full_name, flagstr ? " " : "", - flagstr ? flagstr : "", ba->len); - g_free (flagstr); - - if (!response) { - g_byte_array_free (ba, TRUE); - return NULL; - } - - if (*response->status != '+') { - camel_imap_response_free (store, response); - g_byte_array_free (ba, TRUE); - return NULL; - } - - /* send the rest of our data - the mime message */ - response2 = camel_imap_command_continuation (store, ba->data, ba->len, ex); - g_byte_array_free (ba, TRUE); - - /* free it only after message is sent. This may cause more FETCHes. */ - camel_imap_response_free (store, response); - if (!response2) - return response2; - - if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) { - *uid = camel_strstrcase (response2->status, "[APPENDUID "); - if (*uid) - *uid = strchr (*uid + 11, ' '); - if (*uid) { - *uid = g_strndup (*uid + 1, strcspn (*uid + 1, "]")); - /* Make sure it's a number */ - if (strtoul (*uid, &end, 10) == 0 || *end) { - g_free (*uid); - *uid = NULL; - } - } - } else - *uid = NULL; - - return response2; -} - -static void -imap_append_online (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - char *uid; - int count; - - count = camel_folder_summary_count (folder->summary); - response = do_append (folder, message, info, &uid, ex); - if (!response) - return; - - if (uid) { - /* Cache first, since freeing response may trigger a - * summary update that will want this information. - */ - CAMEL_IMAP_FOLDER_LOCK (folder, cache_lock); - camel_imap_message_cache_insert_wrapper ( - CAMEL_IMAP_FOLDER (folder)->cache, uid, - "", CAMEL_DATA_WRAPPER (message), ex); - CAMEL_IMAP_FOLDER_UNLOCK (folder, cache_lock); - if (appended_uid) - *appended_uid = uid; - else - g_free (uid); - } else if (appended_uid) - *appended_uid = NULL; - - camel_imap_response_free (store, response); - - /* Make sure a "folder_changed" is emitted. */ - CAMEL_SERVICE_LOCK (store, connect_lock); - if (store->current_folder != folder || - camel_folder_summary_count (folder->summary) == count) - imap_refresh_info (folder, ex); - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} - -static void -imap_append_resyncing (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - char *uid; - - response = do_append (folder, message, info, &uid, ex); - if (!response) - return; - - if (uid) { - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - const char *olduid = camel_message_info_uid (info); - - CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock); - camel_imap_message_cache_copy (imap_folder->cache, olduid, - imap_folder->cache, uid, ex); - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - - if (appended_uid) - *appended_uid = uid; - else - g_free (uid); - } else if (appended_uid) - *appended_uid = NULL; - - camel_imap_response_free (store, response); -} - - -static void -imap_transfer_offline (CamelFolder *source, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store); - CamelImapMessageCache *sc = CAMEL_IMAP_FOLDER (source)->cache; - CamelImapMessageCache *dc = CAMEL_IMAP_FOLDER (dest)->cache; - CamelFolderChangeInfo *changes; - CamelMimeMessage *message; - CamelMessageInfo *mi; - char *uid, *destuid; - int i; - - /* We grab the store's command lock first, and then grab the - * source and destination cache_locks. This way we can't - * deadlock in the case where we're simultaneously also trying - * to copy messages in the other direction from another thread. - */ - CAMEL_SERVICE_LOCK (store, connect_lock); - CAMEL_IMAP_FOLDER_LOCK (source, cache_lock); - CAMEL_IMAP_FOLDER_LOCK (dest, cache_lock); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - if (transferred_uids) { - *transferred_uids = g_ptr_array_new (); - g_ptr_array_set_size (*transferred_uids, uids->len); - } - - changes = camel_folder_change_info_new (); - - for (i = 0; i < uids->len; i++) { - uid = uids->pdata[i]; - - destuid = get_temp_uid (); - - mi = camel_folder_summary_uid (source->summary, uid); - g_return_if_fail (mi != NULL); - - message = camel_folder_get_message (source, uid, NULL); - - if (message) { - camel_imap_summary_add_offline (dest->summary, destuid, message, mi); - camel_object_unref (CAMEL_OBJECT (message)); - } else - camel_imap_summary_add_offline_uncached (dest->summary, destuid, mi); - - camel_imap_message_cache_copy (sc, uid, dc, destuid, ex); - camel_folder_summary_info_free (source->summary, mi); - - camel_folder_change_info_add_uid (changes, destuid); - if (transferred_uids) - (*transferred_uids)->pdata[i] = destuid; - else - g_free (destuid); - - if (delete_originals) - camel_folder_delete_message (source, uid); - } - - CAMEL_IMAP_FOLDER_UNLOCK (dest, cache_lock); - CAMEL_IMAP_FOLDER_UNLOCK (source, cache_lock); - - camel_object_trigger_event (CAMEL_OBJECT (dest), "folder_changed", changes); - camel_folder_change_info_free (changes); - - camel_disco_diary_log (CAMEL_DISCO_STORE (store)->diary, - CAMEL_DISCO_DIARY_FOLDER_TRANSFER, - source, dest, uids, delete_originals); -} - -static void -handle_copyuid (CamelImapResponse *response, CamelFolder *source, - CamelFolder *destination) -{ - CamelImapMessageCache *scache = CAMEL_IMAP_FOLDER (source)->cache; - CamelImapMessageCache *dcache = CAMEL_IMAP_FOLDER (destination)->cache; - char *validity, *srcset, *destset; - GPtrArray *src, *dest; - int i; - - validity = camel_strstrcase (response->status, "[COPYUID "); - if (!validity) - return; - validity += 9; - if (strtoul (validity, NULL, 10) != - CAMEL_IMAP_SUMMARY (destination->summary)->validity) - return; - - srcset = strchr (validity, ' '); - if (!srcset++) - goto lose; - destset = strchr (srcset, ' '); - if (!destset++) - goto lose; - - src = imap_uid_set_to_array (source->summary, srcset); - dest = imap_uid_set_to_array (destination->summary, destset); - - if (src && dest && src->len == dest->len) { - /* We don't have to worry about deadlocking on the - * cache locks here, because we've got the store's - * command lock too, so no one else could be here. - */ - CAMEL_IMAP_FOLDER_LOCK (source, cache_lock); - CAMEL_IMAP_FOLDER_LOCK (destination, cache_lock); - for (i = 0; i < src->len; i++) { - camel_imap_message_cache_copy (scache, src->pdata[i], - dcache, dest->pdata[i], - NULL); - } - CAMEL_IMAP_FOLDER_UNLOCK (source, cache_lock); - CAMEL_IMAP_FOLDER_UNLOCK (destination, cache_lock); - - imap_uid_array_free (src); - imap_uid_array_free (dest); - return; - } - - imap_uid_array_free (src); - imap_uid_array_free (dest); - lose: - g_warning ("Bad COPYUID response from server"); -} - -static void -do_copy (CamelFolder *source, GPtrArray *uids, - CamelFolder *destination, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store); - CamelImapResponse *response; - char *uidset; - int uid = 0; - - while (uid < uids->len && !camel_exception_is_set (ex)) { - uidset = imap_uid_array_to_set (source->summary, uids, uid, UID_SET_LIMIT, &uid); - - response = camel_imap_command (store, source, ex, "UID COPY %s %F", - uidset, destination->full_name); - - g_free (uidset); - - if (response && (store->capabilities & IMAP_CAPABILITY_UIDPLUS)) - handle_copyuid (response, source, destination); - - camel_imap_response_free (store, response); - } -} - -static void -imap_transfer_online (CamelFolder *source, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store); - int count, i; - - /* Sync message flags if needed. */ - imap_sync_online (source, ex); - if (camel_exception_is_set (ex)) - return; - - count = camel_folder_summary_count (dest->summary); - - qsort (uids->pdata, uids->len, sizeof (void *), uid_compar); - - /* Now copy the messages */ - do_copy (source, uids, dest, ex); - if (camel_exception_is_set (ex)) - return; - - /* Make the destination notice its new messages */ - CAMEL_SERVICE_LOCK (store, connect_lock); - if (store->current_folder != dest || - camel_folder_summary_count (dest->summary) == count) - camel_folder_refresh_info (dest, ex); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - if (delete_originals) { - for (i = 0; i < uids->len; i++) - camel_folder_delete_message (source, uids->pdata[i]); - } - - /* FIXME */ - if (transferred_uids) - *transferred_uids = NULL; -} - -static void -imap_transfer_resyncing (CamelFolder *source, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, CamelException *ex) -{ - CamelDiscoDiary *diary = CAMEL_DISCO_STORE (source->parent_store)->diary; - GPtrArray *realuids; - int first, i; - const char *uid; - CamelMimeMessage *message; - CamelMessageInfo *info; - - qsort (uids->pdata, uids->len, sizeof (void *), uid_compar); - - /* This is trickier than append_resyncing, because some of - * the messages we are copying may have been copied or - * appended into @source while we were offline, in which case - * if we don't have UIDPLUS, we won't know their real UIDs, - * so we'll have to append them rather than copying. - */ - - realuids = g_ptr_array_new (); - - i = 0; - while (i < uids->len) { - /* Skip past real UIDs */ - for (first = i; i < uids->len; i++) { - uid = uids->pdata[i]; - - if (!isdigit ((unsigned char)*uid)) { - uid = camel_disco_diary_uidmap_lookup (diary, uid); - if (!uid) - break; - } - g_ptr_array_add (realuids, (char *)uid); - - if (delete_originals) - camel_folder_delete_message (source, uid); - } - - /* If we saw any real UIDs, do a COPY */ - if (i != first) { - do_copy (source, realuids, dest, ex); - g_ptr_array_set_size (realuids, 0); - if (i == uids->len || camel_exception_is_set (ex)) - break; - } - - /* Deal with fake UIDs */ - while (i < uids->len && - !isdigit (*(unsigned char *)(uids->pdata[i])) && - !camel_exception_is_set (ex)) { - uid = uids->pdata[i]; - message = camel_folder_get_message (source, uid, NULL); - if (!message) { - /* Message must have been expunged */ - continue; - } - info = camel_folder_get_message_info (source, uid); - g_return_if_fail (info != NULL); - - imap_append_online (dest, message, info, NULL, ex); - camel_folder_free_message_info (source, info); - camel_object_unref (CAMEL_OBJECT (message)); - if (delete_originals) - camel_folder_delete_message (source, uid); - i++; - } - } - - g_ptr_array_free (realuids, FALSE); - - /* FIXME */ - if (transferred_uids) - *transferred_uids = NULL; -} - -static GPtrArray * -imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - GPtrArray *matches, *summary; - - /* we could get around this by creating a new search object each time, - but i doubt its worth it since any long operation would lock the - command channel too */ - CAMEL_IMAP_FOLDER_LOCK(folder, search_lock); - - camel_folder_search_set_folder (imap_folder->search, folder); - summary = camel_folder_get_summary(folder); - camel_folder_search_set_summary(imap_folder->search, summary); - matches = camel_folder_search_execute_expression (imap_folder->search, expression, ex); - - CAMEL_IMAP_FOLDER_UNLOCK(folder, search_lock); - - camel_folder_free_summary(folder, summary); - - return matches; -} - -static GPtrArray * -imap_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER(folder); - GPtrArray *summary, *matches; - int i; - - /* NOTE: could get away without the search lock by creating a new - search object each time */ - - qsort (uids->pdata, uids->len, sizeof (void *), uid_compar); - - summary = g_ptr_array_new(); - for (i=0;ilen;i++) { - CamelMessageInfo *info; - - info = camel_folder_get_message_info(folder, uids->pdata[i]); - if (info) - g_ptr_array_add(summary, info); - } - - if (summary->len == 0) - return summary; - - CAMEL_IMAP_FOLDER_LOCK(folder, search_lock); - - camel_folder_search_set_folder(imap_folder->search, folder); - camel_folder_search_set_summary(imap_folder->search, summary); - - matches = camel_folder_search_execute_expression(imap_folder->search, expression, ex); - - CAMEL_IMAP_FOLDER_UNLOCK(folder, search_lock); - - for (i=0;ilen;i++) - camel_folder_free_message_info(folder, summary->pdata[i]); - g_ptr_array_free(summary, TRUE); - - return matches; -} - -static void -imap_search_free (CamelFolder *folder, GPtrArray *uids) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - - g_return_if_fail (imap_folder->search); - - CAMEL_IMAP_FOLDER_LOCK(folder, search_lock); - - camel_folder_search_free_result (imap_folder->search, uids); - - CAMEL_IMAP_FOLDER_UNLOCK(folder, search_lock); -} - -static CamelMimeMessage *get_message (CamelImapFolder *imap_folder, - const char *uid, - const char *part_specifier, - CamelMessageContentInfo *ci, - CamelException *ex); - -struct _part_spec_stack { - struct _part_spec_stack *parent; - int part; -}; - -static void -part_spec_push (struct _part_spec_stack **stack, int part) -{ - struct _part_spec_stack *node; - - node = g_new (struct _part_spec_stack, 1); - node->parent = *stack; - node->part = part; - - *stack = node; -} - -static int -part_spec_pop (struct _part_spec_stack **stack) -{ - struct _part_spec_stack *node; - int part; - - g_return_val_if_fail (*stack != NULL, 0); - - node = *stack; - *stack = node->parent; - - part = node->part; - g_free (node); - - return part; -} - -static char * -content_info_get_part_spec (CamelMessageContentInfo *ci) -{ - struct _part_spec_stack *stack = NULL; - CamelMessageContentInfo *node; - char *part_spec, *buf; - size_t len = 1; - int part; - - node = ci; - while (node->parent) { - CamelMessageContentInfo *child; - - /* FIXME: is this only supposed to apply if 'node' is a multipart? */ - if (node->parent->parent && camel_content_type_is (node->parent->type, "message", "*")) { - node = node->parent; - continue; - } - - child = node->parent->childs; - for (part = 1; child; part++) { - if (child == node) - break; - - child = child->next; - } - - part_spec_push (&stack, part); - - len += 2; - while ((part = part / 10)) - len++; - - node = node->parent; - } - - buf = part_spec = g_malloc (len); - part_spec[0] = '\0'; - - while (stack) { - part = part_spec_pop (&stack); - buf += sprintf (buf, "%d%s", part, stack ? "." : ""); - } - - return part_spec; -} - -/* Fetch the contents of the MIME part indicated by @ci, which is part - * of message @uid in @folder. - */ -static CamelDataWrapper * -get_content (CamelImapFolder *imap_folder, const char *uid, - CamelMimePart *part, CamelMessageContentInfo *ci, - CamelException *ex) -{ - CamelDataWrapper *content = NULL; - CamelStream *stream; - char *part_spec; - - part_spec = content_info_get_part_spec (ci); - - /* There are three cases: multipart/signed, multipart, message/rfc822, and "other" */ - if (camel_content_type_is (ci->type, "multipart", "signed")) { - CamelMultipartSigned *body_mp; - char *spec; - int ret; - - /* Note: because we get the content parts uninterpreted anyway, we could potentially - just use the normalmultipart code, except that multipart/signed wont let you yet! */ - - body_mp = camel_multipart_signed_new (); - /* need to set this so it grabs the boundary and other info about the signed type */ - /* we assume that part->content_type is more accurate/full than ci->type */ - camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (body_mp), CAMEL_DATA_WRAPPER (part)->mime_type); - - spec = g_alloca (strlen (part_spec) + 6); - sprintf (spec, part_spec[0] ? "%s.TEXT" : "TEXT", part_spec); - g_free (part_spec); - - stream = camel_imap_folder_fetch_data (imap_folder, uid, spec, FALSE, ex); - if (stream) { - ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (body_mp), stream); - camel_object_unref (CAMEL_OBJECT (stream)); - if (ret == -1) { - camel_object_unref ((CamelObject *) body_mp); - return NULL; - } - } - - return (CamelDataWrapper *) body_mp; - } else if (camel_content_type_is (ci->type, "multipart", "*")) { - CamelMultipart *body_mp; - char *child_spec; - int speclen, num; - - if (camel_content_type_is (ci->type, "multipart", "encrypted")) - body_mp = (CamelMultipart *) camel_multipart_encrypted_new (); - else - body_mp = camel_multipart_new (); - - /* need to set this so it grabs the boundary and other info about the multipart */ - /* we assume that part->content_type is more accurate/full than ci->type */ - camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (body_mp), CAMEL_DATA_WRAPPER (part)->mime_type); - - speclen = strlen (part_spec); - child_spec = g_malloc (speclen + 17); /* dot + 10 + dot + MIME + nul */ - memcpy (child_spec, part_spec, speclen); - if (speclen > 0) - child_spec[speclen++] = '.'; - g_free (part_spec); - - ci = ci->childs; - num = 1; - while (ci) { - sprintf (child_spec + speclen, "%d.MIME", num++); - stream = camel_imap_folder_fetch_data (imap_folder, uid, child_spec, FALSE, ex); - if (stream) { - int ret; - - part = camel_mime_part_new (); - ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (part), stream); - camel_object_unref (CAMEL_OBJECT (stream)); - if (ret == -1) { - camel_object_unref (CAMEL_OBJECT (part)); - camel_object_unref (CAMEL_OBJECT (body_mp)); - g_free (child_spec); - return NULL; - } - - content = get_content (imap_folder, uid, part, ci, ex); - } - - if (!stream || !content) { - camel_object_unref (CAMEL_OBJECT (body_mp)); - g_free (child_spec); - return NULL; - } - - camel_medium_set_content_object (CAMEL_MEDIUM (part), content); - camel_object_unref (CAMEL_OBJECT (content)); - camel_multipart_add_part (body_mp, part); - camel_object_unref (CAMEL_OBJECT (part)); - - ci = ci->next; - } - - g_free (child_spec); - - return (CamelDataWrapper *) body_mp; - } else if (camel_content_type_is (ci->type, "message", "rfc822")) { - content = (CamelDataWrapper *) get_message (imap_folder, uid, part_spec, ci->childs, ex); - g_free (part_spec); - return content; - } else { - content = camel_imap_wrapper_new (imap_folder, ci->type, uid, *part_spec ? part_spec : "1", part); - g_free (part_spec); - return content; - } -} - -static CamelMimeMessage * -get_message (CamelImapFolder *imap_folder, const char *uid, - const char *part_spec, CamelMessageContentInfo *ci, - CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (CAMEL_FOLDER (imap_folder)->parent_store); - CamelDataWrapper *content; - CamelMimeMessage *msg; - CamelStream *stream; - char *section_text; - int ret; - - section_text = g_strdup_printf ("%s%s%s", part_spec, *part_spec ? "." : "", - store->server_level >= IMAP_LEVEL_IMAP4REV1 ? "HEADER" : "0"); - stream = camel_imap_folder_fetch_data (imap_folder, uid, section_text, FALSE, ex); - g_free (section_text); - if (!stream) - return NULL; - - msg = camel_mime_message_new (); - ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream); - camel_object_unref (CAMEL_OBJECT (stream)); - if (ret == -1) { - camel_object_unref (CAMEL_OBJECT (msg)); - return NULL; - } - - content = get_content (imap_folder, uid, CAMEL_MIME_PART (msg), ci, ex); - if (!content) { - camel_object_unref (CAMEL_OBJECT (msg)); - return NULL; - } - - camel_medium_set_content_object (CAMEL_MEDIUM (msg), content); - camel_object_unref (CAMEL_OBJECT (content)); - - return msg; -} - -/* FIXME: I pulled this number out of my butt. */ -#define IMAP_SMALL_BODY_SIZE 5120 - -static CamelMimeMessage * -get_message_simple (CamelImapFolder *imap_folder, const char *uid, - CamelStream *stream, CamelException *ex) -{ - CamelMimeMessage *msg; - CamelImapStore *imap_store = - CAMEL_IMAP_STORE (CAMEL_FOLDER (imap_folder)->parent_store); - int ret; - - if (!stream) { - stream = camel_imap_folder_fetch_data (imap_folder, uid, "", - FALSE, ex); - if (!stream) - return NULL; - } - - msg = camel_mime_message_new (); - ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), - stream); - camel_object_unref (CAMEL_OBJECT (stream)); - if (ret == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Unable to retrieve message: %s"), - g_strerror (errno)); - camel_object_unref (CAMEL_OBJECT (msg)); - return NULL; - } - - /* FIXME, this shouldn't be done this way. */ - camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Source", - imap_store->base_url); - return msg; -} - -static CamelMimeMessage * -imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelMessageInfo *mi; - CamelMimeMessage *msg; - CamelStream *stream = NULL; - - /* If the server doesn't support IMAP4rev1, or we already have - * the whole thing cached, fetch it in one piece. - */ - if (store->server_level < IMAP_LEVEL_IMAP4REV1 || - (stream = camel_imap_folder_fetch_data (imap_folder, uid, "", TRUE, NULL))) - return get_message_simple (imap_folder, uid, stream, ex); - - /* If we're not actually connected and it's not in the cache, - * that's as far as we can go. - */ - if (camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex) == FALSE) - return NULL; - - mi = camel_folder_summary_uid (folder->summary, uid); - if (mi == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s\n %s"), uid, _("No such message")); - return NULL; - } - - /* If the message is small, fetch it in one piece. */ - if (mi->size < IMAP_SMALL_BODY_SIZE) { - camel_folder_summary_info_free (folder->summary, mi); - return get_message_simple (imap_folder, uid, NULL, ex); - } - - /* For larger messages, fetch the structure and build a message - * with offline parts. (We check mi->content->type rather than - * mi->content because camel_folder_summary_info_new always creates - * an empty content struct.) - */ - if (!mi->content->type) { - CamelImapResponse *response; - GData *fetch_data = NULL; - char *body, *found_uid; - int i; - - if (camel_disco_store_status (CAMEL_DISCO_STORE (store)) == CAMEL_DISCO_STORE_OFFLINE) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("This message is not currently available")); - return NULL; - } - - response = camel_imap_command (store, folder, ex, - "UID FETCH %s BODY", uid); - if (!response) { - camel_folder_summary_info_free (folder->summary, mi); - return NULL; - } - - for (i = 0, body = NULL; i < response->untagged->len; i++) { - fetch_data = parse_fetch_response (imap_folder, response->untagged->pdata[i]); - if (fetch_data) { - found_uid = g_datalist_get_data (&fetch_data, "UID"); - body = g_datalist_get_data (&fetch_data, "BODY"); - if (found_uid && body && !strcmp (found_uid, uid)) - break; - g_datalist_clear (&fetch_data); - fetch_data = NULL; - body = NULL; - } - } - - if (body) - imap_parse_body ((const char **) &body, folder, mi->content); - - if (fetch_data) - g_datalist_clear (&fetch_data); - - camel_imap_response_free (store, response); - - if (!mi->content->type) { - /* FETCH returned OK, but we didn't parse a BODY - * response. Courier will return invalid BODY - * responses for invalidly MIMEd messages, so - * fall back to fetching the entire thing and - * let the mailer's "bad MIME" code handle it. - */ - camel_folder_summary_info_free (folder->summary, mi); - return get_message_simple (imap_folder, uid, NULL, ex); - } - } - - msg = get_message (imap_folder, uid, "", mi->content, ex); - /* FIXME, this shouldn't be done this way. */ - camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Source", - store->base_url); - camel_folder_summary_info_free (folder->summary, mi); - - return msg; -} - -static void -imap_cache_message (CamelDiscoFolder *disco_folder, const char *uid, - CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (disco_folder); - CamelStream *stream; - - stream = camel_imap_folder_fetch_data (imap_folder, uid, "", FALSE, ex); - if (stream) - camel_object_unref (CAMEL_OBJECT (stream)); -} - -/* We pretend that a FLAGS or RFC822.SIZE response is always exactly - * 20 bytes long, and a BODY[HEADERS] response is always 2000 bytes - * long. Since we know how many of each kind of response we're - * expecting, we can find the total (pretend) amount of server traffic - * to expect and then count off the responses as we read them to update - * the progress bar. - */ -#define IMAP_PRETEND_SIZEOF_FLAGS 20 -#define IMAP_PRETEND_SIZEOF_SIZE 20 -#define IMAP_PRETEND_SIZEOF_HEADERS 2000 - -static char *tm_months[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static gboolean -decode_time (const unsigned char **in, int *hour, int *min, int *sec) -{ - register const unsigned char *inptr; - int *val, colons = 0; - - *hour = *min = *sec = 0; - - val = hour; - for (inptr = *in; *inptr && !isspace ((int) *inptr); inptr++) { - if (*inptr == ':') { - colons++; - switch (colons) { - case 1: - val = min; - break; - case 2: - val = sec; - break; - default: - return FALSE; - } - } else if (!isdigit ((int) *inptr)) - return FALSE; - else - *val = (*val * 10) + (*inptr - '0'); - } - - *in = inptr; - - return TRUE; -} - -static time_t -decode_internaldate (const unsigned char *in) -{ - const unsigned char *inptr = in; - int hour, min, sec, n; - unsigned char *buf; - struct tm tm; - time_t date; - - memset ((void *) &tm, 0, sizeof (struct tm)); - - tm.tm_mday = strtoul (inptr, (char **) &buf, 10); - if (buf == inptr || *buf != '-') - return (time_t) -1; - - inptr = buf + 1; - if (inptr[3] != '-') - return (time_t) -1; - - for (n = 0; n < 12; n++) { - if (!strncasecmp (inptr, tm_months[n], 3)) - break; - } - - if (n >= 12) - return (time_t) -1; - - tm.tm_mon = n; - - inptr += 4; - - n = strtoul (inptr, (char **) &buf, 10); - if (buf == inptr || *buf != ' ') - return (time_t) -1; - - tm.tm_year = n - 1900; - - inptr = buf + 1; - if (!decode_time (&inptr, &hour, &min, &sec)) - return (time_t) -1; - - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; - - n = strtol (inptr, NULL, 10); - - date = e_mktime_utc (&tm); - - /* date is now GMT of the time we want, but not offset by the timezone ... */ - - /* this should convert the time to the GMT equiv time */ - date -= ((n / 100) * 60 * 60) + (n % 100) * 60; - - return date; -} - -static void -add_message_from_data (CamelFolder *folder, GPtrArray *messages, - int first, GData *data) -{ - CamelMimeMessage *msg; - CamelStream *stream; - CamelMessageInfo *mi; - const char *idate; - int seq; - - seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE")); - if (seq < first) - return; - stream = g_datalist_get_data (&data, "BODY_PART_STREAM"); - if (!stream) - return; - - if (seq - first >= messages->len) - g_ptr_array_set_size (messages, seq - first + 1); - - msg = camel_mime_message_new (); - if (camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream) == -1) { - camel_object_unref (CAMEL_OBJECT (msg)); - return; - } - - mi = camel_folder_summary_info_new_from_message (folder->summary, msg); - camel_object_unref (CAMEL_OBJECT (msg)); - - if ((idate = g_datalist_get_data (&data, "INTERNALDATE"))) - mi->date_received = decode_internaldate (idate); - - if (mi->date_received == -1) - mi->date_received = mi->date_sent; - - messages->pdata[seq - first] = mi; -} - - -#define CAMEL_MESSAGE_INFO_HEADERS "DATE FROM TO CC SUBJECT REFERENCES IN-REPLY-TO MESSAGE-ID MIME-VERSION CONTENT-TYPE" - -/* FIXME: this needs to be kept in sync with camel-mime-utils.c's list - of mailing-list headers and so might be best if this were - auto-generated? */ -#define MAILING_LIST_HEADERS "X-MAILING-LIST X-LOOP LIST-ID LIST-POST MAILING-LIST ORIGINATOR X-LIST SENDER RETURN-PATH X-BEENTHERE" - -static void -imap_update_summary (CamelFolder *folder, int exists, - CamelFolderChangeInfo *changes, - CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - GPtrArray *fetch_data = NULL, *messages = NULL, *needheaders; - guint32 flags, uidval; - int i, seq, first, size, got; - CamelImapResponseType type; - const char *header_spec; - CamelMessageInfo *mi, *info; - CamelStream *stream; - char *uid, *resp; - GData *data; - - CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock); - if (store->server_level >= IMAP_LEVEL_IMAP4REV1) - header_spec = "HEADER.FIELDS.NOT (RECEIVED)"; - else - header_spec = "0"; - - /* Figure out if any of the new messages are already cached (which - * may be the case if we're re-syncing after disconnected operation). - * If so, get their UIDs, FLAGS, and SIZEs. If not, get all that - * and ask for the headers too at the same time. - */ - seq = camel_folder_summary_count (folder->summary); - first = seq + 1; - if (seq > 0) { - mi = camel_folder_summary_index (folder->summary, seq - 1); - uidval = strtoul(camel_message_info_uid (mi), NULL, 10); - camel_folder_summary_info_free (folder->summary, mi); - } else - uidval = 0; - - size = (exists - seq) * (IMAP_PRETEND_SIZEOF_FLAGS + IMAP_PRETEND_SIZEOF_SIZE + IMAP_PRETEND_SIZEOF_HEADERS); - got = 0; - if (!camel_imap_command_start (store, folder, ex, - "UID FETCH %d:* (FLAGS RFC822.SIZE INTERNALDATE BODY.PEEK[%s])", - uidval + 1, header_spec)) - return; - camel_operation_start (NULL, _("Fetching summary information for new messages")); - - /* Parse the responses. We can't add a message to the summary - * until we've gotten its headers, and there's no guarantee - * the server will send the responses in a useful order... - */ - fetch_data = g_ptr_array_new (); - messages = g_ptr_array_new (); - while ((type = camel_imap_command_response (store, &resp, ex)) == - CAMEL_IMAP_RESPONSE_UNTAGGED) { - data = parse_fetch_response (imap_folder, resp); - g_free (resp); - if (!data) - continue; - - seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE")); - if (seq < first) { - g_datalist_clear (&data); - continue; - } - - if (g_datalist_get_data (&data, "FLAGS")) - got += IMAP_PRETEND_SIZEOF_FLAGS; - if (g_datalist_get_data (&data, "RFC822.SIZE")) - got += IMAP_PRETEND_SIZEOF_SIZE; - stream = g_datalist_get_data (&data, "BODY_PART_STREAM"); - if (stream) { - got += IMAP_PRETEND_SIZEOF_HEADERS; - - /* Use the stream now so we don't tie up many - * many fds if we're fetching many many messages. - */ - add_message_from_data (folder, messages, first, data); - g_datalist_set_data (&data, "BODY_PART_STREAM", NULL); - } - - camel_operation_progress (NULL, got * 100 / size); - g_ptr_array_add (fetch_data, data); - } - camel_operation_end (NULL); - - if (type == CAMEL_IMAP_RESPONSE_ERROR) - goto lose; - - /* Free the final tagged response */ - g_free (resp); - - /* Figure out which headers we still need to fetch. */ - needheaders = g_ptr_array_new (); - size = got = 0; - for (i = 0; i < fetch_data->len; i++) { - data = fetch_data->pdata[i]; - if (g_datalist_get_data (&data, "BODY_PART_LEN")) - continue; - - uid = g_datalist_get_data (&data, "UID"); - if (uid) { - g_ptr_array_add (needheaders, uid); - size += IMAP_PRETEND_SIZEOF_HEADERS; - } - } - - /* And fetch them */ - if (needheaders->len) { - char *uidset; - int uid = 0; - - qsort (needheaders->pdata, needheaders->len, - sizeof (void *), uid_compar); - - camel_operation_start (NULL, _("Fetching summary information for new messages")); - - while (uid < needheaders->len) { - uidset = imap_uid_array_to_set (folder->summary, needheaders, uid, UID_SET_LIMIT, &uid); - if (!camel_imap_command_start (store, folder, ex, - "UID FETCH %s BODY.PEEK[%s]", - uidset, header_spec)) { - g_ptr_array_free (needheaders, TRUE); - camel_operation_end (NULL); - g_free (uidset); - goto lose; - } - g_free (uidset); - - while ((type = camel_imap_command_response (store, &resp, ex)) - == CAMEL_IMAP_RESPONSE_UNTAGGED) { - data = parse_fetch_response (imap_folder, resp); - g_free (resp); - if (!data) - continue; - - stream = g_datalist_get_data (&data, "BODY_PART_STREAM"); - if (stream) { - add_message_from_data (folder, messages, first, data); - got += IMAP_PRETEND_SIZEOF_HEADERS; - camel_operation_progress (NULL, got * 100 / size); - } - g_datalist_clear (&data); - } - - if (type == CAMEL_IMAP_RESPONSE_ERROR) { - g_ptr_array_free (needheaders, TRUE); - camel_operation_end (NULL); - goto lose; - } - } - - g_ptr_array_free (needheaders, TRUE); - camel_operation_end (NULL); - } - - /* Now finish up summary entries (fix UIDs, set flags and size) */ - for (i = 0; i < fetch_data->len; i++) { - data = fetch_data->pdata[i]; - - seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE")); - if (seq >= first + messages->len) { - g_datalist_clear (&data); - continue; - } - - mi = messages->pdata[seq - first]; - if (mi == NULL) { - CamelMessageInfo *pmi = NULL; - int j; - - /* This is a kludge around a bug in Exchange - * 5.5 that sometimes claims multiple messages - * have the same UID. See bug #17694 for - * details. The "solution" is to create a fake - * message-info with the same details as the - * previously valid message. Yes, the user - * will have a clone in his/her message-list, - * but at least we don't crash. - */ - - /* find the previous valid message info */ - for (j = seq - first - 1; j >= 0; j--) { - pmi = messages->pdata[j]; - if (pmi != NULL) - break; - } - - if (pmi == NULL) { - /* Server response is *really* fucked up, - I guess we just pretend it never happened? */ - continue; - } - - mi = camel_message_info_new (); - camel_message_info_dup_to (pmi, mi); - } - - uid = g_datalist_get_data (&data, "UID"); - if (uid) - camel_message_info_set_uid (mi, g_strdup (uid)); - flags = GPOINTER_TO_INT (g_datalist_get_data (&data, "FLAGS")); - if (flags) { - ((CamelImapMessageInfo *)mi)->server_flags = flags; - /* "or" them in with the existing flags that may - * have been set by summary_info_new_from_message. - */ - mi->flags |= flags; - } - size = GPOINTER_TO_INT (g_datalist_get_data (&data, "RFC822.SIZE")); - if (size) - mi->size = size; - - g_datalist_clear (&data); - } - g_ptr_array_free (fetch_data, TRUE); - - /* And add the entries to the summary, etc. */ - for (i = 0; i < messages->len; i++) { - mi = messages->pdata[i]; - if (!mi) { - g_warning ("No information for message %d", i + first); - continue; - } - uid = (char *)camel_message_info_uid(mi); - if (uid[0] == 0) { - g_warning("Server provided no uid: message %d", i + first); - continue; - } - info = camel_folder_summary_uid(folder->summary, uid); - if (info) { - g_warning("Message already present? %s", camel_message_info_uid(mi)); - camel_folder_summary_info_free(folder->summary, info); - camel_folder_summary_info_free(folder->summary, mi); - continue; - } - - camel_folder_summary_add (folder->summary, mi); - camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi)); - - if ((mi->flags & CAMEL_IMAP_MESSAGE_RECENT)) - camel_folder_change_info_recent_uid(changes, camel_message_info_uid (mi)); - } - g_ptr_array_free (messages, TRUE); - - /* Kludge around Microsoft Exchange 5.5 IMAP - See bug #5348 for details */ - if (camel_folder_summary_count (folder->summary) != exists) { - CamelImapStore *imap_store = (CamelImapStore *) folder->parent_store; - CamelImapResponse *response; - - /* forget the currently selected folder */ - if (imap_store->current_folder) { - camel_object_unref (CAMEL_OBJECT (imap_store->current_folder)); - imap_store->current_folder = NULL; - } - - /* now re-select it and process the EXISTS response */ - response = camel_imap_command (imap_store, folder, ex, NULL); - if (response) { - camel_imap_folder_selected (folder, response, NULL); - camel_imap_response_free (imap_store, response); - } - } - - return; - - lose: - if (fetch_data) { - for (i = 0; i < fetch_data->len; i++) { - data = fetch_data->pdata[i]; - g_datalist_clear (&data); - } - g_ptr_array_free (fetch_data, TRUE); - } - if (messages) { - for (i = 0; i < messages->len; i++) { - if (messages->pdata[i]) - camel_folder_summary_info_free (folder->summary, messages->pdata[i]); - } - g_ptr_array_free (messages, TRUE); - } -} - -/* Called with the store's connect_lock locked */ -void -camel_imap_folder_changed (CamelFolder *folder, int exists, - GArray *expunged, CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - CamelFolderChangeInfo *changes; - CamelMessageInfo *info; - int len; - - CAMEL_SERVICE_ASSERT_LOCKED (folder->parent_store, connect_lock); - - changes = camel_folder_change_info_new (); - if (expunged) { - int i, id; - - for (i = 0; i < expunged->len; i++) { - id = g_array_index (expunged, int, i); - info = camel_folder_summary_index (folder->summary, id - 1); - if (info == NULL) { - /* FIXME: danw: does this mean that the summary is corrupt? */ - /* I guess a message that we never retrieved got expunged? */ - continue; - } - - camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info)); - CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock); - camel_imap_message_cache_remove (imap_folder->cache, camel_message_info_uid (info)); - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - camel_folder_summary_remove (folder->summary, info); - camel_folder_summary_info_free(folder->summary, info); - } - } - - len = camel_folder_summary_count (folder->summary); - if (exists > len) - imap_update_summary (folder, exists, changes, ex); - - if (camel_folder_change_info_changed (changes)) - camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", changes); - - camel_folder_change_info_free (changes); - camel_folder_summary_save (folder->summary); -} - -static void -imap_thaw (CamelFolder *folder) -{ - CamelImapFolder *imap_folder; - - CAMEL_FOLDER_CLASS (disco_folder_class)->thaw (folder); - if (camel_folder_is_frozen (folder)) - return; - - imap_folder = CAMEL_IMAP_FOLDER (folder); - if (imap_folder->need_refresh) { - imap_folder->need_refresh = FALSE; - imap_refresh_info (folder, NULL); - } -} - - -CamelStream * -camel_imap_folder_fetch_data (CamelImapFolder *imap_folder, const char *uid, - const char *section_text, gboolean cache_only, - CamelException *ex) -{ - CamelFolder *folder = CAMEL_FOLDER (imap_folder); - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - CamelStream *stream; - GData *fetch_data; - char *found_uid; - int i; - - /* EXPUNGE responses have to modify the cache, which means - * they have to grab the cache_lock while holding the - * connect_lock. So we grab the connect_lock now, in case - * we're going to need it below, since we can't grab it - * after the cache_lock. - */ - CAMEL_SERVICE_LOCK (store, connect_lock); - - CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock); - stream = camel_imap_message_cache_get (imap_folder->cache, uid, section_text, ex); - if (!stream && (!strcmp (section_text, "HEADER") || !strcmp (section_text, "0"))) { - camel_exception_clear (ex); - stream = camel_imap_message_cache_get (imap_folder->cache, uid, "", ex); - } - - if (stream || cache_only) { - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return stream; - } - - if (camel_disco_store_status (CAMEL_DISCO_STORE (store)) == CAMEL_DISCO_STORE_OFFLINE) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("This message is not currently available")); - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return NULL; - } - - camel_exception_clear (ex); - if (store->server_level < IMAP_LEVEL_IMAP4REV1 && !*section_text) { - response = camel_imap_command (store, folder, ex, - "UID FETCH %s RFC822.PEEK", - uid); - } else { - response = camel_imap_command (store, folder, ex, - "UID FETCH %s BODY.PEEK[%s]", - uid, section_text); - } - /* We won't need the connect_lock again after this. */ - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - if (!response) { - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - return NULL; - } - - for (i = 0; i < response->untagged->len; i++) { - fetch_data = parse_fetch_response (imap_folder, response->untagged->pdata[i]); - found_uid = g_datalist_get_data (&fetch_data, "UID"); - stream = g_datalist_get_data (&fetch_data, "BODY_PART_STREAM"); - if (found_uid && stream && !strcmp (uid, found_uid)) - break; - - g_datalist_clear (&fetch_data); - stream = NULL; - } - camel_imap_response_free (store, response); - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - if (!stream) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not find message body in FETCH response.")); - } else { - camel_object_ref (CAMEL_OBJECT (stream)); - g_datalist_clear (&fetch_data); - } - - return stream; -} - -static GData * -parse_fetch_response (CamelImapFolder *imap_folder, char *response) -{ - GData *data = NULL; - char *start, *part_spec = NULL, *body = NULL, *uid = NULL, *idate = NULL; - gboolean cache_header = TRUE, header = FALSE; - size_t body_len = 0; - - if (*response != '(') { - long seq; - - if (*response != '*' || *(response + 1) != ' ') - return NULL; - seq = strtol (response + 2, &response, 10); - if (seq == 0) - return NULL; - if (strncasecmp (response, " FETCH (", 8) != 0) - return NULL; - response += 7; - - g_datalist_set_data (&data, "SEQUENCE", GINT_TO_POINTER (seq)); - } - - do { - /* Skip the initial '(' or the ' ' between elements */ - response++; - - if (!strncasecmp (response, "FLAGS ", 6)) { - guint32 flags; - - response += 6; - /* FIXME user flags */ - flags = imap_parse_flag_list (&response); - - g_datalist_set_data (&data, "FLAGS", GUINT_TO_POINTER (flags)); - } else if (!strncasecmp (response, "RFC822.SIZE ", 12)) { - unsigned long size; - - response += 12; - size = strtoul (response, &response, 10); - g_datalist_set_data (&data, "RFC822.SIZE", GUINT_TO_POINTER (size)); - } else if (!strncasecmp (response, "BODY[", 5) || - !strncasecmp (response, "RFC822 ", 7)) { - char *p; - - if (*response == 'B') { - response += 5; - - /* HEADER], HEADER.FIELDS (...)], or 0] */ - if (!strncasecmp (response, "HEADER", 6)) { - header = TRUE; - if (!strncasecmp (response + 6, ".FIELDS", 7)) - cache_header = FALSE; - } else if (!strncasecmp (response, "0]", 2)) - header = TRUE; - - p = strchr (response, ']'); - if (!p || *(p + 1) != ' ') - break; - - if (cache_header) - part_spec = g_strndup (response, p - response); - else - part_spec = g_strdup ("HEADER.FIELDS"); - - response = p + 2; - } else { - part_spec = g_strdup (""); - response += 7; - - if (!strncasecmp (response, "HEADER", 6)) - header = TRUE; - } - - body = imap_parse_nstring ((const char **) &response, &body_len); - if (!response) { - g_free (part_spec); - break; - } - - if (!body) - body = g_strdup (""); - g_datalist_set_data_full (&data, "BODY_PART_SPEC", part_spec, g_free); - g_datalist_set_data_full (&data, "BODY_PART_DATA", body, g_free); - g_datalist_set_data (&data, "BODY_PART_LEN", GINT_TO_POINTER (body_len)); - } else if (!strncasecmp (response, "BODY ", 5) || - !strncasecmp (response, "BODYSTRUCTURE ", 14)) { - response = strchr (response, ' ') + 1; - start = response; - imap_skip_list ((const char **) &response); - g_datalist_set_data_full (&data, "BODY", g_strndup (start, response - start), g_free); - } else if (!strncasecmp (response, "UID ", 4)) { - int len; - - len = strcspn (response + 4, " )"); - uid = g_strndup (response + 4, len); - g_datalist_set_data_full (&data, "UID", uid, g_free); - response += 4 + len; - } else if (!strncasecmp (response, "INTERNALDATE ", 13)) { - int len; - - response += 13; - if (*response == '"') { - response++; - len = strcspn (response, "\""); - idate = g_strndup (response, len); - g_datalist_set_data_full (&data, "INTERNALDATE", idate, g_free); - response += len + 1; - } - } else { - g_warning ("Unexpected FETCH response from server: (%s", response); - break; - } - } while (response && *response != ')'); - - if (!response || *response != ')') { - g_datalist_clear (&data); - return NULL; - } - - if (uid && body) { - CamelStream *stream; - - if (header && !cache_header) { - stream = camel_stream_mem_new_with_buffer (body, body_len); - } else { - CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock); - stream = camel_imap_message_cache_insert (imap_folder->cache, - uid, part_spec, - body, body_len, NULL); - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - } - - if (stream) - g_datalist_set_data_full (&data, "BODY_PART_STREAM", stream, - (GDestroyNotify) camel_object_unref); - } - - return data; -} - diff --git a/camel/providers/imap/camel-imap-folder.h b/camel/providers/imap/camel-imap-folder.h deleted file mode 100644 index a49f7bd497..0000000000 --- a/camel/providers/imap/camel-imap-folder.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-folder.h: class for an imap folder */ - -/* - * Authors: - * Dan Winship - * Jeffrey Stedfast - * - * Copyright (C) 2000, 2001 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAP_FOLDER_H -#define CAMEL_IMAP_FOLDER_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include "camel-imap-types.h" -#include -#include - -#define CAMEL_IMAP_FOLDER_TYPE (camel_imap_folder_get_type ()) -#define CAMEL_IMAP_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAP_FOLDER_TYPE, CamelImapFolder)) -#define CAMEL_IMAP_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAP_FOLDER_TYPE, CamelImapFolderClass)) -#define CAMEL_IS_IMAP_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAP_FOLDER_TYPE)) - -struct _CamelImapFolder { - CamelDiscoFolder parent_object; - - struct _CamelImapFolderPrivate *priv; - - gboolean need_rescan, need_refresh; - CamelFolderSearch *search; - CamelImapMessageCache *cache; -}; - - -typedef struct { - CamelDiscoFolderClass parent_class; - - /* Virtual methods */ - -} CamelImapFolderClass; - - -/* public methods */ -CamelFolder *camel_imap_folder_new (CamelStore *parent, - const char *folder_name, - const char *folder_dir, - CamelException *ex); - -void camel_imap_folder_selected (CamelFolder *folder, - CamelImapResponse *response, - CamelException *ex); - -void camel_imap_folder_changed (CamelFolder *folder, int exists, - GArray *expunged, CamelException *ex); - -CamelStream *camel_imap_folder_fetch_data (CamelImapFolder *imap_folder, - const char *uid, - const char *section_text, - gboolean cache_only, - CamelException *ex); - -/* Standard Camel function */ -CamelType camel_imap_folder_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_IMAP_FOLDER_H */ diff --git a/camel/providers/imap/camel-imap-message-cache.c b/camel/providers/imap/camel-imap-message-cache.c deleted file mode 100644 index 559c6d2f88..0000000000 --- a/camel/providers/imap/camel-imap-message-cache.c +++ /dev/null @@ -1,527 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-message-cache.c: Class for an IMAP message cache */ - -/* - * Author: - * Dan Winship - * - * Copyright (C) 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "camel-imap-message-cache.h" -#include "camel-data-wrapper.h" -#include "camel-exception.h" -#include "camel-stream-fs.h" - -static void finalize (CamelImapMessageCache *cache); -static void stream_finalize (CamelObject *stream, gpointer event_data, gpointer user_data); - - -CamelType -camel_imap_message_cache_get_type (void) -{ - static CamelType camel_imap_message_cache_type = CAMEL_INVALID_TYPE; - - if (camel_imap_message_cache_type == CAMEL_INVALID_TYPE) { - camel_imap_message_cache_type = camel_type_register ( - CAMEL_OBJECT_TYPE, "CamelImapMessageCache", - sizeof (CamelImapMessageCache), - sizeof (CamelImapMessageCacheClass), - NULL, - NULL, - NULL, - (CamelObjectFinalizeFunc) finalize); - } - - return camel_imap_message_cache_type; -} - -static void -free_part (gpointer key, gpointer value, gpointer data) -{ - if (value) { - if (strchr (key, '.')) { - camel_object_unhook_event (value, "finalize", - stream_finalize, data); - camel_object_unref (value); - } else - g_ptr_array_free (value, TRUE); - } - g_free (key); -} - -static void -finalize (CamelImapMessageCache *cache) -{ - if (cache->path) - g_free (cache->path); - if (cache->parts) { - g_hash_table_foreach (cache->parts, free_part, cache); - g_hash_table_destroy (cache->parts); - } - if (cache->cached) - g_hash_table_destroy (cache->cached); -} - -static void -cache_put (CamelImapMessageCache *cache, const char *uid, const char *key, - CamelStream *stream) -{ - char *hash_key; - GPtrArray *subparts; - gpointer okey, ostream; - guint32 uidval; - - uidval = strtoul (uid, NULL, 10); - if (uidval > cache->max_uid) - cache->max_uid = uidval; - - subparts = g_hash_table_lookup (cache->parts, uid); - if (!subparts) { - subparts = g_ptr_array_new (); - g_hash_table_insert (cache->parts, g_strdup (uid), subparts); - } - - if (g_hash_table_lookup_extended (cache->parts, key, &okey, &ostream)) { - if (ostream) { - camel_object_unhook_event (ostream, "finalize", - stream_finalize, cache); - g_hash_table_remove (cache->cached, ostream); - camel_object_unref (ostream); - } - hash_key = okey; - } else { - hash_key = g_strdup (key); - g_ptr_array_add (subparts, hash_key); - } - - g_hash_table_insert (cache->parts, hash_key, stream); - g_hash_table_insert (cache->cached, stream, hash_key); - - if (stream) { - camel_object_hook_event (CAMEL_OBJECT (stream), "finalize", - stream_finalize, cache); - } -} - -/** - * camel_imap_message_cache_new: - * @path: directory to use for storage - * @summary: CamelFolderSummary for the folder we are caching - * @ex: a CamelException - * - * Return value: a new CamelImapMessageCache object using @path for - * storage. If cache files already exist in @path, then any that do not - * correspond to messages in @summary will be deleted. - **/ -CamelImapMessageCache * -camel_imap_message_cache_new (const char *path, CamelFolderSummary *summary, - CamelException *ex) -{ - CamelImapMessageCache *cache; - DIR *dir; - struct dirent *d; - char *uid, *p; - GPtrArray *deletes; - CamelMessageInfo *info; - - dir = opendir (path); - if (!dir) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open cache directory: %s"), - g_strerror (errno)); - return NULL; - } - - cache = (CamelImapMessageCache *)camel_object_new (CAMEL_IMAP_MESSAGE_CACHE_TYPE); - cache->path = g_strdup (path); - - cache->parts = g_hash_table_new (g_str_hash, g_str_equal); - cache->cached = g_hash_table_new (NULL, NULL); - deletes = g_ptr_array_new (); - while ((d = readdir (dir))) { - if (!isdigit (d->d_name[0])) - continue; - - p = strchr (d->d_name, '.'); - if (p) - uid = g_strndup (d->d_name, p - d->d_name); - else - uid = g_strdup (d->d_name); - - info = camel_folder_summary_uid (summary, uid); - if (info) { - camel_folder_summary_info_free (summary, info); - cache_put (cache, uid, d->d_name, NULL); - } else - g_ptr_array_add (deletes, g_strdup_printf ("%s/%s", cache->path, d->d_name)); - g_free (uid); - } - closedir (dir); - - while (deletes->len) { - unlink (deletes->pdata[0]); - g_free (deletes->pdata[0]); - g_ptr_array_remove_index_fast (deletes, 0); - } - g_ptr_array_free (deletes, TRUE); - - return cache; -} - -/** - * camel_imap_message_cache_max_uid: - * @cache: the cache - * - * Return value: the largest (real) UID in the cache. - **/ -guint32 -camel_imap_message_cache_max_uid (CamelImapMessageCache *cache) -{ - return cache->max_uid; -} - -/** - * camel_imap_message_cache_set_path: - * @cache: - * @path: - * - * Set the path used for the message cache. - **/ -void -camel_imap_message_cache_set_path (CamelImapMessageCache *cache, const char *path) -{ - g_free(cache->path); - cache->path = g_strdup(path); -} - -static void -stream_finalize (CamelObject *stream, gpointer event_data, gpointer user_data) -{ - CamelImapMessageCache *cache = user_data; - char *key; - - key = g_hash_table_lookup (cache->cached, stream); - if (!key) - return; - g_hash_table_remove (cache->cached, stream); - g_hash_table_insert (cache->parts, key, NULL); -} - - -static CamelStream * -insert_setup (CamelImapMessageCache *cache, const char *uid, const char *part_spec, - char **path, char **key, CamelException *ex) -{ - CamelStream *stream; - int fd; - - *path = g_strdup_printf ("%s/%s.%s", cache->path, uid, part_spec); - *key = strrchr (*path, '/') + 1; - stream = g_hash_table_lookup (cache->parts, *key); - if (stream) - camel_object_unref (CAMEL_OBJECT (stream)); - - fd = open (*path, O_RDWR | O_CREAT | O_TRUNC, 0600); - if (fd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to cache message %s: %s"), - uid, g_strerror (errno)); - g_free (*path); - return NULL; - } - - return camel_stream_fs_new_with_fd (fd); -} - -static CamelStream * -insert_abort (char *path, CamelStream *stream) -{ - unlink (path); - g_free (path); - camel_object_unref (CAMEL_OBJECT (stream)); - return NULL; -} - -static CamelStream * -insert_finish (CamelImapMessageCache *cache, const char *uid, char *path, - char *key, CamelStream *stream) -{ - camel_stream_flush (stream); - camel_stream_reset (stream); - cache_put (cache, uid, key, stream); - g_free (path); - - return stream; -} - -/** - * camel_imap_message_cache_insert: - * @cache: the cache - * @uid: UID of the message data to cache - * @part_spec: the IMAP part_spec of the data - * @data: the data - * @len: length of @data - * - * Caches the provided data into @cache. - * - * Return value: a CamelStream containing the cached data, which the - * caller must unref. - **/ -CamelStream * -camel_imap_message_cache_insert (CamelImapMessageCache *cache, const char *uid, - const char *part_spec, const char *data, - int len, CamelException *ex) -{ - char *path, *key; - CamelStream *stream; - - stream = insert_setup (cache, uid, part_spec, &path, &key, ex); - if (!stream) - return NULL; - - if (camel_stream_write (stream, data, len) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to cache message %s: %s"), - uid, g_strerror (errno)); - return insert_abort (path, stream); - } - - return insert_finish (cache, uid, path, key, stream); -} - -/** - * camel_imap_message_cache_insert_stream: - * @cache: the cache - * @uid: UID of the message data to cache - * @part_spec: the IMAP part_spec of the data - * @data_stream: the stream to cache - * - * Caches the provided data into @cache. - **/ -void -camel_imap_message_cache_insert_stream (CamelImapMessageCache *cache, - const char *uid, const char *part_spec, - CamelStream *data_stream, CamelException *ex) -{ - char *path, *key; - CamelStream *stream; - - stream = insert_setup (cache, uid, part_spec, &path, &key, ex); - if (!stream) - return; - - if (camel_stream_write_to_stream (data_stream, stream) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to cache message %s: %s"), - uid, g_strerror (errno)); - insert_abort (path, stream); - } else { - insert_finish (cache, uid, path, key, stream); - camel_object_unref (CAMEL_OBJECT (stream)); - } -} - -/** - * camel_imap_message_cache_insert_wrapper: - * @cache: the cache - * @uid: UID of the message data to cache - * @part_spec: the IMAP part_spec of the data - * @wrapper: the wrapper to cache - * - * Caches the provided data into @cache. - **/ -void -camel_imap_message_cache_insert_wrapper (CamelImapMessageCache *cache, - const char *uid, const char *part_spec, - CamelDataWrapper *wrapper, CamelException *ex) -{ - char *path, *key; - CamelStream *stream; - - stream = insert_setup (cache, uid, part_spec, &path, &key, ex); - if (!stream) - return; - - if (camel_data_wrapper_write_to_stream (wrapper, stream) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to cache message %s: %s"), - uid, g_strerror (errno)); - insert_abort (path, stream); - } else { - insert_finish (cache, uid, path, key, stream); - camel_object_unref (CAMEL_OBJECT (stream)); - } -} - - -/** - * camel_imap_message_cache_get: - * @cache: the cache - * @uid: the UID of the data to get - * @part_spec: the part_spec of the data to get - * @ex: exception - * - * Return value: a CamelStream containing the cached data (which the - * caller must unref), or %NULL if that data is not cached. - **/ -CamelStream * -camel_imap_message_cache_get (CamelImapMessageCache *cache, const char *uid, - const char *part_spec, CamelException *ex) -{ - CamelStream *stream; - char *path, *key; - - if (uid[0] == 0) - return NULL; - - path = g_strdup_printf ("%s/%s.%s", cache->path, uid, part_spec); - key = strrchr (path, '/') + 1; - stream = g_hash_table_lookup (cache->parts, key); - if (stream) { - camel_stream_reset (CAMEL_STREAM (stream)); - camel_object_ref (CAMEL_OBJECT (stream)); - g_free (path); - return stream; - } - - stream = camel_stream_fs_new_with_name (path, O_RDONLY, 0); - if (stream) { - cache_put (cache, uid, key, stream); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to cache %s: %s"), - part_spec, g_strerror (errno)); - } - - g_free (path); - - return stream; -} - -/** - * camel_imap_message_cache_remove: - * @cache: the cache - * @uid: UID of the data to remove - * - * Removes all data associated with @uid from @cache. - **/ -void -camel_imap_message_cache_remove (CamelImapMessageCache *cache, const char *uid) -{ - GPtrArray *subparts; - char *key, *path; - CamelObject *stream; - int i; - - subparts = g_hash_table_lookup (cache->parts, uid); - if (!subparts) - return; - for (i = 0; i < subparts->len; i++) { - key = subparts->pdata[i]; - path = g_strdup_printf ("%s/%s", cache->path, key); - unlink (path); - g_free (path); - stream = g_hash_table_lookup (cache->parts, key); - if (stream) { - camel_object_unhook_event (stream, "finalize", - stream_finalize, cache); - camel_object_unref (stream); - g_hash_table_remove (cache->cached, stream); - } - g_hash_table_remove (cache->parts, key); - g_free (key); - } - g_hash_table_remove (cache->parts, uid); - g_ptr_array_free (subparts, TRUE); -} - -static void -add_uids (gpointer key, gpointer value, gpointer data) -{ - if (!strchr (key, '.')) - g_ptr_array_add (data, key); -} - -/** - * camel_imap_message_cache_clear: - * @cache: the cache - * - * Removes all cached data from @cache. - **/ -void -camel_imap_message_cache_clear (CamelImapMessageCache *cache) -{ - GPtrArray *uids; - int i; - - uids = g_ptr_array_new (); - g_hash_table_foreach (cache->parts, add_uids, uids); - - for (i = 0; i < uids->len; i++) - camel_imap_message_cache_remove (cache, uids->pdata[i]); - g_ptr_array_free (uids, TRUE); -} - - -/** - * camel_imap_message_cache_copy: - * @source: the source message cache - * @source_uid: UID of a message in @source - * @dest: the destination message cache - * @dest_uid: UID of the message in @dest - * - * Copies all cached parts from @source_uid in @source to @dest_uid in - * @destination. - **/ -void -camel_imap_message_cache_copy (CamelImapMessageCache *source, - const char *source_uid, - CamelImapMessageCache *dest, - const char *dest_uid, - CamelException *ex) -{ - GPtrArray *subparts; - CamelStream *stream; - char *part; - int i; - - subparts = g_hash_table_lookup (source->parts, source_uid); - if (!subparts || !subparts->len) - return; - - for (i = 0; i < subparts->len; i++) { - part = strchr (subparts->pdata[i], '.'); - if (!part++) - continue; - - if ((stream = camel_imap_message_cache_get (source, source_uid, part, ex))) { - camel_imap_message_cache_insert_stream (dest, dest_uid, part, stream, ex); - camel_object_unref (CAMEL_OBJECT (stream)); - } - } -} diff --git a/camel/providers/imap/camel-imap-message-cache.h b/camel/providers/imap/camel-imap-message-cache.h deleted file mode 100644 index c79195cfa4..0000000000 --- a/camel/providers/imap/camel-imap-message-cache.h +++ /dev/null @@ -1,111 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-message-cache.h: Class for an IMAP message cache */ - -/* - * Author: - * Dan Winship - * - * Copyright (C) 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAP_MESSAGE_CACHE_H -#define CAMEL_IMAP_MESSAGE_CACHE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-imap-types.h" -#include "camel-folder.h" -#include - -#define CAMEL_IMAP_MESSAGE_CACHE_TYPE (camel_imap_message_cache_get_type ()) -#define CAMEL_IMAP_MESSAGE_CACHE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAP_MESSAGE_CACHE_TYPE, CamelImapFolder)) -#define CAMEL_IMAP_MESSAGE_CACHE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAP_MESSAGE_CACHE_TYPE, CamelImapFolderClass)) -#define CAMEL_IS_IMAP_MESSAGE_CACHE(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAP_MESSAGE_CACHE_TYPE)) - -struct _CamelImapMessageCache { - CamelObject parent_object; - - char *path; - GHashTable *parts, *cached; - guint32 max_uid; -}; - - -typedef struct { - CamelFolderClass parent_class; - - /* Virtual methods */ - -} CamelImapMessageCacheClass; - - -/* public methods */ -CamelImapMessageCache *camel_imap_message_cache_new (const char *path, - CamelFolderSummary *summ, - CamelException *ex); - -void camel_imap_message_cache_set_path (CamelImapMessageCache *cache, - const char *path); - -guint32 camel_imap_message_cache_max_uid (CamelImapMessageCache *cache); - -CamelStream *camel_imap_message_cache_insert (CamelImapMessageCache *cache, - const char *uid, - const char *part_spec, - const char *data, - int len, - CamelException *ex); -void camel_imap_message_cache_insert_stream (CamelImapMessageCache *cache, - const char *uid, - const char *part_spec, - CamelStream *data_stream, - CamelException *ex); -void camel_imap_message_cache_insert_wrapper (CamelImapMessageCache *cache, - const char *uid, - const char *part_spec, - CamelDataWrapper *wrapper, - CamelException *ex); - -CamelStream *camel_imap_message_cache_get (CamelImapMessageCache *cache, - const char *uid, - const char *part_spec, - CamelException *ex); - -void camel_imap_message_cache_remove (CamelImapMessageCache *cache, - const char *uid); - -void camel_imap_message_cache_clear (CamelImapMessageCache *cache); - -void camel_imap_message_cache_copy (CamelImapMessageCache *source, - const char *source_uid, - CamelImapMessageCache *dest, - const char *dest_uid, - CamelException *ex); - -/* Standard Camel function */ -CamelType camel_imap_message_cache_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_IMAP_MESSAGE_CACHE_H */ diff --git a/camel/providers/imap/camel-imap-private.h b/camel/providers/imap/camel-imap-private.h deleted file mode 100644 index 0f80dbfd1c..0000000000 --- a/camel/providers/imap/camel-imap-private.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * camel-imap-private.h: Private info for imap. - * - * Authors: Michael Zucchi - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_IMAP_PRIVATE_H -#define CAMEL_IMAP_PRIVATE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* need a way to configure and save this data, if this header is to - be installed. For now, dont install it */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef ENABLE_THREADS -#include "e-util/e-msgport.h" -#endif - -struct _CamelImapFolderPrivate { -#ifdef ENABLE_THREADS - EMutex *search_lock; /* for locking the search object */ - EMutex *cache_lock; /* for locking the cache object */ -#endif -}; - -#ifdef ENABLE_THREADS -#define CAMEL_IMAP_FOLDER_LOCK(f, l) (e_mutex_lock(((CamelImapFolder *)f)->priv->l)) -#define CAMEL_IMAP_FOLDER_UNLOCK(f, l) (e_mutex_unlock(((CamelImapFolder *)f)->priv->l)) -#else -#define CAMEL_IMAP_FOLDER_LOCK(f, l) -#define CAMEL_IMAP_FOLDER_UNLOCK(f, l) -#endif - -struct _CamelImapWrapperPrivate { -#ifdef ENABLE_THREADS - GMutex *lock; -#endif -}; - -#ifdef ENABLE_THREADS -#define CAMEL_IMAP_WRAPPER_LOCK(f, l) (g_mutex_lock(((CamelImapWrapper *)f)->priv->l)) -#define CAMEL_IMAP_WRAPPER_UNLOCK(f, l) (g_mutex_unlock(((CamelImapWrapper *)f)->priv->l)) -#else -#define CAMEL_IMAP_WRAPPER_LOCK(f, l) -#define CAMEL_IMAP_WRAPPER_UNLOCK(f, l) -#endif - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_IMAP_PRIVATE_H */ - diff --git a/camel/providers/imap/camel-imap-provider.c b/camel/providers/imap/camel-imap-provider.c deleted file mode 100644 index abda8f89a0..0000000000 --- a/camel/providers/imap/camel-imap-provider.c +++ /dev/null @@ -1,158 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-provider.c: imap provider registration code */ - -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "camel-imap-store.h" -#include "camel-provider.h" -#include "camel-session.h" -#include "camel-url.h" -#include "camel-sasl.h" - -static void add_hash (guint *hash, char *s); -static guint imap_url_hash (gconstpointer key); -static gint check_equal (char *s1, char *s2); -static gint imap_url_equal (gconstpointer a, gconstpointer b); - -CamelProviderConfEntry imap_conf_entries[] = { - { CAMEL_PROVIDER_CONF_SECTION_START, "cmdsection", NULL, - N_("Connection to Server") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "use_command", NULL, - N_("Use custom command to connect to server"), "0" }, - { CAMEL_PROVIDER_CONF_ENTRY, "command", "use_command", - N_("Command:"), "ssh -C -l %u %h exec /usr/sbin/imapd" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_SECTION_START, "mailcheck", NULL, - N_("Checking for new mail") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "check_all", NULL, - N_("Check for new messages in all folders"), "1" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_SECTION_START, "folders", NULL, - N_("Folders") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "use_lsub", NULL, - N_("Show only subscribed folders"), "1" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "override_namespace", NULL, - N_("Override server-supplied folder namespace"), "0" }, - { CAMEL_PROVIDER_CONF_ENTRY, "namespace", "override_namespace", - N_("Namespace") }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter", NULL, - N_("Apply filters to new messages in INBOX on this server"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "offline_sync", NULL, - N_("Automatically synchronize remote mail locally"), "0" }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider imap_provider = { - "imap", - N_("IMAP"), - - N_("For reading and storing mail on IMAP servers."), - - "mail", - - CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE | - CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL, - - CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH, - - imap_conf_entries, - - /* ... */ -}; - -CamelServiceAuthType camel_imap_password_authtype = { - N_("Password"), - - N_("This option will connect to the IMAP server using a " - "plaintext password."), - - "", - TRUE -}; - -void -camel_provider_module_init (CamelSession *session) -{ - imap_provider.object_types[CAMEL_PROVIDER_STORE] = - camel_imap_store_get_type (); - imap_provider.url_hash = imap_url_hash; - imap_provider.url_equal = imap_url_equal; - imap_provider.authtypes = camel_sasl_authtype_list (FALSE); - imap_provider.authtypes = g_list_prepend (imap_provider.authtypes, - &camel_imap_password_authtype); - - camel_session_register_provider (session, &imap_provider); -} - -static void -add_hash (guint *hash, char *s) -{ - if (s) - *hash ^= g_str_hash(s); -} - -static guint -imap_url_hash (gconstpointer key) -{ - const CamelURL *u = (CamelURL *)key; - guint hash = 0; - - add_hash (&hash, u->user); - add_hash (&hash, u->authmech); - add_hash (&hash, u->host); - hash ^= u->port; - - return hash; -} - -static gint -check_equal (char *s1, char *s2) -{ - if (s1 == NULL) { - if (s2 == NULL) - return TRUE; - else - return FALSE; - } - - if (s2 == NULL) - return FALSE; - - return strcmp (s1, s2) == 0; -} - -static gint -imap_url_equal (gconstpointer a, gconstpointer b) -{ - const CamelURL *u1 = a, *u2 = b; - - return check_equal (u1->user, u2->user) - && check_equal (u1->authmech, u2->authmech) - && check_equal (u1->host, u2->host) - && u1->port == u2->port; -} diff --git a/camel/providers/imap/camel-imap-search.c b/camel/providers/imap/camel-imap-search.c deleted file mode 100644 index eacb839cb2..0000000000 --- a/camel/providers/imap/camel-imap-search.c +++ /dev/null @@ -1,499 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-search.c: IMAP folder search */ - -/* - * Authors: - * Dan Winship - * Michael Zucchi - * - * Copyright 2000, 2001, 2002 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "camel-imap-command.h" -#include "camel-imap-folder.h" -#include "camel-imap-store.h" -#include "camel-imap-search.h" -#include "camel-imap-private.h" -#include "camel-imap-utils.h" -#include "camel-imap-summary.h" - -#include "e-util/md5-utils.h" /* md5 hash building */ -#include "camel-mime-utils.h" /* base64 encoding */ - -#include "camel-seekable-stream.h" -#include "camel-search-private.h" - -#define d(x) - -/* - File is: - BODY (as in body search) - Last uid when search performed - termcount: number of search terms - matchcount: number of matches - term0, term1 ... - match0, match1, match2, ... -*/ - -/* size of in-memory cache */ -#define MATCH_CACHE_SIZE (32) - -/* Also takes care of 'endianness' file magic */ -#define MATCH_MARK (('B' << 24) | ('O' << 16) | ('D' << 8) | 'Y') - -/* on-disk header, in native endianness format, matches follow */ -struct _match_header { - guint32 mark; - guint32 validity; /* uidvalidity for this folder */ - guint32 lastuid; - guint32 termcount; - guint32 matchcount; -}; - -/* in-memory record */ -struct _match_record { - struct _match_record *next; - struct _match_record *prev; - - char hash[17]; - - guint32 lastuid; - guint32 validity; - - unsigned int termcount; - char **terms; - GArray *matches; -}; - - -static void free_match(CamelImapSearch *is, struct _match_record *mr); -static ESExpResult *imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s); - -static CamelFolderSearchClass *imap_search_parent_class; - -static void -camel_imap_search_class_init (CamelImapSearchClass *camel_imap_search_class) -{ - /* virtual method overload */ - CamelFolderSearchClass *camel_folder_search_class = - CAMEL_FOLDER_SEARCH_CLASS (camel_imap_search_class); - - imap_search_parent_class = (CamelFolderSearchClass *)camel_type_get_global_classfuncs (camel_folder_search_get_type ()); - - /* virtual method overload */ - camel_folder_search_class->body_contains = imap_body_contains; -} - -static void -camel_imap_search_init(CamelImapSearch *is) -{ - e_dlist_init(&is->matches); - is->matches_hash = g_hash_table_new(g_str_hash, g_str_equal); - is->matches_count = 0; - is->lastuid = 0; -} - -static void -camel_imap_search_finalise(CamelImapSearch *is) -{ - struct _match_record *mr; - - while ( (mr = (struct _match_record *)e_dlist_remtail(&is->matches)) ) - free_match(is, mr); - g_hash_table_destroy(is->matches_hash); - if (is->cache) - camel_object_unref((CamelObject *)is->cache); -} - -CamelType -camel_imap_search_get_type (void) -{ - static CamelType camel_imap_search_type = CAMEL_INVALID_TYPE; - - if (camel_imap_search_type == CAMEL_INVALID_TYPE) { - camel_imap_search_type = camel_type_register ( - CAMEL_FOLDER_SEARCH_TYPE, "CamelImapSearch", - sizeof (CamelImapSearch), - sizeof (CamelImapSearchClass), - (CamelObjectClassInitFunc) camel_imap_search_class_init, NULL, - (CamelObjectInitFunc) camel_imap_search_init, - (CamelObjectFinalizeFunc) camel_imap_search_finalise); - } - - return camel_imap_search_type; -} - -/** - * camel_imap_search_new: - * - * Return value: A new CamelImapSearch widget. - **/ -CamelFolderSearch * -camel_imap_search_new (const char *cachedir) -{ - CamelFolderSearch *new = CAMEL_FOLDER_SEARCH (camel_object_new (camel_imap_search_get_type ())); - CamelImapSearch *is = (CamelImapSearch *)new; - - camel_folder_search_construct (new); - - is->cache = camel_data_cache_new(cachedir, 0, NULL); - if (is->cache) { - /* Expire entries after 14 days of inactivity */ - camel_data_cache_set_expire_access(is->cache, 60*60*24*14); - } - - return new; -} - - -static void -hash_match(char hash[17], int argc, struct _ESExpResult **argv) -{ - MD5Context ctx; - unsigned char digest[16]; - unsigned int state = 0, save = 0; - int i; - - md5_init(&ctx); - for (i=0;itype == ESEXP_RES_STRING) - md5_update(&ctx, argv[i]->value.string, strlen(argv[i]->value.string)); - } - md5_final(&ctx, digest); - - camel_base64_encode_close(digest, 12, FALSE, hash, &state, &save); - - for (i=0;i<16;i++) { - if (hash[i] == '+') - hash[i] = ','; - if (hash[i] == '/') - hash[i] = '_'; - } - - hash[16] = 0; -} - -static int -save_match(CamelImapSearch *is, struct _match_record *mr) -{ - guint32 mark = MATCH_MARK; - int ret = 0; - struct _match_header header; - CamelStream *stream; - - /* since its a cache, doesn't matter if it doesn't save, at least we have the in-memory cache - for this session */ - if (is->cache == NULL) - return -1; - - stream = camel_data_cache_add(is->cache, "search/body-contains", mr->hash, NULL); - if (stream == NULL) - return -1; - - d(printf("Saving search cache entry to '%s': %s\n", mr->hash, mr->terms[0])); - - /* we write the whole thing, then re-write the header magic, saves fancy sync code */ - memcpy(&header.mark, " ", 4); - header.termcount = 0; - header.matchcount = mr->matches->len; - header.lastuid = mr->lastuid; - header.validity = mr->validity; - - if (camel_stream_write(stream, (char *)&header, sizeof(header)) != sizeof(header) - || camel_stream_write(stream, mr->matches->data, mr->matches->len*sizeof(guint32)) != mr->matches->len*sizeof(guint32) - || camel_seekable_stream_seek((CamelSeekableStream *)stream, 0, CAMEL_STREAM_SET) == -1 - || camel_stream_write(stream, (char *)&mark, sizeof(mark)) != sizeof(mark)) { - d(printf(" saving failed, removing cache entry\n")); - camel_data_cache_remove(is->cache, "search/body-contains", mr->hash, NULL); - ret = -1; - } - - camel_object_unref((CamelObject *)stream); - return ret; -} - -static void -free_match(CamelImapSearch *is, struct _match_record *mr) -{ - int i; - - for (i=0;itermcount;i++) - g_free(mr->terms[i]); - g_free(mr->terms); - g_array_free(mr->matches, TRUE); - g_free(mr); -} - -static struct _match_record * -load_match(CamelImapSearch *is, char hash[17], int argc, struct _ESExpResult **argv) -{ - struct _match_record *mr; - CamelStream *stream = NULL; - struct _match_header header; - int i; - - mr = g_malloc0(sizeof(*mr)); - mr->matches = g_array_new(0, 0, sizeof(guint32)); - g_assert(strlen(hash) == 16); - strcpy(mr->hash, hash); - mr->terms = g_malloc0(sizeof(mr->terms[0]) * argc); - for (i=0;itype == ESEXP_RES_STRING) { - mr->termcount++; - mr->terms[i] = g_strdup(argv[i]->value.string); - } - } - - d(printf("Loading search cache entry to '%s': %s\n", mr->hash, mr->terms[0])); - - memset(&header, 0, sizeof(header)); - if (is->cache) - stream = camel_data_cache_get(is->cache, "search/body-contains", mr->hash, NULL); - if (stream != NULL) { - /* 'cause i'm gonna be lazy, i'm going to have the termcount == 0 for now, - and not load or save them since i can't think of a nice way to do it, the hash - should be sufficient to key it */ - /* This check should also handle endianness changes, we just throw away - the data (its only a cache) */ - if (camel_stream_read(stream, (char *)&header, sizeof(header)) == sizeof(header) - && header.validity == is->validity - && header.mark == MATCH_MARK - && header.termcount == 0) { - d(printf(" found %d matches\n", header.matchcount)); - g_array_set_size(mr->matches, header.matchcount); - camel_stream_read(stream, mr->matches->data, sizeof(guint32)*header.matchcount); - } else { - d(printf(" file format invalid/validity changed\n")); - memset(&header, 0, sizeof(header)); - } - camel_object_unref((CamelObject *)stream); - } else { - d(printf(" no cache entry found\n")); - } - - mr->validity = header.validity; - if (mr->validity != is->validity) - mr->lastuid = 0; - else - mr->lastuid = header.lastuid; - - return mr; -} - -static int -sync_match(CamelImapSearch *is, struct _match_record *mr) -{ - char *p, *result, *lasts = NULL; - CamelImapResponse *response = NULL; - guint32 uid; - CamelFolder *folder = ((CamelFolderSearch *)is)->folder; - CamelImapStore *store = (CamelImapStore *)folder->parent_store; - struct _camel_search_words *words; - GString *search; - int i; - - if (mr->lastuid >= is->lastuid && mr->validity == is->validity) - return 0; - - d(printf ("updating match record for uid's %d:%d\n", mr->lastuid+1, is->lastuid)); - - /* TODO: Handle multiple search terms */ - - /* This handles multiple search words within a single term */ - words = camel_search_words_split (mr->terms[0]); - search = g_string_new (""); - g_string_append_printf (search, "UID %d:%d", mr->lastuid + 1, is->lastuid); - for (i = 0; i < words->len; i++) { - char *w = words->words[i]->word, c; - - g_string_append_printf (search, " BODY \""); - while ((c = *w++)) { - if (c == '\\' || c == '"') - g_string_append_c (search, '\\'); - g_string_append_c (search, c); - } - g_string_append_c (search, '"'); - } - camel_search_words_free (words); - - /* We only try search using utf8 if its non us-ascii text? */ - if ((words->type & CAMEL_SEARCH_WORD_8BIT) && (store->capabilities & IMAP_CAPABILITY_utf8_search)) { - response = camel_imap_command (store, folder, NULL, - "UID SEARCH CHARSET UTF-8 %s", search->str); - /* We can't actually tell if we got a NO response, so assume always */ - if (response == NULL) - store->capabilities &= ~IMAP_CAPABILITY_utf8_search; - } - if (response == NULL) - response = camel_imap_command (store, folder, NULL, - "UID SEARCH %s", search->str); - g_string_free(search, TRUE); - - if (!response) - return -1; - result = camel_imap_response_extract (store, response, "SEARCH", NULL); - if (!result) - return -1; - - p = result + sizeof ("* SEARCH"); - for (p = strtok_r (p, " ", &lasts); p; p = strtok_r (NULL, " ", &lasts)) { - uid = strtoul(p, NULL, 10); - g_array_append_vals(mr->matches, &uid, 1); - } - g_free(result); - - mr->validity = is->validity; - mr->lastuid = is->lastuid; - save_match(is, mr); - - return 0; -} - -static struct _match_record * -get_match(CamelImapSearch *is, int argc, struct _ESExpResult **argv) -{ - char hash[17]; - struct _match_record *mr; - - hash_match(hash, argc, argv); - - mr = g_hash_table_lookup(is->matches_hash, hash); - if (mr == NULL) { - while (is->matches_count >= MATCH_CACHE_SIZE) { - mr = (struct _match_record *)e_dlist_remtail(&is->matches); - if (mr) { - printf("expiring match '%s' (%s)\n", mr->hash, mr->terms[0]); - g_hash_table_remove(is->matches_hash, mr->hash); - free_match(is, mr); - is->matches_count--; - } else { - is->matches_count = 0; - } - } - mr = load_match(is, hash, argc, argv); - g_hash_table_insert(is->matches_hash, mr->hash, mr); - is->matches_count++; - } else { - e_dlist_remove((EDListNode *)mr); - } - - e_dlist_addhead(&is->matches, (EDListNode *)mr); - - /* what about offline mode? */ - /* We could cache those results too, or should we cache them elsewhere? */ - sync_match(is, mr); - - return mr; -} - -static ESExpResult * -imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (s->folder->parent_store); - CamelImapSearch *is = (CamelImapSearch *)s; - char *uid; - ESExpResult *r; - CamelMessageInfo *info; - GHashTable *uid_hash = NULL; - GPtrArray *array; - int i, j; - struct _match_record *mr; - guint32 uidn, *uidp; - - d(printf("Performing body search '%s'\n", argv[0]->value.string)); - - /* TODO: Cache offline searches too? */ - - /* If offline, search using the parent class, which can handle this manually */ - if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), NULL)) - return imap_search_parent_class->body_contains(f, argc, argv, s); - - /* optimise the match "" case - match everything */ - if (argc == 1 && argv[0]->value.string[0] == '\0') { - if (s->current) { - r = e_sexp_result_new(f, ESEXP_RES_BOOL); - r->value.bool = TRUE; - } else { - r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR); - r->value.ptrarray = g_ptr_array_new (); - for (i = 0; i < s->summary->len; i++) { - info = g_ptr_array_index(s->summary, i); - g_ptr_array_add(r->value.ptrarray, (char *)camel_message_info_uid(info)); - } - } - } else if (argc == 0 || s->summary->len == 0) { - /* nothing to match case, do nothing (should be handled higher up?) */ - if (s->current) { - r = e_sexp_result_new(f, ESEXP_RES_BOOL); - r->value.bool = FALSE; - } else { - r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR); - r->value.ptrarray = g_ptr_array_new (); - } - } else { - int truth = FALSE; - - /* setup lastuid/validity for synchronising */ - info = g_ptr_array_index(s->summary, s->summary->len-1); - is->lastuid = strtoul(camel_message_info_uid(info), NULL, 10); - is->validity = ((CamelImapSummary *)(s->folder->summary))->validity; - - mr = get_match(is, argc, argv); - - if (s->current) { - uidn = strtoul(camel_message_info_uid(s->current), NULL, 10); - uidp = (guint32 *)mr->matches->data; - j = mr->matches->len; - for (i=0;ivalue.bool = truth; - } else { - r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR); - array = r->value.ptrarray = g_ptr_array_new(); - - /* We use a hash to map the uid numbers to uid strings as required by the search api */ - /* We use the summary's strings so we dont need to alloc more */ - uid_hash = g_hash_table_new(NULL, NULL); - for (i = 0; i < s->summary->len; i++) { - info = s->summary->pdata[i]; - uid = (char *)camel_message_info_uid(info); - uidn = strtoul(uid, NULL, 10); - g_hash_table_insert(uid_hash, GUINT_TO_POINTER(uidn), uid); - } - - uidp = (guint32 *)mr->matches->data; - j = mr->matches->len; - for (i=0;i - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef _CAMEL_IMAP_SEARCH_H -#define _CAMEL_IMAP_SEARCH_H - -#include -#include -#include - -#define CAMEL_IMAP_SEARCH_TYPE (camel_imap_search_get_type ()) -#define CAMEL_IMAP_SEARCH(obj) CAMEL_CHECK_CAST (obj, camel_imap_search_get_type (), CamelImapSearch) -#define CAMEL_IMAP_SEARCH_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imap_search_get_type (), CamelImapSearchClass) -#define CAMEL_IS_IMAP_SEARCH(obj) CAMEL_CHECK_TYPE (obj, camel_imap_search_get_type ()) - -typedef struct _CamelImapSearchClass CamelImapSearchClass; - -struct _CamelImapSearch { - CamelFolderSearch parent; - - guint32 lastuid; /* current 'last uid' for the folder */ - guint32 validity; /* validity of the current folder */ - - CamelDataCache *cache; /* disk-cache for searches */ - - /* cache of body search matches */ - unsigned int matches_count; - EDList matches; - GHashTable *matches_hash; -}; - -struct _CamelImapSearchClass { - CamelFolderSearchClass parent_class; - -}; - -CamelType camel_imap_search_get_type (void); -CamelFolderSearch *camel_imap_search_new (const char *cachedir); - -#endif /* ! _CAMEL_IMAP_SEARCH_H */ diff --git a/camel/providers/imap/camel-imap-store-summary.c b/camel/providers/imap/camel-imap-store-summary.c deleted file mode 100644 index 32530d3c3f..0000000000 --- a/camel/providers/imap/camel-imap-store-summary.c +++ /dev/null @@ -1,619 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2002 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "camel-imap-store-summary.h" - -#include "camel-file-utils.h" - -#include "e-util/md5-utils.h" -#include "e-util/e-memory.h" - -#include "camel-private.h" -#include "camel-utf8.h" - -#define d(x) -#define io(x) /* io debug */ - -#define CAMEL_IMAP_STORE_SUMMARY_VERSION_0 (0) - -#define CAMEL_IMAP_STORE_SUMMARY_VERSION (0) - -#define _PRIVATE(o) (((CamelImapStoreSummary *)(o))->priv) - -static int summary_header_load(CamelStoreSummary *, FILE *); -static int summary_header_save(CamelStoreSummary *, FILE *); - -/*static CamelStoreInfo * store_info_new(CamelStoreSummary *, const char *);*/ -static CamelStoreInfo * store_info_load(CamelStoreSummary *, FILE *); -static int store_info_save(CamelStoreSummary *, FILE *, CamelStoreInfo *); -static void store_info_free(CamelStoreSummary *, CamelStoreInfo *); - -static const char *store_info_string(CamelStoreSummary *, const CamelStoreInfo *, int); -static void store_info_set_string(CamelStoreSummary *, CamelStoreInfo *, int, const char *); - -static void camel_imap_store_summary_class_init (CamelImapStoreSummaryClass *klass); -static void camel_imap_store_summary_init (CamelImapStoreSummary *obj); -static void camel_imap_store_summary_finalise (CamelObject *obj); - -static CamelStoreSummaryClass *camel_imap_store_summary_parent; - -static void -camel_imap_store_summary_class_init (CamelImapStoreSummaryClass *klass) -{ - CamelStoreSummaryClass *ssklass = (CamelStoreSummaryClass *)klass; - - ssklass->summary_header_load = summary_header_load; - ssklass->summary_header_save = summary_header_save; - - /*ssklass->store_info_new = store_info_new;*/ - ssklass->store_info_load = store_info_load; - ssklass->store_info_save = store_info_save; - ssklass->store_info_free = store_info_free; - - ssklass->store_info_string = store_info_string; - ssklass->store_info_set_string = store_info_set_string; -} - -static void -camel_imap_store_summary_init (CamelImapStoreSummary *s) -{ - /*struct _CamelImapStoreSummaryPrivate *p; - - p = _PRIVATE(s) = g_malloc0(sizeof(*p));*/ - - ((CamelStoreSummary *)s)->store_info_size = sizeof(CamelImapStoreInfo); - s->version = CAMEL_IMAP_STORE_SUMMARY_VERSION; -} - -static void -camel_imap_store_summary_finalise (CamelObject *obj) -{ - /*struct _CamelImapStoreSummaryPrivate *p;*/ - /*CamelImapStoreSummary *s = (CamelImapStoreSummary *)obj;*/ - - /*p = _PRIVATE(obj); - g_free(p);*/ -} - -CamelType -camel_imap_store_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - camel_imap_store_summary_parent = (CamelStoreSummaryClass *)camel_store_summary_get_type(); - type = camel_type_register((CamelType)camel_imap_store_summary_parent, "CamelImapStoreSummary", - sizeof (CamelImapStoreSummary), - sizeof (CamelImapStoreSummaryClass), - (CamelObjectClassInitFunc) camel_imap_store_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_imap_store_summary_init, - (CamelObjectFinalizeFunc) camel_imap_store_summary_finalise); - } - - return type; -} - -/** - * camel_imap_store_summary_new: - * - * Create a new CamelImapStoreSummary object. - * - * Return value: A new CamelImapStoreSummary widget. - **/ -CamelImapStoreSummary * -camel_imap_store_summary_new (void) -{ - CamelImapStoreSummary *new = CAMEL_IMAP_STORE_SUMMARY ( camel_object_new (camel_imap_store_summary_get_type ())); - - return new; -} - -/** - * camel_imap_store_summary_full_name: - * @s: - * @path: - * - * Retrieve a summary item by full name. - * - * A referenced to the summary item is returned, which may be - * ref'd or free'd as appropriate. - * - * Return value: The summary item, or NULL if the @full_name name - * is not available. - * It must be freed using camel_store_summary_info_free(). - **/ -CamelImapStoreInfo * -camel_imap_store_summary_full_name(CamelImapStoreSummary *s, const char *full_name) -{ - int count, i; - CamelImapStoreInfo *info; - - count = camel_store_summary_count((CamelStoreSummary *)s); - for (i=0;ifull_name, full_name) == 0) - return info; - camel_store_summary_info_free((CamelStoreSummary *)s, (CamelStoreInfo *)info); - } - } - - return NULL; -} - -char * -camel_imap_store_summary_full_to_path(CamelImapStoreSummary *s, const char *full_name, char dir_sep) -{ - char *path, *p; - int c; - const char *f; - - if (dir_sep != '/') { - p = path = alloca(strlen(full_name)*3+1); - f = full_name; - while ( (c = *f++ & 0xff) ) { - if (c == dir_sep) - *p++ = '/'; - else if (c == '/' || c == '%') - p += sprintf(p, "%%%02X", c); - else - *p++ = c; - } - *p = 0; - } else - path = (char *)full_name; - - return camel_utf7_utf8(path); -} - -static guint32 hexnib(guint32 c) -{ - if (c >= '0' && c <= '9') - return c-'0'; - else if (c>='A' && c <= 'Z') - return c-'A'+10; - else - return 0; -} - -char * -camel_imap_store_summary_path_to_full(CamelImapStoreSummary *s, const char *path, char dir_sep) -{ - unsigned char *full, *f; - guint32 c, v = 0; - const char *p; - int state=0; - char *subpath, *last = NULL; - CamelStoreInfo *si; - CamelImapStoreNamespace *ns; - - /* check to see if we have a subpath of path already defined */ - subpath = alloca(strlen(path)+1); - strcpy(subpath, path); - do { - si = camel_store_summary_path((CamelStoreSummary *)s, subpath); - if (si == NULL) { - last = strrchr(subpath, '/'); - if (last) - *last = 0; - } - } while (si == NULL && last); - - /* path is already present, use the raw version we have */ - if (si && strlen(subpath) == strlen(path)) { - f = g_strdup(camel_imap_store_info_full_name(s, si)); - camel_store_summary_info_free((CamelStoreSummary *)s, si); - return f; - } - - ns = camel_imap_store_summary_namespace_find_path(s, path); - - f = full = alloca(strlen(path)*2+1); - if (si) - p = path + strlen(subpath); - else if (ns) - p = path + strlen(ns->path); - else - p = path; - - while ( (c = camel_utf8_getc((const unsigned char **)&p)) ) { - switch(state) { - case 0: - if (c == '%') - state = 1; - else { - if (c == '/') - c = dir_sep; - camel_utf8_putc(&f, c); - } - break; - case 1: - state = 2; - v = hexnib(c)<<4; - break; - case 2: - state = 0; - v |= hexnib(c); - camel_utf8_putc(&f, v); - break; - } - } - camel_utf8_putc(&f, c); - - /* merge old path part if required */ - f = camel_utf8_utf7(full); - if (si) { - full = g_strdup_printf("%s%s", camel_imap_store_info_full_name(s, si), f); - g_free(f); - camel_store_summary_info_free((CamelStoreSummary *)s, si); - f = full; - } else if (ns) { - full = g_strdup_printf("%s%s", ns->full_name, f); - g_free(f); - f = full; - } - - return f; -} - -CamelImapStoreInfo * -camel_imap_store_summary_add_from_full(CamelImapStoreSummary *s, const char *full, char dir_sep) -{ - CamelImapStoreInfo *info; - char *pathu8, *prefix; - int len; - char *full_name; - CamelImapStoreNamespace *ns; - - d(printf("adding full name '%s' '%c'\n", full, dir_sep)); - - len = strlen(full); - full_name = alloca(len+1); - strcpy(full_name, full); - if (full_name[len-1] == dir_sep) - full_name[len-1] = 0; - - info = camel_imap_store_summary_full_name(s, full_name); - if (info) { - camel_store_summary_info_free((CamelStoreSummary *)s, (CamelStoreInfo *)info); - d(printf(" already there\n")); - return info; - } - - ns = camel_imap_store_summary_namespace_find_full(s, full_name); - if (ns) { - d(printf("(found namespace for '%s' ns '%s') ", full_name, ns->path)); - len = strlen(ns->full_name); - if (len >= strlen(full_name)) { - pathu8 = g_strdup(ns->path); - } else { - if (full_name[len] == ns->sep) - len++; - - prefix = camel_imap_store_summary_full_to_path(s, full_name+len, ns->sep); - if (*ns->path) { - pathu8 = g_strdup_printf ("%s/%s", ns->path, prefix); - g_free (prefix); - } else { - pathu8 = prefix; - } - } - d(printf(" (pathu8 = '%s')", pathu8)); - } else { - d(printf("(Cannot find namespace for '%s')\n", full_name)); - pathu8 = camel_imap_store_summary_full_to_path(s, full_name, dir_sep); - } - - info = (CamelImapStoreInfo *)camel_store_summary_add_from_path((CamelStoreSummary *)s, pathu8); - if (info) { - d(printf(" '%s' -> '%s'\n", pathu8, full_name)); - camel_store_info_set_string((CamelStoreSummary *)s, (CamelStoreInfo *)info, CAMEL_IMAP_STORE_INFO_FULL_NAME, full_name); - } else - d(printf(" failed\n")); - - return info; -} - -/* should this be const? */ -/* TODO: deprecate/merge this function with path_to_full */ -char * -camel_imap_store_summary_full_from_path(CamelImapStoreSummary *s, const char *path) -{ - CamelImapStoreNamespace *ns; - char *name = NULL; - - ns = camel_imap_store_summary_namespace_find_path(s, path); - if (ns) - name = camel_imap_store_summary_path_to_full(s, path, ns->sep); - - d(printf("looking up path %s -> %s\n", path, name?name:"not found")); - - return name; -} - -/* TODO: this api needs some more work */ -CamelImapStoreNamespace *camel_imap_store_summary_namespace_new(CamelImapStoreSummary *s, const char *full_name, char dir_sep) -{ - CamelImapStoreNamespace *ns; - char *p, *o, c; - int len; - - ns = g_malloc0(sizeof(*ns)); - ns->full_name = g_strdup(full_name); - len = strlen(ns->full_name)-1; - if (len >= 0 && ns->full_name[len] == dir_sep) - ns->full_name[len] = 0; - ns->sep = dir_sep; - - o = p = ns->path = camel_imap_store_summary_full_to_path(s, ns->full_name, dir_sep); - while ((c = *p++)) { - if (c != '#') { - if (c == '/') - c = '.'; - *o++ = c; - } - } - *o = 0; - - return ns; -} - -void camel_imap_store_summary_namespace_set(CamelImapStoreSummary *s, CamelImapStoreNamespace *ns) -{ - static void namespace_clear(CamelStoreSummary *s); - - d(printf("Setting namesapce to '%s' '%c' -> '%s'\n", ns->full_name, ns->sep, ns->path)); - namespace_clear((CamelStoreSummary *)s); - s->namespace = ns; - camel_store_summary_touch((CamelStoreSummary *)s); -} - -CamelImapStoreNamespace * -camel_imap_store_summary_namespace_find_path(CamelImapStoreSummary *s, const char *path) -{ - int len; - CamelImapStoreNamespace *ns; - - /* NB: this currently only compares against 1 namespace, in future compare against others */ - ns = s->namespace; - while (ns) { - len = strlen(ns->path); - if (len == 0 - || (strncmp(ns->path, path, len) == 0 - && (path[len] == '/' || path[len] == 0))) - break; - ns = NULL; - } - - /* have a default? */ - return ns; -} - -CamelImapStoreNamespace * -camel_imap_store_summary_namespace_find_full(CamelImapStoreSummary *s, const char *full) -{ - int len; - CamelImapStoreNamespace *ns; - - /* NB: this currently only compares against 1 namespace, in future compare against others */ - ns = s->namespace; - while (ns) { - len = strlen(ns->full_name); - d(printf("find_full: comparing namespace '%s' to name '%s'\n", ns->full_name, full)); - if (len == 0 - || (strncmp(ns->full_name, full, len) == 0 - && (full[len] == ns->sep || full[len] == 0))) - break; - ns = NULL; - } - - /* have a default? */ - return ns; -} - -static void -namespace_free(CamelStoreSummary *s, CamelImapStoreNamespace *ns) -{ - g_free(ns->path); - g_free(ns->full_name); - g_free(ns); -} - -static void -namespace_clear(CamelStoreSummary *s) -{ - CamelImapStoreSummary *is = (CamelImapStoreSummary *)s; - - if (is->namespace) - namespace_free(s, is->namespace); - is->namespace = NULL; -} - -static CamelImapStoreNamespace * -namespace_load(CamelStoreSummary *s, FILE *in) -{ - CamelImapStoreNamespace *ns; - guint32 sep = '/'; - - ns = g_malloc0(sizeof(*ns)); - if (camel_file_util_decode_string(in, &ns->path) == -1 - || camel_file_util_decode_string(in, &ns->full_name) == -1 - || camel_file_util_decode_uint32(in, &sep) == -1) { - namespace_free(s, ns); - ns = NULL; - } else { - ns->sep = sep; - } - - return ns; -} - -static int -namespace_save(CamelStoreSummary *s, FILE *in, CamelImapStoreNamespace *ns) -{ - if (camel_file_util_encode_string(in, ns->path) == -1 - || camel_file_util_encode_string(in, ns->full_name) == -1 - || camel_file_util_encode_uint32(in, (guint32)ns->sep) == -1) - return -1; - - return 0; -} - -static int -summary_header_load(CamelStoreSummary *s, FILE *in) -{ - CamelImapStoreSummary *is = (CamelImapStoreSummary *)s; - gint32 version, capabilities, count; - - namespace_clear(s); - - if (camel_imap_store_summary_parent->summary_header_load((CamelStoreSummary *)s, in) == -1 - || camel_file_util_decode_fixed_int32(in, &version) == -1) - return -1; - - is->version = version; - - if (version < CAMEL_IMAP_STORE_SUMMARY_VERSION_0) { - g_warning("Store summary header version too low"); - return -1; - } - - /* note file format can be expanded to contain more namespaces, but only 1 at the moment */ - if (camel_file_util_decode_fixed_int32(in, &capabilities) == -1 - || camel_file_util_decode_fixed_int32(in, &count) == -1 - || count > 1) - return -1; - - is->capabilities = capabilities; - if (count == 1) { - if ((is->namespace = namespace_load(s, in)) == NULL) - return -1; - } - - return 0; -} - -static int -summary_header_save(CamelStoreSummary *s, FILE *out) -{ - CamelImapStoreSummary *is = (CamelImapStoreSummary *)s; - guint32 count; - - count = is->namespace?1:0; - - /* always write as latest version */ - if (camel_imap_store_summary_parent->summary_header_save((CamelStoreSummary *)s, out) == -1 - || camel_file_util_encode_fixed_int32(out, CAMEL_IMAP_STORE_SUMMARY_VERSION) == -1 - || camel_file_util_encode_fixed_int32(out, is->capabilities) == -1 - || camel_file_util_encode_fixed_int32(out, count) == -1) - return -1; - - if (is->namespace && namespace_save(s, out, is->namespace) == -1) - return -1; - - return 0; -} - -static CamelStoreInfo * -store_info_load(CamelStoreSummary *s, FILE *in) -{ - CamelImapStoreInfo *mi; - - mi = (CamelImapStoreInfo *)camel_imap_store_summary_parent->store_info_load(s, in); - if (mi) { - if (camel_file_util_decode_string(in, &mi->full_name) == -1) { - camel_store_summary_info_free(s, (CamelStoreInfo *)mi); - mi = NULL; - } - } - - return (CamelStoreInfo *)mi; -} - -static int -store_info_save(CamelStoreSummary *s, FILE *out, CamelStoreInfo *mi) -{ - CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi; - - if (camel_imap_store_summary_parent->store_info_save(s, out, mi) == -1 - || camel_file_util_encode_string(out, isi->full_name) == -1) - return -1; - - return 0; -} - -static void -store_info_free(CamelStoreSummary *s, CamelStoreInfo *mi) -{ - CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi; - - g_free(isi->full_name); - camel_imap_store_summary_parent->store_info_free(s, mi); -} - -static const char * -store_info_string(CamelStoreSummary *s, const CamelStoreInfo *mi, int type) -{ - CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi; - - /* FIXME: Locks? */ - - g_assert (mi != NULL); - - switch (type) { - case CAMEL_IMAP_STORE_INFO_FULL_NAME: - return isi->full_name; - default: - return camel_imap_store_summary_parent->store_info_string(s, mi, type); - } -} - -static void -store_info_set_string(CamelStoreSummary *s, CamelStoreInfo *mi, int type, const char *str) -{ - CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi; - - g_assert(mi != NULL); - - switch(type) { - case CAMEL_IMAP_STORE_INFO_FULL_NAME: - d(printf("Set full name %s -> %s\n", isi->full_name, str)); - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - g_free(isi->full_name); - isi->full_name = g_strdup(str); - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - break; - default: - camel_imap_store_summary_parent->store_info_set_string(s, mi, type, str); - break; - } -} diff --git a/camel/providers/imap/camel-imap-store-summary.h b/camel/providers/imap/camel-imap-store-summary.h deleted file mode 100644 index 0fa6be0df3..0000000000 --- a/camel/providers/imap/camel-imap-store-summary.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2002 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_IMAP_STORE_SUMMARY_H -#define _CAMEL_IMAP_STORE_SUMMARY_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include - -#define CAMEL_IMAP_STORE_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_imap_store_summary_get_type (), CamelImapStoreSummary) -#define CAMEL_IMAP_STORE_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imap_store_summary_get_type (), CamelImapStoreSummaryClass) -#define CAMEL_IS_IMAP_STORE_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_imap_store_summary_get_type ()) - -typedef struct _CamelImapStoreSummary CamelImapStoreSummary; -typedef struct _CamelImapStoreSummaryClass CamelImapStoreSummaryClass; - -typedef struct _CamelImapStoreInfo CamelImapStoreInfo; - -enum { - CAMEL_IMAP_STORE_INFO_FULL_NAME = CAMEL_STORE_INFO_LAST, - CAMEL_IMAP_STORE_INFO_LAST, -}; - -struct _CamelImapStoreInfo { - CamelStoreInfo info; - char *full_name; -}; - -typedef struct _CamelImapStoreNamespace CamelImapStoreNamespace; - -struct _CamelImapStoreNamespace { - char *path; /* display path */ - char *full_name; /* real name */ - char sep; /* directory separator */ -}; - -struct _CamelImapStoreSummary { - CamelStoreSummary summary; - - struct _CamelImapStoreSummaryPrivate *priv; - - /* header info */ - guint32 version; /* version of base part of file */ - guint32 capabilities; - CamelImapStoreNamespace *namespace; /* eventually to be a list */ -}; - -struct _CamelImapStoreSummaryClass { - CamelStoreSummaryClass summary_class; -}; - -CamelType camel_imap_store_summary_get_type (void); -CamelImapStoreSummary *camel_imap_store_summary_new (void); - -/* TODO: this api needs some more work, needs to support lists */ -CamelImapStoreNamespace *camel_imap_store_summary_namespace_new(CamelImapStoreSummary *s, const char *full_name, char dir_sep); -void camel_imap_store_summary_namespace_set(CamelImapStoreSummary *s, CamelImapStoreNamespace *ns); -CamelImapStoreNamespace *camel_imap_store_summary_namespace_find_path(CamelImapStoreSummary *s, const char *path); -CamelImapStoreNamespace *camel_imap_store_summary_namespace_find_full(CamelImapStoreSummary *s, const char *full_name); - -/* converts to/from utf8 canonical nasmes */ -char *camel_imap_store_summary_full_to_path(CamelImapStoreSummary *s, const char *full_name, char dir_sep); -char *camel_imap_store_summary_path_to_full(CamelImapStoreSummary *s, const char *path, char dir_sep); - -CamelImapStoreInfo *camel_imap_store_summary_full_name(CamelImapStoreSummary *s, const char *full_name); -CamelImapStoreInfo *camel_imap_store_summary_add_from_full(CamelImapStoreSummary *s, const char *full_name, char dir_sep); - -/* a convenience lookup function. always use this if path known */ -char *camel_imap_store_summary_full_from_path(CamelImapStoreSummary *s, const char *path); - -/* helper macro's */ -#define camel_imap_store_info_full_name(s, i) (camel_store_info_string((CamelStoreSummary *)s, (const CamelStoreInfo *)i, CAMEL_IMAP_STORE_INFO_FULL_NAME)) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_IMAP_STORE_SUMMARY_H */ diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c deleted file mode 100644 index 07152eef87..0000000000 --- a/camel/providers/imap/camel-imap-store.c +++ /dev/null @@ -1,2845 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-store.c : class for an imap store */ - -/* - * Authors: - * Dan Winship - * Jeffrey Stedfast - * - * Copyright 2000, 2003 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "e-util/e-path.h" - -#include "camel-imap-store.h" -#include "camel-imap-store-summary.h" -#include "camel-imap-folder.h" -#include "camel-imap-utils.h" -#include "camel-imap-command.h" -#include "camel-imap-summary.h" -#include "camel-imap-message-cache.h" -#include "camel-disco-diary.h" -#include "camel-file-utils.h" -#include "camel-folder.h" -#include "camel-exception.h" -#include "camel-session.h" -#include "camel-stream.h" -#include "camel-stream-buffer.h" -#include "camel-stream-fs.h" -#include "camel-stream-process.h" -#include "camel-tcp-stream-raw.h" -#include "camel-tcp-stream-ssl.h" -#include "camel-url.h" -#include "camel-sasl.h" -#include "camel-utf8.h" -#include "camel-string-utils.h" - -#include "camel-imap-private.h" -#include "camel-private.h" - -#define d(x) - -/* Specified in RFC 2060 */ -#define IMAP_PORT 143 -#define SIMAP_PORT 993 - - -extern int camel_verbose_debug; - -static CamelDiscoStoreClass *parent_class = NULL; - -static char imap_tag_prefix = 'A'; - -static void construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex); - -static int imap_setv (CamelObject *object, CamelException *ex, CamelArgV *args); -static int imap_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args); - -static char *imap_get_name (CamelService *service, gboolean brief); - -static gboolean can_work_offline (CamelDiscoStore *disco_store); -static gboolean imap_connect_online (CamelService *service, CamelException *ex); -static gboolean imap_connect_offline (CamelService *service, CamelException *ex); -static gboolean imap_disconnect_online (CamelService *service, gboolean clean, CamelException *ex); -static gboolean imap_disconnect_offline (CamelService *service, gboolean clean, CamelException *ex); -static void imap_noop (CamelStore *store, CamelException *ex); -static GList *query_auth_types (CamelService *service, CamelException *ex); -static guint hash_folder_name (gconstpointer key); -static gint compare_folder_name (gconstpointer a, gconstpointer b); -static CamelFolder *get_folder_online (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex); -static CamelFolder *get_folder_offline (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex); -static CamelFolderInfo *create_folder (CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex); -static void delete_folder (CamelStore *store, const char *folder_name, CamelException *ex); -static void rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex); -static CamelFolderInfo *get_folder_info_online (CamelStore *store, - const char *top, - guint32 flags, - CamelException *ex); -static CamelFolderInfo *get_folder_info_offline (CamelStore *store, - const char *top, - guint32 flags, - CamelException *ex); -static gboolean folder_subscribed (CamelStore *store, const char *folder_name); -static void subscribe_folder (CamelStore *store, const char *folder_name, - CamelException *ex); -static void unsubscribe_folder (CamelStore *store, const char *folder_name, - CamelException *ex); - -static void get_folders_online (CamelImapStore *imap_store, const char *pattern, - GPtrArray *folders, gboolean lsub, CamelException *ex); - - -static void imap_folder_effectively_unsubscribed(CamelImapStore *imap_store, const char *folder_name, CamelException *ex); -static gboolean imap_check_folder_still_extant (CamelImapStore *imap_store, const char *full_name, CamelException *ex); -static void imap_forget_folder(CamelImapStore *imap_store, const char *folder_name, CamelException *ex); -static void imap_set_server_level (CamelImapStore *store); - -static void -camel_imap_store_class_init (CamelImapStoreClass *camel_imap_store_class) -{ - CamelObjectClass *camel_object_class = - CAMEL_OBJECT_CLASS (camel_imap_store_class); - CamelServiceClass *camel_service_class = - CAMEL_SERVICE_CLASS (camel_imap_store_class); - CamelStoreClass *camel_store_class = - CAMEL_STORE_CLASS (camel_imap_store_class); - CamelDiscoStoreClass *camel_disco_store_class = - CAMEL_DISCO_STORE_CLASS (camel_imap_store_class); - - parent_class = CAMEL_DISCO_STORE_CLASS (camel_type_get_global_classfuncs (camel_disco_store_get_type ())); - - /* virtual method overload */ - camel_object_class->setv = imap_setv; - camel_object_class->getv = imap_getv; - - camel_service_class->construct = construct; - camel_service_class->query_auth_types = query_auth_types; - camel_service_class->get_name = imap_get_name; - - camel_store_class->hash_folder_name = hash_folder_name; - camel_store_class->compare_folder_name = compare_folder_name; - camel_store_class->create_folder = create_folder; - camel_store_class->delete_folder = delete_folder; - camel_store_class->rename_folder = rename_folder; - camel_store_class->free_folder_info = camel_store_free_folder_info_full; - camel_store_class->folder_subscribed = folder_subscribed; - camel_store_class->subscribe_folder = subscribe_folder; - camel_store_class->unsubscribe_folder = unsubscribe_folder; - camel_store_class->noop = imap_noop; - - camel_disco_store_class->can_work_offline = can_work_offline; - camel_disco_store_class->connect_online = imap_connect_online; - camel_disco_store_class->connect_offline = imap_connect_offline; - camel_disco_store_class->disconnect_online = imap_disconnect_online; - camel_disco_store_class->disconnect_offline = imap_disconnect_offline; - camel_disco_store_class->get_folder_online = get_folder_online; - camel_disco_store_class->get_folder_offline = get_folder_offline; - camel_disco_store_class->get_folder_resyncing = get_folder_online; - camel_disco_store_class->get_folder_info_online = get_folder_info_online; - camel_disco_store_class->get_folder_info_offline = get_folder_info_offline; - camel_disco_store_class->get_folder_info_resyncing = get_folder_info_online; -} - -static gboolean -free_key (gpointer key, gpointer value, gpointer user_data) -{ - g_free (key); - return TRUE; -} - -static void -camel_imap_store_finalize (CamelObject *object) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (object); - - /* This frees current_folder, folders, authtypes, streams, and namespace. */ - camel_service_disconnect((CamelService *)imap_store, TRUE, NULL); - - if (imap_store->summary) { - camel_store_summary_save((CamelStoreSummary *)imap_store->summary); - camel_object_unref(imap_store->summary); - } - - if (imap_store->base_url) - g_free (imap_store->base_url); - if (imap_store->storage_path) - g_free (imap_store->storage_path); - -#ifdef ENABLE_THREADS - e_thread_destroy (imap_store->async_thread); -#endif -} - -#ifdef ENABLE_THREADS -static void async_destroy(EThread *et, EMsg *em, void *data) -{ - CamelImapStore *imap_store = data; - CamelImapMsg *msg = (CamelImapMsg *)em; - - if (msg->free) - msg->free (imap_store, msg); - - g_free (msg); -} - -static void async_received(EThread *et, EMsg *em, void *data) -{ - CamelImapStore *imap_store = data; - CamelImapMsg *msg = (CamelImapMsg *)em; - - if (msg->receive) - msg->receive(imap_store, msg); -} - -CamelImapMsg *camel_imap_msg_new(void (*receive)(CamelImapStore *store, struct _CamelImapMsg *m), - void (*free)(CamelImapStore *store, struct _CamelImapMsg *m), - size_t size) -{ - CamelImapMsg *msg; - - g_assert(size >= sizeof(*msg)); - - msg = g_malloc0(size); - msg->receive = receive; - msg->free = free; - - return msg; -} - -void camel_imap_msg_queue(CamelImapStore *store, CamelImapMsg *msg) -{ - e_thread_put(store->async_thread, (EMsg *)msg); -} - -#endif - -static void -camel_imap_store_init (gpointer object, gpointer klass) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (object); - - imap_store->istream = NULL; - imap_store->ostream = NULL; - - imap_store->dir_sep = '\0'; - imap_store->current_folder = NULL; - imap_store->connected = FALSE; - imap_store->preauthed = FALSE; - - imap_store->tag_prefix = imap_tag_prefix++; - if (imap_tag_prefix > 'Z') - imap_tag_prefix = 'A'; - -#ifdef ENABLE_THREADS - imap_store->async_thread = e_thread_new(E_THREAD_QUEUE); - e_thread_set_msg_destroy(imap_store->async_thread, async_destroy, imap_store); - e_thread_set_msg_received(imap_store->async_thread, async_received, imap_store); -#endif /* ENABLE_THREADS */ -} - -CamelType -camel_imap_store_get_type (void) -{ - static CamelType camel_imap_store_type = CAMEL_INVALID_TYPE; - - if (camel_imap_store_type == CAMEL_INVALID_TYPE) { - camel_imap_store_type = - camel_type_register (CAMEL_DISCO_STORE_TYPE, - "CamelImapStore", - sizeof (CamelImapStore), - sizeof (CamelImapStoreClass), - (CamelObjectClassInitFunc) camel_imap_store_class_init, - NULL, - (CamelObjectInitFunc) camel_imap_store_init, - (CamelObjectFinalizeFunc) camel_imap_store_finalize); - } - - return camel_imap_store_type; -} - -static void -construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (service); - CamelStore *store = CAMEL_STORE (service); - char *tmp; - CamelURL *summary_url; - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set (ex)) - return; - - imap_store->storage_path = camel_session_get_storage_path (session, service, ex); - if (!imap_store->storage_path) - return; - - /* FIXME */ - imap_store->base_url = camel_url_to_string (service->url, (CAMEL_URL_HIDE_PASSWORD | - CAMEL_URL_HIDE_PARAMS | - CAMEL_URL_HIDE_AUTH)); - - imap_store->parameters = 0; - if (camel_url_get_param (url, "use_lsub")) - store->flags |= CAMEL_STORE_SUBSCRIPTIONS; - if (camel_url_get_param (url, "namespace")) { - imap_store->parameters |= IMAP_PARAM_OVERRIDE_NAMESPACE; - g_free(imap_store->namespace); - imap_store->namespace = g_strdup (camel_url_get_param (url, "namespace")); - } - if (camel_url_get_param (url, "check_all")) - imap_store->parameters |= IMAP_PARAM_CHECK_ALL; - if (camel_url_get_param (url, "filter")) { - imap_store->parameters |= IMAP_PARAM_FILTER_INBOX; - store->flags |= CAMEL_STORE_FILTER_INBOX; - } - - /* setup/load the store summary */ - tmp = alloca(strlen(imap_store->storage_path)+32); - sprintf(tmp, "%s/.ev-store-summary", imap_store->storage_path); - imap_store->summary = camel_imap_store_summary_new(); - camel_store_summary_set_filename((CamelStoreSummary *)imap_store->summary, tmp); - summary_url = camel_url_new(imap_store->base_url, NULL); - camel_store_summary_set_uri_base((CamelStoreSummary *)imap_store->summary, summary_url); - camel_url_free(summary_url); - if (camel_store_summary_load((CamelStoreSummary *)imap_store->summary) == 0) { - CamelImapStoreSummary *is = imap_store->summary; - - if (is->namespace) { - /* if namespace has changed, clear folder list */ - if (imap_store->namespace && strcmp(imap_store->namespace, is->namespace->full_name) != 0) { - camel_store_summary_clear((CamelStoreSummary *)is); - } else { - imap_store->namespace = g_strdup(is->namespace->full_name); - imap_store->dir_sep = is->namespace->sep; - store->dir_sep = is->namespace->sep; - } - } - - imap_store->capabilities = is->capabilities; - imap_set_server_level(imap_store); - } -} - -static int -imap_setv (CamelObject *object, CamelException *ex, CamelArgV *args) -{ - CamelImapStore *store = (CamelImapStore *) object; - guint32 tag, flags; - int i; - - for (i = 0; i < args->argc; i++) { - tag = args->argv[i].tag; - - /* make sure this arg wasn't already handled */ - if (tag & CAMEL_ARG_IGNORE) - continue; - - /* make sure this is an arg we're supposed to handle */ - if ((tag & CAMEL_ARG_TAG) <= CAMEL_IMAP_STORE_ARG_FIRST || - (tag & CAMEL_ARG_TAG) >= CAMEL_IMAP_STORE_ARG_FIRST + 100) - continue; - - if (tag == CAMEL_IMAP_STORE_NAMESPACE) { - if (strcmp (store->namespace, args->argv[i].ca_str) != 0) { - g_free (store->namespace); - store->namespace = g_strdup (args->argv[i].ca_str); - /* the current imap code will need to do a reconnect for this to take effect */ - /*reconnect = TRUE;*/ - } - } else if (tag == CAMEL_IMAP_STORE_OVERRIDE_NAMESPACE) { - flags = args->argv[i].ca_int ? IMAP_PARAM_OVERRIDE_NAMESPACE : 0; - flags |= (store->parameters & ~IMAP_PARAM_OVERRIDE_NAMESPACE); - - if (store->parameters != flags) { - store->parameters = flags; - /* the current imap code will need to do a reconnect for this to take effect */ - /*reconnect = TRUE;*/ - } - } else if (tag == CAMEL_IMAP_STORE_CHECK_ALL) { - flags = args->argv[i].ca_int ? IMAP_PARAM_CHECK_ALL : 0; - flags |= (store->parameters & ~IMAP_PARAM_CHECK_ALL); - store->parameters = flags; - /* no need to reconnect for this option to take effect... */ - } else if (tag == CAMEL_IMAP_STORE_FILTER_INBOX) { - flags = args->argv[i].ca_int ? IMAP_PARAM_FILTER_INBOX : 0; - flags |= (store->parameters & ~IMAP_PARAM_FILTER_INBOX); - store->parameters = flags; - /* no need to reconnect for this option to take effect... */ - } else { - /* error?? */ - continue; - } - - /* let our parent know that we've handled this arg */ - camel_argv_ignore (args, i); - } - - /* FIXME: if we need to reconnect for a change to take affect, - we need to do it here... or, better yet, somehow chain it - up to CamelService's setv implementation. */ - - return CAMEL_OBJECT_CLASS (parent_class)->setv (object, ex, args); -} - -static int -imap_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args) -{ - CamelImapStore *store = (CamelImapStore *) object; - guint32 tag; - int i; - - for (i = 0; i < args->argc; i++) { - tag = args->argv[i].tag; - - /* make sure this is an arg we're supposed to handle */ - if ((tag & CAMEL_ARG_TAG) <= CAMEL_IMAP_STORE_ARG_FIRST || - (tag & CAMEL_ARG_TAG) >= CAMEL_IMAP_STORE_ARG_FIRST + 100) - continue; - - switch (tag) { - case CAMEL_IMAP_STORE_NAMESPACE: - /* get the username */ - *args->argv[i].ca_str = store->namespace; - break; - case CAMEL_IMAP_STORE_OVERRIDE_NAMESPACE: - /* get the auth mechanism */ - *args->argv[i].ca_int = store->parameters & IMAP_PARAM_OVERRIDE_NAMESPACE ? TRUE : FALSE; - break; - case CAMEL_IMAP_STORE_CHECK_ALL: - /* get the hostname */ - *args->argv[i].ca_int = store->parameters & IMAP_PARAM_CHECK_ALL ? TRUE : FALSE; - break; - case CAMEL_IMAP_STORE_FILTER_INBOX: - /* get the port */ - *args->argv[i].ca_int = store->parameters & IMAP_PARAM_FILTER_INBOX ? TRUE : FALSE; - break; - default: - /* error? */ - break; - } - } - - return CAMEL_OBJECT_CLASS (parent_class)->getv (object, ex, args); -} - -static char * -imap_get_name (CamelService *service, gboolean brief) -{ - if (brief) - return g_strdup_printf (_("IMAP server %s"), service->url->host); - else - return g_strdup_printf (_("IMAP service for %s on %s"), - service->url->user, service->url->host); -} - -static void -imap_set_server_level (CamelImapStore *store) -{ - if (store->capabilities & IMAP_CAPABILITY_IMAP4REV1) { - store->server_level = IMAP_LEVEL_IMAP4REV1; - store->capabilities |= IMAP_CAPABILITY_STATUS; - } else if (store->capabilities & IMAP_CAPABILITY_IMAP4) - store->server_level = IMAP_LEVEL_IMAP4; - else - store->server_level = IMAP_LEVEL_UNKNOWN; -} - -static struct { - const char *name; - guint32 flag; -} capabilities[] = { - { "IMAP4", IMAP_CAPABILITY_IMAP4 }, - { "IMAP4REV1", IMAP_CAPABILITY_IMAP4REV1 }, - { "STATUS", IMAP_CAPABILITY_STATUS }, - { "NAMESPACE", IMAP_CAPABILITY_NAMESPACE }, - { "UIDPLUS", IMAP_CAPABILITY_UIDPLUS }, - { "LITERAL+", IMAP_CAPABILITY_LITERALPLUS }, - { "STARTTLS", IMAP_CAPABILITY_STARTTLS }, - { NULL, 0 } -}; - - -static gboolean -imap_get_capability (CamelService *service, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelImapResponse *response; - char *result, *capa, *lasts; - int i; - - CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock); - - /* Find out the IMAP capabilities */ - /* We assume we have utf8 capable search until a failed search tells us otherwise */ - store->capabilities = IMAP_CAPABILITY_utf8_search; - store->authtypes = g_hash_table_new (g_str_hash, g_str_equal); - response = camel_imap_command (store, NULL, ex, "CAPABILITY"); - if (!response) - return FALSE; - result = camel_imap_response_extract (store, response, "CAPABILITY ", ex); - if (!result) - return FALSE; - - /* Skip over "* CAPABILITY ". */ - capa = result + 13; - for (capa = strtok_r (capa, " ", &lasts); capa; - capa = strtok_r (NULL, " ", &lasts)) { - if (!strncmp (capa, "AUTH=", 5)) { - g_hash_table_insert (store->authtypes, - g_strdup (capa + 5), - GINT_TO_POINTER (1)); - continue; - } - for (i = 0; capabilities[i].name; i++) { - if (strcasecmp (capa, capabilities[i].name) == 0) { - store->capabilities |= capabilities[i].flag; - break; - } - } - } - g_free (result); - - imap_set_server_level (store); - - if (store->summary->capabilities != store->capabilities) { - store->summary->capabilities = store->capabilities; - camel_store_summary_touch((CamelStoreSummary *)store->summary); - camel_store_summary_save((CamelStoreSummary *)store->summary); - } - - return TRUE; -} - -enum { - USE_SSL_NEVER, - USE_SSL_ALWAYS, - USE_SSL_WHEN_POSSIBLE -}; - -#define SSL_PORT_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3) -#define STARTTLS_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_TLS) - -static gboolean -connect_to_server (CamelService *service, int ssl_mode, int try_starttls, CamelException *ex) -{ - CamelImapStore *store = (CamelImapStore *) service; - CamelImapResponse *response; - CamelStream *tcp_stream; - struct hostent *h; - int clean_quit; - int port, ret; - char *buf; - - h = camel_service_gethost (service, ex); - if (!h) - return FALSE; - - port = service->url->port ? service->url->port : 143; - - if (ssl_mode != USE_SSL_NEVER) { -#ifdef HAVE_SSL - if (try_starttls) { - tcp_stream = camel_tcp_stream_ssl_new_raw (service->session, service->url->host, STARTTLS_FLAGS); - } else { - port = service->url->port ? service->url->port : 993; - tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, SSL_PORT_FLAGS); - } -#else - if (!try_starttls) - port = service->url->port ? service->url->port : 993; - - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s (port %d): %s"), - service->url->host, port, - _("SSL unavailable")); - - camel_free_host (h); - - return FALSE; -#endif /* HAVE_SSL */ - } else { - tcp_stream = camel_tcp_stream_raw_new (); - } - - ret = camel_tcp_stream_connect (CAMEL_TCP_STREAM (tcp_stream), h, port); - camel_free_host (h); - if (ret == -1) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Connection cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s (port %d): %s"), - service->url->host, port, g_strerror (errno)); - - camel_object_unref (CAMEL_OBJECT (tcp_stream)); - - return FALSE; - } - - store->ostream = tcp_stream; - store->istream = camel_stream_buffer_new (tcp_stream, CAMEL_STREAM_BUFFER_READ); - - store->connected = TRUE; - store->preauthed = FALSE; - store->command = 0; - - /* Read the greeting, if any, and deal with PREAUTH */ - if (camel_imap_store_readline (store, &buf, ex) < 0) { - if (store->istream) { - camel_object_unref (CAMEL_OBJECT (store->istream)); - store->istream = NULL; - } - - if (store->ostream) { - camel_object_unref (CAMEL_OBJECT (store->ostream)); - store->ostream = NULL; - } - - store->connected = FALSE; - - return FALSE; - } - if (!strncmp(buf, "* PREAUTH", 9)) - store->preauthed = TRUE; - g_free (buf); - - /* get the imap server capabilities */ - if (!imap_get_capability (service, ex)) { - if (store->istream) { - camel_object_unref (CAMEL_OBJECT (store->istream)); - store->istream = NULL; - } - - if (store->ostream) { - camel_object_unref (CAMEL_OBJECT (store->ostream)); - store->ostream = NULL; - } - - store->connected = FALSE; - return FALSE; - } - -#ifdef HAVE_SSL - if (ssl_mode == USE_SSL_WHEN_POSSIBLE) { - if (store->capabilities & IMAP_CAPABILITY_STARTTLS) - goto starttls; - } else if (ssl_mode == USE_SSL_ALWAYS) { - if (try_starttls) { - if (store->capabilities & IMAP_CAPABILITY_STARTTLS) { - /* attempt to toggle STARTTLS mode */ - goto starttls; - } else { - /* server doesn't support STARTTLS, abort */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to IMAP server %s in secure mode: %s"), - service->url->host, _("SSL/TLS extension not supported.")); - /* we have the possibility of quitting cleanly here */ - clean_quit = TRUE; - goto exception; - } - } - } -#endif /* HAVE_SSL */ - - return TRUE; - -#ifdef HAVE_SSL - starttls: - - /* as soon as we send a STARTTLS command, all hope is lost of a clean QUIT if problems arise */ - clean_quit = FALSE; - - response = camel_imap_command (store, NULL, ex, "STARTTLS"); - if (!response) { - camel_object_unref (CAMEL_OBJECT (store->istream)); - camel_object_unref (CAMEL_OBJECT (store->ostream)); - store->istream = store->ostream = NULL; - return FALSE; - } - - camel_imap_response_free_without_processing (store, response); - - /* Okay, now toggle SSL/TLS mode */ - if (camel_tcp_stream_ssl_enable_ssl (CAMEL_TCP_STREAM_SSL (tcp_stream)) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to IMAP server %s in secure mode: %s"), - service->url->host, _("SSL negotiations failed")); - goto exception; - } - - /* rfc2595, section 4 states that after a successful STLS - command, the client MUST discard prior CAPA responses */ - if (!imap_get_capability (service, ex)) { - if (store->istream) { - camel_object_unref (CAMEL_OBJECT (store->istream)); - store->istream = NULL; - } - - if (store->ostream) { - camel_object_unref (CAMEL_OBJECT (store->ostream)); - store->ostream = NULL; - } - - store->connected = FALSE; - - return FALSE; - } - - return TRUE; - - exception: - - if (clean_quit && store->connected) { - /* try to disconnect cleanly */ - response = camel_imap_command (store, NULL, ex, "LOGOUT"); - if (response) - camel_imap_response_free_without_processing (store, response); - } - - if (store->istream) { - camel_object_unref (CAMEL_OBJECT (store->istream)); - store->istream = NULL; - } - - if (store->ostream) { - camel_object_unref (CAMEL_OBJECT (store->ostream)); - store->ostream = NULL; - } - - store->connected = FALSE; - - return FALSE; -#endif /* HAVE_SSL */ -} - -static gboolean -connect_to_server_process (CamelService *service, const char *cmd, CamelException *ex) -{ - CamelImapStore *store = (CamelImapStore *) service; - CamelStream *cmd_stream; - int ret, i = 0; - char *buf; - char *cmd_copy; - char *full_cmd; - char *child_env[7]; - - /* Put full details in the environment, in case the connection - program needs them */ - buf = camel_url_to_string(service->url, 0); - child_env[i++] = g_strdup_printf("URL=%s", buf); - g_free(buf); - - child_env[i++] = g_strdup_printf("URLHOST=%s", service->url->host); - if (service->url->port) - child_env[i++] = g_strdup_printf("URLPORT=%d", service->url->port); - if (service->url->user) - child_env[i++] = g_strdup_printf("URLUSER=%s", service->url->user); - if (service->url->passwd) - child_env[i++] = g_strdup_printf("URLPASSWD=%s", service->url->passwd); - if (service->url->path) - child_env[i++] = g_strdup_printf("URLPATH=%s", service->url->path); - child_env[i] = NULL; - - /* Now do %h, %u, etc. substitution in cmd */ - buf = cmd_copy = g_strdup(cmd); - - full_cmd = g_strdup(""); - - for(;;) { - char *pc; - char *tmp; - char *var; - int len; - - pc = strchr(buf, '%'); - ignore: - if (!pc) { - tmp = g_strdup_printf("%s%s", full_cmd, buf); - g_free(full_cmd); - full_cmd = tmp; - break; - } - - len = pc - buf; - - var = NULL; - - switch(pc[1]) { - case 'h': - var = service->url->host; - break; - case 'u': - var = service->url->user; - break; - } - if (!var) { - /* If there wasn't a valid %-code, with an actual - variable to insert, pretend we didn't see the % */ - pc = strchr(pc + 1, '%'); - goto ignore; - } - tmp = g_strdup_printf("%s%.*s%s", full_cmd, len, buf, var); - g_free(full_cmd); - full_cmd = tmp; - buf = pc + 2; - } - - g_free(cmd_copy); - - cmd_stream = camel_stream_process_new (); - - ret = camel_stream_process_connect (CAMEL_STREAM_PROCESS(cmd_stream), - full_cmd, (const char **)child_env); - - while (i) - g_free(child_env[--i]); - - if (ret == -1) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Connection cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect with command \"%s\": %s"), - full_cmd, g_strerror (errno)); - - camel_object_unref (CAMEL_OBJECT (cmd_stream)); - g_free(full_cmd); - return FALSE; - } - g_free(full_cmd); - - store->ostream = cmd_stream; - store->istream = camel_stream_buffer_new (cmd_stream, CAMEL_STREAM_BUFFER_READ); - - store->connected = TRUE; - store->preauthed = FALSE; - store->command = 0; - - /* Read the greeting, if any, and deal with PREAUTH */ - if (camel_imap_store_readline (store, &buf, ex) < 0) { - if (store->istream) { - camel_object_unref (CAMEL_OBJECT (store->istream)); - store->istream = NULL; - } - - if (store->ostream) { - camel_object_unref (CAMEL_OBJECT (store->ostream)); - store->ostream = NULL; - } - - store->connected = FALSE; - return FALSE; - } - if (!strncmp(buf, "* PREAUTH", 9)) - store->preauthed = TRUE; - g_free (buf); - - /* get the imap server capabilities */ - if (!imap_get_capability (service, ex)) { - if (store->istream) { - camel_object_unref (CAMEL_OBJECT (store->istream)); - store->istream = NULL; - } - - if (store->ostream) { - camel_object_unref (CAMEL_OBJECT (store->ostream)); - store->ostream = NULL; - } - - store->connected = FALSE; - return FALSE; - } - - return TRUE; - -} - -static struct { - char *value; - int mode; -} ssl_options[] = { - { "", USE_SSL_ALWAYS }, - { "always", USE_SSL_ALWAYS }, - { "when-possible", USE_SSL_WHEN_POSSIBLE }, - { "never", USE_SSL_NEVER }, - { NULL, USE_SSL_NEVER }, -}; - -static gboolean -connect_to_server_wrapper (CamelService *service, CamelException *ex) -{ - const char *command; -#ifdef HAVE_SSL - const char *use_ssl; - int i, ssl_mode; -#endif - command = camel_url_get_param (service->url, "command"); - if (command) - return connect_to_server_process (service, command, ex); - -#ifdef HAVE_SSL - use_ssl = camel_url_get_param (service->url, "use_ssl"); - if (use_ssl) { - for (i = 0; ssl_options[i].value; i++) - if (!strcmp (ssl_options[i].value, use_ssl)) - break; - ssl_mode = ssl_options[i].mode; - } else - ssl_mode = USE_SSL_NEVER; - - if (ssl_mode == USE_SSL_ALWAYS) { - /* First try the ssl port */ - if (!connect_to_server (service, ssl_mode, FALSE, ex)) { - if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE) { - /* The ssl port seems to be unavailable, lets try STARTTLS */ - camel_exception_clear (ex); - return connect_to_server (service, ssl_mode, TRUE, ex); - } else { - return FALSE; - } - } - - return TRUE; - } else if (ssl_mode == USE_SSL_WHEN_POSSIBLE) { - /* If the server supports STARTTLS, use it */ - return connect_to_server (service, ssl_mode, TRUE, ex); - } else { - /* User doesn't care about SSL */ - return connect_to_server (service, ssl_mode, FALSE, ex); - } -#else - return connect_to_server (service, USE_SSL_NEVER, FALSE, ex); -#endif -} - -extern CamelServiceAuthType camel_imap_password_authtype; - -static GList * -query_auth_types (CamelService *service, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelServiceAuthType *authtype; - GList *sasl_types, *t, *next; - gboolean connected; - - if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) - return NULL; - - CAMEL_SERVICE_LOCK (store, connect_lock); - connected = connect_to_server_wrapper (service, ex); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - if (!connected) - return NULL; - - sasl_types = camel_sasl_authtype_list (FALSE); - for (t = sasl_types; t; t = next) { - authtype = t->data; - next = t->next; - - if (!g_hash_table_lookup (store->authtypes, authtype->authproto)) { - sasl_types = g_list_remove_link (sasl_types, t); - g_list_free_1 (t); - } - } - - return g_list_prepend (sasl_types, &camel_imap_password_authtype); -} - -/* folder_name is path name */ -static CamelFolderInfo * -imap_build_folder_info(CamelImapStore *imap_store, const char *folder_name) -{ - CamelURL *url; - const char *name; - CamelFolderInfo *fi; - - fi = g_malloc0(sizeof(*fi)); - - fi->full_name = g_strdup(folder_name); - fi->unread_message_count = 0; - - url = camel_url_new (imap_store->base_url, NULL); - g_free (url->path); - url->path = g_strdup_printf ("/%s", folder_name); - fi->url = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_url_free(url); - fi->path = g_strdup_printf("/%s", folder_name); - name = strrchr (fi->path, '/'); - if (name) - name++; - else - name = fi->path; - - fi->name = g_strdup (name); - - return fi; -} - -static void -imap_folder_effectively_unsubscribed(CamelImapStore *imap_store, - const char *folder_name, CamelException *ex) -{ - CamelFolderInfo *fi; - CamelStoreInfo *si; - - si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, folder_name); - if (si) { - if (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) { - si->flags &= ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; - camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); - camel_store_summary_save((CamelStoreSummary *)imap_store->summary); - } - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } - - if (imap_store->renaming) { - /* we don't need to emit a "folder_unsubscribed" signal - if we are in the process of renaming folders, so we - are done here... */ - return; - - } - - fi = imap_build_folder_info(imap_store, folder_name); - camel_object_trigger_event (CAMEL_OBJECT (imap_store), "folder_unsubscribed", fi); - camel_folder_info_free (fi); -} - -static void -imap_forget_folder (CamelImapStore *imap_store, const char *folder_name, CamelException *ex) -{ - CamelFolderSummary *summary; - CamelImapMessageCache *cache; - char *summary_file; - char *journal_file; - char *folder_dir, *storage_path; - CamelFolderInfo *fi; - const char *name; - - name = strrchr (folder_name, imap_store->dir_sep); - if (name) - name++; - else - name = folder_name; - - storage_path = g_strdup_printf ("%s/folders", imap_store->storage_path); - folder_dir = e_path_to_physical (storage_path, folder_name); - g_free (storage_path); - if (access (folder_dir, F_OK) != 0) { - g_free (folder_dir); - goto event; - } - - summary_file = g_strdup_printf ("%s/summary", folder_dir); - summary = camel_imap_summary_new (summary_file); - if (!summary) { - g_free (summary_file); - g_free (folder_dir); - goto event; - } - - cache = camel_imap_message_cache_new (folder_dir, summary, ex); - if (cache) - camel_imap_message_cache_clear (cache); - - camel_object_unref (cache); - camel_object_unref (summary); - - unlink (summary_file); - g_free (summary_file); - - journal_file = g_strdup_printf ("%s/summary", folder_dir); - unlink (journal_file); - g_free (journal_file); - - rmdir (folder_dir); - g_free (folder_dir); - - event: - - camel_store_summary_remove_path((CamelStoreSummary *)imap_store->summary, folder_name); - camel_store_summary_save((CamelStoreSummary *)imap_store->summary); - - fi = imap_build_folder_info(imap_store, folder_name); - camel_object_trigger_event (CAMEL_OBJECT (imap_store), "folder_deleted", fi); - camel_folder_info_free (fi); -} - -static gboolean -imap_check_folder_still_extant (CamelImapStore *imap_store, const char *full_name, - CamelException *ex) -{ - CamelImapResponse *response; - - response = camel_imap_command (imap_store, NULL, ex, "LIST \"\" %S", - full_name); - - if (response) { - gboolean stillthere = response->untagged->len != 0; - - camel_imap_response_free_without_processing (imap_store, response); - - return stillthere; - } - - /* if the command was rejected, there must be some other error, - assume it worked so we dont blow away the folder unecessarily */ - return TRUE; -} - -/* This is a little 'hack' to avoid the deadlock conditions that would otherwise - ensue when calling camel_folder_refresh_info from inside a lock */ -/* NB: on second thougts this is probably not entirely safe, but it'll do for now */ -/* No, its definetly not safe. So its been changed to copy the folders first */ -/* the alternative is to: - make the camel folder->lock recursive (which should probably be done) - or remove it from camel_folder_refresh_info, and use another locking mechanism */ -/* also see get_folder_info_online() for the same hack repeated */ -static void -imap_store_refresh_folders (CamelImapStore *store, CamelException *ex) -{ - GPtrArray *folders; - int i; - - folders = camel_object_bag_list(CAMEL_STORE (store)->folders); - - for (i = 0; i len; i++) { - CamelFolder *folder = folders->pdata[i]; - - CAMEL_IMAP_FOLDER (folder)->need_rescan = TRUE; - if (!camel_exception_is_set(ex)) - CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->refresh_info(folder, ex); - - if (camel_exception_is_set (ex) && - imap_check_folder_still_extant (store, folder->full_name, ex) == FALSE) { - gchar *namedup; - - /* the folder was deleted (may happen when we come back online - * after being offline */ - - namedup = g_strdup (folder->full_name); - camel_object_unref(folder); - imap_folder_effectively_unsubscribed (store, namedup, ex); - imap_forget_folder (store, namedup, ex); - g_free (namedup); - } else - camel_object_unref(folder); - } - - g_ptr_array_free (folders, TRUE); -} - -static gboolean -try_auth (CamelImapStore *store, const char *mech, CamelException *ex) -{ - CamelSasl *sasl; - CamelImapResponse *response; - char *resp; - char *sasl_resp; - - CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock); - - response = camel_imap_command (store, NULL, ex, "AUTHENTICATE %s", mech); - if (!response) - return FALSE; - - sasl = camel_sasl_new ("imap", mech, CAMEL_SERVICE (store)); - while (!camel_sasl_authenticated (sasl)) { - resp = camel_imap_response_extract_continuation (store, response, ex); - if (!resp) - goto lose; - - sasl_resp = camel_sasl_challenge_base64 (sasl, imap_next_word (resp), ex); - g_free (resp); - if (camel_exception_is_set (ex)) - goto break_and_lose; - - response = camel_imap_command_continuation (store, sasl_resp, strlen (sasl_resp), ex); - g_free (sasl_resp); - if (!response) - goto lose; - } - - resp = camel_imap_response_extract_continuation (store, response, NULL); - if (resp) { - /* Oops. SASL claims we're done, but the IMAP server - * doesn't think so... - */ - g_free (resp); - goto lose; - } - - camel_object_unref (CAMEL_OBJECT (sasl)); - - return TRUE; - - break_and_lose: - /* Get the server out of "waiting for continuation data" mode. */ - response = camel_imap_command_continuation (store, "*", 1, NULL); - if (response) - camel_imap_response_free (store, response); - - lose: - if (!camel_exception_is_set (ex)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Bad authentication response from server.")); - } - - camel_object_unref (CAMEL_OBJECT (sasl)); - - return FALSE; -} - -static gboolean -imap_auth_loop (CamelService *service, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelSession *session = camel_service_get_session (service); - CamelServiceAuthType *authtype = NULL; - CamelImapResponse *response; - char *errbuf = NULL; - gboolean authenticated = FALSE; - - CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock); - - if (store->preauthed) { - if (camel_verbose_debug) - fprintf(stderr, "Server %s has preauthenticated us.\n", - service->url->host); - return TRUE; - } - - if (service->url->authmech) { - if (!g_hash_table_lookup (store->authtypes, service->url->authmech)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("IMAP server %s does not support requested " - "authentication type %s"), - service->url->host, - service->url->authmech); - return FALSE; - } - - authtype = camel_sasl_authtype (service->url->authmech); - if (!authtype) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("No support for authentication type %s"), - service->url->authmech); - return FALSE; - } - - if (!authtype->need_password) { - authenticated = try_auth (store, authtype->authproto, ex); - if (!authenticated) - return FALSE; - } - } - - while (!authenticated) { - if (errbuf) { - /* We need to un-cache the password before prompting again */ - camel_session_forget_password (session, service, "password", ex); - g_free (service->url->passwd); - service->url->passwd = NULL; - } - - if (!service->url->passwd) { - char *prompt; - - prompt = g_strdup_printf (_("%sPlease enter the IMAP " - "password for %s@%s"), - errbuf ? errbuf : "", - service->url->user, - service->url->host); - service->url->passwd = - camel_session_get_password (session, prompt, FALSE, TRUE, - service, "password", ex); - g_free (prompt); - g_free (errbuf); - errbuf = NULL; - - if (!service->url->passwd) { - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("You didn't enter a password.")); - return FALSE; - } - } - - if (!store->connected) { - /* Some servers (eg, courier) will disconnect on - * a bad password. So reconnect here. - */ - if (!connect_to_server_wrapper (service, ex)) - return FALSE; - } - - if (authtype) - authenticated = try_auth (store, authtype->authproto, ex); - else { - response = camel_imap_command (store, NULL, ex, - "LOGIN %S %S", - service->url->user, - service->url->passwd); - if (response) { - camel_imap_response_free (store, response); - authenticated = TRUE; - } - } - if (!authenticated) { - if (camel_exception_get_id(ex) == CAMEL_EXCEPTION_USER_CANCEL) - return FALSE; - - errbuf = g_strdup_printf (_("Unable to authenticate " - "to IMAP server.\n%s\n\n"), - camel_exception_get_description (ex)); - camel_exception_clear (ex); - } - } - - return TRUE; -} - -static gboolean -can_work_offline (CamelDiscoStore *disco_store) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (disco_store); - - return camel_store_summary_count((CamelStoreSummary *)store->summary) != 0; -} - -static gboolean -imap_connect_online (CamelService *service, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelDiscoStore *disco_store = CAMEL_DISCO_STORE (service); - CamelImapResponse *response; - /*struct _namespaces *namespaces;*/ - char *result, *name, *path; - int i; - size_t len; - CamelImapStoreNamespace *ns; - - CAMEL_SERVICE_LOCK (store, connect_lock); - if (!connect_to_server_wrapper (service, ex) || - !imap_auth_loop (service, ex)) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - camel_service_disconnect (service, TRUE, NULL); - return FALSE; - } - - /* Get namespace and hierarchy separator */ - if ((store->capabilities & IMAP_CAPABILITY_NAMESPACE) && - !(store->parameters & IMAP_PARAM_OVERRIDE_NAMESPACE)) { - response = camel_imap_command (store, NULL, ex, "NAMESPACE"); - if (!response) - goto done; - - result = camel_imap_response_extract (store, response, "NAMESPACE", ex); - if (!result) - goto done; - -#if 0 - /* new code... */ - namespaces = imap_parse_namespace_response (result); - imap_namespaces_destroy (namespaces); - /* end new code */ -#endif - - name = camel_strstrcase (result, "NAMESPACE (("); - if (name) { - char *sep; - - name += 12; - store->namespace = imap_parse_string ((const char **) &name, &len); - if (name && *name++ == ' ') { - sep = imap_parse_string ((const char **) &name, &len); - if (sep) { - store->dir_sep = *sep; - ((CamelStore *)store)->dir_sep = store->dir_sep; - g_free (sep); - } - } - } - g_free (result); - } - - if (!store->namespace) - store->namespace = g_strdup (""); - - if (!store->dir_sep) { - if (store->server_level >= IMAP_LEVEL_IMAP4REV1) { - /* This idiom means "tell me the hierarchy separator - * for the given path, even if that path doesn't exist. - */ - response = camel_imap_command (store, NULL, ex, - "LIST %S \"\"", - store->namespace); - } else { - /* Plain IMAP4 doesn't have that idiom, so we fall back - * to "tell me about this folder", which will fail if - * the folder doesn't exist (eg, if namespace is ""). - */ - response = camel_imap_command (store, NULL, ex, - "LIST \"\" %S", - store->namespace); - } - if (!response) - goto done; - - result = camel_imap_response_extract (store, response, "LIST", NULL); - if (result) { - imap_parse_list_response (store, result, NULL, &store->dir_sep, NULL); - g_free (result); - } - if (!store->dir_sep) { - store->dir_sep = '/'; /* Guess */ - ((CamelStore *)store)->dir_sep = store->dir_sep; - } - } - - /* canonicalize the namespace to end with dir_sep */ - len = strlen (store->namespace); - if (len && store->namespace[len - 1] != store->dir_sep) { - gchar *tmp; - - tmp = g_strdup_printf ("%s%c", store->namespace, store->dir_sep); - g_free (store->namespace); - store->namespace = tmp; - } - - ns = camel_imap_store_summary_namespace_new(store->summary, store->namespace, store->dir_sep); - camel_imap_store_summary_namespace_set(store->summary, ns); - - if (CAMEL_STORE (store)->flags & CAMEL_STORE_SUBSCRIPTIONS) { - gboolean haveinbox = FALSE; - GPtrArray *folders; - char *pattern; - - /* this pre-fills the summary, and checks that lsub is useful */ - folders = g_ptr_array_new (); - pattern = g_strdup_printf ("%s*", store->namespace); - get_folders_online (store, pattern, folders, TRUE, ex); - g_free (pattern); - - for (i = 0; i < folders->len; i++) { - CamelFolderInfo *fi = folders->pdata[i]; - - haveinbox = haveinbox || !strcasecmp (fi->full_name, "INBOX"); - - if (fi->flags & (CAMEL_IMAP_FOLDER_MARKED | CAMEL_IMAP_FOLDER_UNMARKED)) - store->capabilities |= IMAP_CAPABILITY_useful_lsub; - camel_folder_info_free (fi); - } - - /* if the namespace is under INBOX, check INBOX explicitly */ - if (!strncasecmp (store->namespace, "INBOX", 5) && !camel_exception_is_set (ex)) { - gboolean just_subscribed = FALSE; - gboolean need_subscribe = FALSE; - - recheck: - g_ptr_array_set_size (folders, 0); - get_folders_online (store, "INBOX", folders, TRUE, ex); - - for (i = 0; i < folders->len; i++) { - CamelFolderInfo *fi = folders->pdata[i]; - - /* this should always be TRUE if folders->len > 0 */ - if (!strcasecmp (fi->full_name, "INBOX")) { - haveinbox = TRUE; - - /* if INBOX is marked as \NoSelect then it is probably - because it has not been subscribed to */ - if (!need_subscribe) - need_subscribe = fi->flags & CAMEL_FOLDER_NOSELECT; - } - - camel_folder_info_free (fi); - } - - need_subscribe = !haveinbox || need_subscribe; - if (need_subscribe && !just_subscribed && !camel_exception_is_set (ex)) { - /* in order to avoid user complaints, force a subscription to INBOX */ - response = camel_imap_command (store, NULL, ex, "SUBSCRIBE INBOX"); - if (response != NULL) { - /* force a re-check which will pre-fill the summary and - also get any folder flags present on the INBOX */ - camel_imap_response_free (store, response); - just_subscribed = TRUE; - goto recheck; - } - } - } - - g_ptr_array_free (folders, TRUE); - } - - path = g_strdup_printf ("%s/journal", store->storage_path); - disco_store->diary = camel_disco_diary_new (disco_store, path, ex); - g_free (path); - - done: - /* save any changes we had */ - camel_store_summary_save((CamelStoreSummary *)store->summary); - - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - if (camel_exception_is_set (ex)) - camel_service_disconnect (service, TRUE, NULL); - else if (camel_disco_diary_empty (disco_store->diary)) - imap_store_refresh_folders (store, ex); - - return !camel_exception_is_set (ex); -} - -static gboolean -imap_connect_offline (CamelService *service, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelDiscoStore *disco_store = CAMEL_DISCO_STORE (service); - char *path; - - path = g_strdup_printf ("%s/journal", store->storage_path); - disco_store->diary = camel_disco_diary_new (disco_store, path, ex); - g_free (path); - if (!disco_store->diary) - return FALSE; - - imap_store_refresh_folders (store, ex); - - store->connected = !camel_exception_is_set (ex); - return store->connected; -} - -static gboolean -imap_disconnect_offline (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelDiscoStore *disco = CAMEL_DISCO_STORE (service); - - store->connected = FALSE; - if (store->current_folder) { - camel_object_unref (CAMEL_OBJECT (store->current_folder)); - store->current_folder = NULL; - } - - if (store->authtypes) { - g_hash_table_foreach_remove (store->authtypes, - free_key, NULL); - g_hash_table_destroy (store->authtypes); - store->authtypes = NULL; - } - - if (store->namespace && !(store->parameters & IMAP_PARAM_OVERRIDE_NAMESPACE)) { - g_free (store->namespace); - store->namespace = NULL; - } - - if (disco->diary) { - camel_object_unref (CAMEL_OBJECT (disco->diary)); - disco->diary = NULL; - } - - return TRUE; -} - -static gboolean -imap_disconnect_online (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelImapResponse *response; - - if (store->connected && clean) { - response = camel_imap_command (store, NULL, NULL, "LOGOUT"); - camel_imap_response_free (store, response); - } - - if (store->istream) { - camel_object_unref (CAMEL_OBJECT (store->istream)); - store->istream = NULL; - } - - if (store->ostream) { - camel_object_unref (CAMEL_OBJECT (store->ostream)); - store->ostream = NULL; - } - - imap_disconnect_offline (service, clean, ex); - - return TRUE; -} - - -static gboolean -imap_summary_is_dirty (CamelFolderSummary *summary) -{ - CamelMessageInfo *info; - int max, i; - - max = camel_folder_summary_count (summary); - for (i = 0; i < max; i++) { - info = camel_folder_summary_index (summary, i); - if (info && (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) - return TRUE; - } - - return FALSE; -} - -static void -imap_noop (CamelStore *store, CamelException *ex) -{ - CamelImapStore *imap_store = (CamelImapStore *) store; - CamelDiscoStore *disco = (CamelDiscoStore *) store; - CamelImapResponse *response; - CamelFolder *current_folder; - - if (camel_disco_store_status (disco) != CAMEL_DISCO_STORE_ONLINE) - return; - - CAMEL_SERVICE_LOCK (imap_store, connect_lock); - - current_folder = imap_store->current_folder; - if (current_folder && imap_summary_is_dirty (current_folder->summary)) { - /* let's sync the flags instead. NB: must avoid folder lock */ - ((CamelFolderClass *)((CamelObject *)current_folder)->klass)->sync(current_folder, FALSE, ex); - } else { - response = camel_imap_command (imap_store, NULL, ex, "NOOP"); - if (response) - camel_imap_response_free (imap_store, response); - } - - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); -} - -static guint -hash_folder_name (gconstpointer key) -{ - if (strcasecmp (key, "INBOX") == 0) - return g_str_hash ("INBOX"); - else - return g_str_hash (key); -} - -static gint -compare_folder_name (gconstpointer a, gconstpointer b) -{ - gconstpointer aname = a, bname = b; - - if (strcasecmp (a, "INBOX") == 0) - aname = "INBOX"; - if (strcasecmp (b, "INBOX") == 0) - bname = "INBOX"; - return g_str_equal (aname, bname); -} - -static CamelFolder * -no_such_folder (const char *name, CamelException *ex) -{ - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("No such folder %s"), name); - return NULL; -} - -static int -get_folder_status (CamelImapStore *imap_store, const char *folder_name, const char *type) -{ - CamelImapResponse *response; - char *status, *p; - int out; - - /* FIXME: we assume the server is STATUS-capable */ - - response = camel_imap_command (imap_store, NULL, NULL, - "STATUS %F (%s)", - folder_name, - type); - - if (!response) { - CamelException ex; - - camel_exception_init (&ex); - if (imap_check_folder_still_extant (imap_store, folder_name, &ex) == FALSE) { - imap_folder_effectively_unsubscribed (imap_store, folder_name, &ex); - imap_forget_folder (imap_store, folder_name, &ex); - } - camel_exception_clear (&ex); - return -1; - } - - status = camel_imap_response_extract (imap_store, response, - "STATUS", NULL); - if (!status) - return -1; - - p = camel_strstrcase (status, type); - if (p) - out = strtoul (p + strlen (type), NULL, 10); - else - out = -1; - - g_free (status); - return out; -} - -static CamelFolder * -get_folder_online (CamelStore *store, const char *folder_name, - guint32 flags, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelImapResponse *response; - CamelFolder *new_folder; - char *folder_dir, *storage_path; - - if (!camel_imap_store_connected (imap_store, ex)) - return NULL; - - if (!strcasecmp (folder_name, "INBOX")) - folder_name = "INBOX"; - - /* Lock around the whole lot to check/create atomically */ - CAMEL_SERVICE_LOCK (imap_store, connect_lock); - if (imap_store->current_folder) { - camel_object_unref (CAMEL_OBJECT (imap_store->current_folder)); - imap_store->current_folder = NULL; - } - response = camel_imap_command (imap_store, NULL, NULL, "SELECT %F", folder_name); - if (!response) { - char *folder_real; - - if (!flags & CAMEL_STORE_FOLDER_CREATE) { - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - return no_such_folder (folder_name, ex); - } - - folder_real = camel_imap_store_summary_path_to_full(imap_store->summary, folder_name, store->dir_sep); - - response = camel_imap_command (imap_store, NULL, ex, "CREATE %S", folder_real); - - if (response) { - camel_imap_store_summary_add_from_full(imap_store->summary, folder_real, store->dir_sep); - - camel_imap_response_free (imap_store, response); - - response = camel_imap_command (imap_store, NULL, NULL, "SELECT %F", folder_name); - } - g_free(folder_real); - if (!response) { - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - return NULL; - } - } - - storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); - folder_dir = e_path_to_physical (storage_path, folder_name); - g_free(storage_path); - new_folder = camel_imap_folder_new (store, folder_name, folder_dir, ex); - g_free (folder_dir); - if (new_folder) { - CamelException local_ex; - - imap_store->current_folder = new_folder; - camel_object_ref (CAMEL_OBJECT (new_folder)); - camel_exception_init (&local_ex); - camel_imap_folder_selected (new_folder, response, &local_ex); - - if (camel_exception_is_set (&local_ex)) { - camel_exception_xfer (ex, &local_ex); - camel_object_unref (CAMEL_OBJECT (imap_store->current_folder)); - imap_store->current_folder = NULL; - camel_object_unref (CAMEL_OBJECT (new_folder)); - new_folder = NULL; - } - } - camel_imap_response_free_without_processing (imap_store, response); - - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - - return new_folder; -} - -static CamelFolder * -get_folder_offline (CamelStore *store, const char *folder_name, - guint32 flags, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelFolder *new_folder; - char *folder_dir, *storage_path; - - if (!imap_store->connected && - !camel_service_connect (CAMEL_SERVICE (store), ex)) - return NULL; - - if (!strcasecmp (folder_name, "INBOX")) - folder_name = "INBOX"; - - storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); - folder_dir = e_path_to_physical (storage_path, folder_name); - g_free(storage_path); - if (!folder_dir || access (folder_dir, F_OK) != 0) { - g_free (folder_dir); - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("No such folder %s"), folder_name); - return NULL; - } - - new_folder = camel_imap_folder_new (store, folder_name, folder_dir, ex); - g_free (folder_dir); - - return new_folder; -} - -static void -delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelImapResponse *response; - - if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) - return; - - /* make sure this folder isn't currently SELECTed */ - response = camel_imap_command (imap_store, NULL, ex, "SELECT INBOX"); - if (response) { - camel_imap_response_free_without_processing (imap_store, response); - - CAMEL_SERVICE_LOCK (imap_store, connect_lock); - - if (imap_store->current_folder) - camel_object_unref (CAMEL_OBJECT (imap_store->current_folder)); - /* no need to actually create a CamelFolder for INBOX */ - imap_store->current_folder = NULL; - - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - } else - return; - - response = camel_imap_command (imap_store, NULL, ex, "DELETE %F", - folder_name); - - if (response) { - camel_imap_response_free (imap_store, response); - imap_forget_folder (imap_store, folder_name, ex); - } -} - -static void -manage_subscriptions (CamelStore *store, const char *old_name, gboolean subscribe) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelStoreInfo *si; - int olen = strlen(old_name); - const char *path; - int i, count; - - count = camel_store_summary_count((CamelStoreSummary *)imap_store->summary); - for (i=0;isummary, i); - if (si) { - path = camel_store_info_path(imap_store->summary, si); - if (strncmp(path, old_name, olen) == 0) { - if (subscribe) - subscribe_folder(store, path, NULL); - else - unsubscribe_folder(store, path, NULL); - } - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } - } -} - -static void -rename_folder_info (CamelImapStore *imap_store, const char *old_name, const char *new_name) -{ - int i, count; - CamelStoreInfo *si; - int olen = strlen(old_name); - const char *path; - char *npath, *nfull; - - count = camel_store_summary_count((CamelStoreSummary *)imap_store->summary); - for (i=0;isummary, i); - if (si == NULL) - continue; - path = camel_store_info_path(imap_store->summary, si); - if (strncmp(path, old_name, olen) == 0) { - if (strlen(path) > olen) - npath = g_strdup_printf("%s/%s", new_name, path+olen+1); - else - npath = g_strdup(new_name); - nfull = camel_imap_store_summary_path_to_full(imap_store->summary, npath, imap_store->dir_sep); - - /* workaround for broken server (courier uses '.') that doesn't rename - subordinate folders as required by rfc 2060 */ - if (imap_store->dir_sep == '.') { - CamelImapResponse *response; - - response = camel_imap_command (imap_store, NULL, NULL, "RENAME %F %S", path, nfull); - if (response) - camel_imap_response_free (imap_store, response); - } - - camel_store_info_set_string((CamelStoreSummary *)imap_store->summary, si, CAMEL_STORE_INFO_PATH, npath); - camel_store_info_set_string((CamelStoreSummary *)imap_store->summary, si, CAMEL_IMAP_STORE_INFO_FULL_NAME, nfull); - - camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); - g_free(nfull); - g_free(npath); - } - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } -} - -static void -rename_folder (CamelStore *store, const char *old_name, const char *new_name_in, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelImapResponse *response; - char *oldpath, *newpath, *storage_path, *new_name; - - if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) - return; - - /* make sure this folder isn't currently SELECTed - it's - actually possible to rename INBOX but if you do another - INBOX will immediately be created by the server */ - response = camel_imap_command (imap_store, NULL, ex, "SELECT INBOX"); - if (response) { - camel_imap_response_free_without_processing (imap_store, response); - - CAMEL_SERVICE_LOCK (imap_store, connect_lock); - - if (imap_store->current_folder) - camel_object_unref (CAMEL_OBJECT (imap_store->current_folder)); - /* no need to actually create a CamelFolder for INBOX */ - imap_store->current_folder = NULL; - - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - } else - return; - - imap_store->renaming = TRUE; - - if (store->flags & CAMEL_STORE_SUBSCRIPTIONS) - manage_subscriptions(store, old_name, FALSE); - - new_name = camel_imap_store_summary_path_to_full(imap_store->summary, new_name_in, store->dir_sep); - response = camel_imap_command (imap_store, NULL, ex, "RENAME %F %S", old_name, new_name); - - if (!response) { - if (store->flags & CAMEL_STORE_SUBSCRIPTIONS) - manage_subscriptions(store, old_name, TRUE); - g_free(new_name); - imap_store->renaming = FALSE; - return; - } - - camel_imap_response_free (imap_store, response); - - /* rename summary, and handle broken server */ - rename_folder_info(imap_store, old_name, new_name_in); - - if (store->flags & CAMEL_STORE_SUBSCRIPTIONS) - manage_subscriptions(store, new_name_in, TRUE); - - storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); - oldpath = e_path_to_physical (storage_path, old_name); - newpath = e_path_to_physical (storage_path, new_name_in); - g_free(storage_path); - - /* So do we care if this didn't work? Its just a cache? */ - if (rename (oldpath, newpath) == -1) { - g_warning ("Could not rename message cache '%s' to '%s': %s: cache reset", - oldpath, newpath, strerror (errno)); - } - - g_free (oldpath); - g_free (newpath); - g_free(new_name); - - imap_store->renaming = FALSE; -} - -static CamelFolderInfo * -create_folder (CamelStore *store, const char *parent_name, - const char *folder_name, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - char *full_name, *resp, *thisone, *parent_real, *real_name; - CamelImapResponse *response; - CamelException internal_ex; - CamelFolderInfo *root = NULL; - gboolean need_convert; - int i = 0, flags; - - if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) - return NULL; - if (!parent_name) - parent_name = ""; - - if (strchr (folder_name, imap_store->dir_sep)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_PATH, - _("The folder name \"%s\" is invalid because " - "it containes the character \"%c\""), - folder_name, imap_store->dir_sep); - return NULL; - } - - /* check if the parent allows inferiors */ - - /* FIXME: use storesummary directly */ - parent_real = camel_imap_store_summary_full_from_path(imap_store->summary, parent_name); - if (parent_real == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_STATE, - _("Unknown parent folder: %s"), parent_name); - return NULL; - } - - need_convert = FALSE; - response = camel_imap_command (imap_store, NULL, ex, "LIST \"\" %S", - parent_real); - if (!response) /* whoa, this is bad */ { - g_free(parent_real); - return NULL; - } - - /* FIXME: does not handle unexpected circumstances very well */ - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i]; - - if (!imap_parse_list_response (imap_store, resp, &flags, NULL, &thisone)) - continue; - - if (strcmp (thisone, parent_name) == 0) { - if (flags & CAMEL_FOLDER_NOINFERIORS) - need_convert = TRUE; - break; - } - } - - camel_imap_response_free (imap_store, response); - - camel_exception_init (&internal_ex); - - /* if not, check if we can delete it and recreate it */ - if (need_convert) { - char *name; - - if (get_folder_status (imap_store, parent_name, "MESSAGES")) { - camel_exception_set (ex, CAMEL_EXCEPTION_FOLDER_INVALID_STATE, - _("The parent folder is not allowed to contain subfolders")); - g_free(parent_real); - return NULL; - } - - /* delete the old parent and recreate it */ - delete_folder (store, parent_name, &internal_ex); - if (camel_exception_is_set (&internal_ex)) { - camel_exception_xfer (ex, &internal_ex); - return NULL; - } - - /* add the dirsep to the end of parent_name */ - name = g_strdup_printf ("%s%c", parent_real, imap_store->dir_sep); - response = camel_imap_command (imap_store, NULL, ex, "CREATE %S", - name); - g_free (name); - - if (!response) { - g_free(parent_real); - return NULL; - } else - camel_imap_response_free (imap_store, response); - - root = imap_build_folder_info(imap_store, parent_name); - } - - /* ok now we can create the folder */ - real_name = camel_imap_store_summary_path_to_full(imap_store->summary, folder_name, store->dir_sep); - full_name = imap_concat (imap_store, parent_real, real_name); - g_free(real_name); - response = camel_imap_command (imap_store, NULL, ex, "CREATE %S", full_name); - - if (response) { - CamelImapStoreInfo *si; - CamelFolderInfo *fi; - - camel_imap_response_free (imap_store, response); - - si = camel_imap_store_summary_add_from_full(imap_store->summary, full_name, store->dir_sep); - camel_store_summary_save((CamelStoreSummary *)imap_store->summary); - fi = imap_build_folder_info(imap_store, camel_store_info_path(imap_store->summary, si)); - if (root) { - root->child = fi; - fi->parent = root; - } else { - root = fi; - } - camel_object_trigger_event (CAMEL_OBJECT (store), "folder_created", root); - } else if (root) { - /* need to re-recreate the folder we just deleted */ - camel_object_trigger_event (CAMEL_OBJECT (store), "folder_created", root); - camel_folder_info_free(root); - root = NULL; - } - - g_free (full_name); - g_free(parent_real); - - return root; -} - -static CamelFolderInfo * -parse_list_response_as_folder_info (CamelImapStore *imap_store, - const char *response) -{ - CamelFolderInfo *fi; - int flags; - char sep, *dir; - CamelURL *url; - CamelImapStoreInfo *si; - guint32 newflags; - - if (!imap_parse_list_response (imap_store, response, &flags, &sep, &dir)) - return NULL; - - /* FIXME: should use imap_build_folder_info, note the differences with param setting tho */ - - si = camel_imap_store_summary_add_from_full(imap_store->summary, dir, sep?sep:'/'); - newflags = (si->info.flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) | (flags & ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED); - if (si->info.flags != newflags) { - si->info.flags = newflags; - camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); - } - - fi = g_new0 (CamelFolderInfo, 1); - fi->flags = flags; - fi->name = g_strdup(camel_store_info_name(imap_store->summary, si)); - fi->path = g_strdup_printf("/%s", camel_store_info_path(imap_store->summary, si)); - fi->full_name = g_strdup(fi->path+1); - - url = camel_url_new (imap_store->base_url, NULL); - camel_url_set_path(url, fi->path); - - if (flags & CAMEL_FOLDER_NOSELECT || fi->name[0] == 0) - camel_url_set_param (url, "noselect", "yes"); - fi->url = camel_url_to_string (url, 0); - camel_url_free (url); - - /* FIXME: redundant */ - if (flags & CAMEL_IMAP_FOLDER_UNMARKED) - fi->unread_message_count = -1; - - return fi; -} - -/* this is used when lsub doesn't provide very useful information */ -static GPtrArray * -get_subscribed_folders (CamelImapStore *imap_store, const char *top, CamelException *ex) -{ - GPtrArray *names, *folders; - int i, toplen = strlen (top); - CamelStoreInfo *si; - CamelImapResponse *response; - CamelFolderInfo *fi; - char *result; - int haveinbox = FALSE; - - folders = g_ptr_array_new (); - names = g_ptr_array_new (); - for (i=0;(si = camel_store_summary_index((CamelStoreSummary *)imap_store->summary, i));i++) { - if (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) { - g_ptr_array_add(names, (char *)camel_imap_store_info_full_name(imap_store->summary, si)); - haveinbox = haveinbox || strcasecmp(camel_imap_store_info_full_name(imap_store->summary, si), "INBOX") == 0; - } - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } - - if (!haveinbox) - g_ptr_array_add (names, "INBOX"); - - for (i = 0; i < names->len; i++) { - response = camel_imap_command (imap_store, NULL, ex, - "LIST \"\" %S", - names->pdata[i]); - if (!response) - break; - - result = camel_imap_response_extract (imap_store, response, "LIST", NULL); - if (!result) { - camel_store_summary_remove_path((CamelStoreSummary *)imap_store->summary, names->pdata[i]); - g_ptr_array_remove_index_fast (names, i); - i--; - continue; - } - - fi = parse_list_response_as_folder_info (imap_store, result); - if (!fi) - continue; - - if (strncmp (top, fi->full_name, toplen) != 0) { - camel_folder_info_free (fi); - continue; - } - - g_ptr_array_add (folders, fi); - } - - g_ptr_array_free (names, TRUE); - - return folders; -} - -static int imap_match_pattern(char dir_sep, const char *pattern, const char *name) -{ - char p, n; - - p = *pattern++; - n = *name++; - while (n && p) { - if (n == p) { - p = *pattern++; - n = *name++; - } else if (p == '%') { - if (n != dir_sep) { - n = *name++; - } else { - p = *pattern++; - } - } else if (p == '*') { - return TRUE; - } else - return FALSE; - } - - return n == 0 && (p == '%' || p == 0); -} - -static void -get_folders_online (CamelImapStore *imap_store, const char *pattern, - GPtrArray *folders, gboolean lsub, CamelException *ex) -{ - CamelImapResponse *response; - CamelFolderInfo *fi; - char *list; - int i, count; - GHashTable *present; - CamelStoreInfo *si; - - response = camel_imap_command (imap_store, NULL, ex, - "%s \"\" %S", lsub ? "LSUB" : "LIST", - pattern); - if (!response) - return; - - present = g_hash_table_new(g_str_hash, g_str_equal); - for (i = 0; i < response->untagged->len; i++) { - list = response->untagged->pdata[i]; - fi = parse_list_response_as_folder_info (imap_store, list); - if (fi) { - g_ptr_array_add(folders, fi); - g_hash_table_insert(present, fi->full_name, fi); - } - } - camel_imap_response_free (imap_store, response); - - /* update our summary to match the server */ - count = camel_store_summary_count((CamelStoreSummary *)imap_store->summary); - for (i=0;isummary, i); - if (si == NULL) - continue; - - if (imap_match_pattern(((CamelStore *)imap_store)->dir_sep, pattern, camel_imap_store_info_full_name(imap_store->summary, si))) { - if (g_hash_table_lookup(present, camel_store_info_path(imap_store->summary, si)) != NULL) { - if (lsub && (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) == 0) { - si->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; - camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); - } - } else { - if (lsub) { - if (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) { - si->flags &= ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; - camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); - } - } else { - camel_store_summary_remove((CamelStoreSummary *)imap_store->summary, si); - count--; - i--; - } - } - } - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } - g_hash_table_destroy(present); -} - -#if 0 -static void -dumpfi(CamelFolderInfo *fi) -{ - int depth; - CamelFolderInfo *n = fi; - - if (fi == NULL) - return; - - depth = 0; - while (n->parent) { - depth++; - n = n->parent; - } - - while (fi) { - printf("%-40s %-30s %*s\n", fi->path, fi->full_name, depth*2+strlen(fi->url), fi->url); - if (fi->child) - dumpfi(fi->child); - fi = fi->sibling; - } -} -#endif - -static void -get_folder_counts(CamelImapStore *imap_store, CamelFolderInfo *fi, CamelException *ex) -{ - GSList *q; - CamelFolder *folder; - - /* non-recursive breath first search */ - - q = g_slist_append(NULL, fi); - - while (q) { - fi = q->data; - q = g_slist_remove_link(q, q); - - while (fi) { - /* ignore noselect folders, and check only inbox if we only check inbox */ - if ((fi->flags & CAMEL_FOLDER_NOSELECT) == 0 - && ( (imap_store->parameters & IMAP_PARAM_CHECK_ALL) - || strcasecmp(fi->full_name, "inbox") == 0) ) { - - CAMEL_SERVICE_LOCK (imap_store, connect_lock); - /* For the current folder, poke it to check for new - * messages and then report that number, rather than - * doing a STATUS command. - */ - if (imap_store->current_folder && strcmp(imap_store->current_folder->full_name, fi->full_name) == 0) { - /* we bypass the folder locking otherwise we can deadlock. we use the command lock for - any operations anyway so this is 'safe'. See comment above imap_store_refresh_folders() for info */ - CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(imap_store->current_folder))->refresh_info(imap_store->current_folder, ex); - fi->unread_message_count = camel_folder_get_unread_message_count (imap_store->current_folder); - } else { - fi->unread_message_count = get_folder_status (imap_store, fi->full_name, "UNSEEN"); - /* if we have this folder open, and the unread count has changed, update */ - folder = camel_object_bag_get(CAMEL_STORE(imap_store)->folders, fi->full_name); - if (folder && fi->unread_message_count != camel_folder_get_unread_message_count(folder)) { - CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->refresh_info(folder, ex); - fi->unread_message_count = camel_folder_get_unread_message_count(folder); - } - if (folder) - camel_object_unref(folder); - - } - - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - } else { - /* since its cheap, get it if they're open */ - folder = camel_object_bag_get(CAMEL_STORE(imap_store)->folders, fi->full_name); - if (folder) { - fi->unread_message_count = camel_folder_get_unread_message_count(folder); - camel_object_unref(folder); - } else - fi->unread_message_count = -1; - } - - if (fi->child) - q = g_slist_append(q, fi->child); - fi = fi->sibling; - } - } -} - -/* imap needs to treat inbox case insensitive */ -/* we'll assume the names are normalised already */ -static guint folder_hash(const void *ap) -{ - const char *a = ap; - - if (strcasecmp(a, "INBOX") == 0) - a = "INBOX"; - - return g_str_hash(a); -} - -static int folder_eq(const void *ap, const void *bp) -{ - const char *a = ap; - const char *b = bp; - - if (strcasecmp(a, "INBOX") == 0) - a = "INBOX"; - if (strcasecmp(b, "INBOX") == 0) - b = "INBOX"; - - return g_str_equal(a, b); -} - -static GPtrArray * -get_folders(CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - GSList *p = NULL; - GHashTable *infos; - int i; - GPtrArray *folders, *folders_out; - CamelFolderInfo *fi; - char *name; - int depth = 0; - int haveinbox = 0; - static int imap_max_depth = 0; - - if (!camel_imap_store_connected (imap_store, ex)) - return NULL; - - /* allow megalomaniacs to override the max of 10 */ - if (imap_max_depth == 0) { - name = getenv("CAMEL_IMAP_MAX_DEPTH"); - if (name) { - imap_max_depth = atoi (name); - imap_max_depth = MIN (MAX (imap_max_depth, 0), 2); - } else - imap_max_depth = 10; - } - - infos = g_hash_table_new(folder_hash, folder_eq); - - /* get starting point & strip trailing '/' */ - if (top[0] == 0) { - if (imap_store->namespace) { - top = imap_store->namespace; - i = strlen(top)-1; - name = g_malloc(i+2); - strcpy(name, top); - while (i>0 && name[i] == store->dir_sep) - name[i--] = 0; - } else - name = g_strdup(""); - } else { - name = camel_imap_store_summary_full_from_path(imap_store->summary, top); - if (name == NULL) - name = camel_imap_store_summary_path_to_full(imap_store->summary, top, store->dir_sep); - } - - d(printf("\n\nList '%s' %s\n", name, flags&CAMEL_STORE_FOLDER_INFO_RECURSIVE?"RECURSIVE":"NON-RECURSIVE")); - - folders_out = g_ptr_array_new(); - folders = g_ptr_array_new(); - - /* first get working list of names */ - get_folders_online (imap_store, name[0]?name:"%", folders, flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, ex); - if (camel_exception_is_set(ex)) - goto fail; - for (i=0; ilen && !haveinbox; i++) { - fi = folders->pdata[i]; - haveinbox = (strcasecmp(fi->full_name, "INBOX")) == 0; - } - - if (!haveinbox && top == imap_store->namespace) { - get_folders_online (imap_store, "INBOX", folders, - flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, ex); - - if (camel_exception_is_set (ex)) - goto fail; - } - - for (i=0; ilen; i++) - p = g_slist_prepend(p, folders->pdata[i]); - - g_ptr_array_set_size(folders, 0); - - /* p is a reversed list of pending folders for the next level, q is the list of folders for this */ - while (p) { - GSList *q = g_slist_reverse(p); - - p = NULL; - while (q) { - fi = q->data; - - q = g_slist_remove_link(q, q); - g_ptr_array_add(folders_out, fi); - - d(printf("Checking folder '%s'\n", fi->full_name)); - - /* First if we're not recursive mode on the top level, and we know it has or doesn't - or can't have children, no need to go further - a bit ugly */ - if ( top == imap_store->namespace - && (flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) == 0 - && (fi->flags & (CAMEL_FOLDER_CHILDREN|CAMEL_IMAP_FOLDER_NOCHILDREN|CAMEL_FOLDER_NOINFERIORS)) != 0) { - /* do nothing */ - } - /* Otherwise, if this has (or might have) children, scan it */ - else if ( (fi->flags & (CAMEL_IMAP_FOLDER_NOCHILDREN|CAMEL_FOLDER_NOINFERIORS)) == 0 - || (fi->flags & CAMEL_FOLDER_CHILDREN) != 0) { - char *n, *real; - - real = camel_imap_store_summary_full_from_path(imap_store->summary, fi->full_name); - n = imap_concat(imap_store, real?real:fi->full_name, "%"); - get_folders_online(imap_store, n, folders, flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, ex); - g_free(n); - g_free(real); - - if (folders->len > 0) - fi->flags |= CAMEL_FOLDER_CHILDREN; - - for (i=0;ilen;i++) { - fi = folders->pdata[i]; - if (g_hash_table_lookup(infos, fi->full_name) == NULL) { - g_hash_table_insert(infos, fi->full_name, fi); - if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) && depthcapabilities & IMAP_CAPABILITY_useful_lsub) - && (imap_store->parameters & IMAP_PARAM_CHECK_ALL)) - folders = get_subscribed_folders(imap_store, top, ex); - else - folders = get_folders(store, top, flags, ex); - - if (folders == NULL) - return NULL; - - tree = camel_folder_info_build(folders, top, '/', TRUE); - g_ptr_array_free(folders, TRUE); - - if (!(flags & CAMEL_STORE_FOLDER_INFO_FAST)) - get_folder_counts(imap_store, tree, ex); - - d(dumpfi(tree)); - camel_store_summary_save((CamelStoreSummary *)imap_store->summary); - - return tree; -} - -static gboolean -get_one_folder_offline (const char *physical_path, const char *path, gpointer data) -{ - GPtrArray *folders = data; - CamelImapStore *imap_store = folders->pdata[0]; - CamelFolderInfo *fi; - CamelStoreInfo *si; - - if (*path != '/') - return TRUE; - - /* folder_info_build will insert parent nodes as necessary and mark - * them as noselect, which is information we actually don't have at - * the moment. So let it do the right thing by bailing out if it's - * not a folder we're explicitly interested in. - */ - - si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, path+1); - if (si) { - if ((((CamelStore *)imap_store)->flags & CAMEL_STORE_SUBSCRIPTIONS) == 0 - || (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED)) { - fi = imap_build_folder_info(imap_store, path+1); - fi->flags = si->flags; - if (si->flags & CAMEL_FOLDER_NOSELECT) { - CamelURL *url = camel_url_new(fi->url, NULL); - - camel_url_set_param (url, "noselect", "yes"); - g_free(fi->url); - fi->url = camel_url_to_string (url, 0); - camel_url_free (url); - } - g_ptr_array_add (folders, fi); - } - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } - - return TRUE; -} - -static CamelFolderInfo * -get_folder_info_offline (CamelStore *store, const char *top, - guint32 flags, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelFolderInfo *fi; - GPtrArray *folders; - char *storage_path; - - if (!imap_store->connected && - !camel_service_connect (CAMEL_SERVICE (store), ex)) - return NULL; - - if ((store->flags & CAMEL_STORE_SUBSCRIPTIONS) && - !(flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED)) { - camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex); - return NULL; - } - - /* FIXME: obey other flags */ - - folders = g_ptr_array_new (); - - /* A kludge to avoid having to pass a struct to the callback */ - g_ptr_array_add (folders, imap_store); - storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); - if (!e_path_find_folders (storage_path, get_one_folder_offline, folders)) { - camel_disco_store_check_online (CAMEL_DISCO_STORE (imap_store), ex); - fi = NULL; - } else { - g_ptr_array_remove_index_fast (folders, 0); - fi = camel_folder_info_build (folders, "", '/', TRUE); - } - g_free(storage_path); - - g_ptr_array_free (folders, TRUE); - return fi; -} - -static gboolean -folder_subscribed (CamelStore *store, const char *folder_name) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelStoreInfo *si; - int truth = FALSE; - - si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, folder_name); - if (si) { - truth = (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) != 0; - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } - - return truth; -} - -/* Note: folder_name must match a folder as listed with get_folder_info() -> full_name */ -static void -subscribe_folder (CamelStore *store, const char *folder_name, - CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelImapResponse *response; - CamelFolderInfo *fi; - CamelStoreInfo *si; - - if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) - return; - if (!camel_imap_store_connected (imap_store, ex)) - return; - - response = camel_imap_command (imap_store, NULL, ex, - "SUBSCRIBE %F", folder_name); - if (!response) - return; - camel_imap_response_free (imap_store, response); - - si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, folder_name); - if (si) { - if ((si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) == 0) { - si->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; - camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); - camel_store_summary_save((CamelStoreSummary *)imap_store->summary); - } - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } - - if (imap_store->renaming) { - /* we don't need to emit a "folder_subscribed" signal - if we are in the process of renaming folders, so we - are done here... */ - return; - } - - fi = imap_build_folder_info(imap_store, folder_name); - camel_object_trigger_event (CAMEL_OBJECT (store), "folder_subscribed", fi); - camel_folder_info_free (fi); -} - -static void -unsubscribe_folder (CamelStore *store, const char *folder_name, - CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelImapResponse *response; - - if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) - return; - if (!camel_imap_store_connected (imap_store, ex)) - return; - - response = camel_imap_command (imap_store, NULL, ex, - "UNSUBSCRIBE %F", folder_name); - if (!response) - return; - camel_imap_response_free (imap_store, response); - - imap_folder_effectively_unsubscribed (imap_store, folder_name, ex); -} - -#if 0 -static gboolean -folder_flags_have_changed (CamelFolder *folder) -{ - CamelMessageInfo *info; - int i, max; - - max = camel_folder_summary_count (folder->summary); - for (i = 0; i < max; i++) { - info = camel_folder_summary_index (folder->summary, i); - if (!info) - continue; - if (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) { - return TRUE; - } - } - - return FALSE; -} -#endif - - -gboolean -camel_imap_store_connected (CamelImapStore *store, CamelException *ex) -{ - if (store->istream == NULL || !store->connected) - return camel_service_connect (CAMEL_SERVICE (store), ex); - return TRUE; -} - - -/* FIXME: please god, when will the hurting stop? Thus function is so - fucking broken it's not even funny. */ -ssize_t -camel_imap_store_readline (CamelImapStore *store, char **dest, CamelException *ex) -{ - CamelStreamBuffer *stream; - char linebuf[1024]; - GByteArray *ba; - ssize_t nread; - - g_return_val_if_fail (CAMEL_IS_IMAP_STORE (store), -1); - g_return_val_if_fail (dest, -1); - - *dest = NULL; - - /* Check for connectedness. Failed (or cancelled) operations will - * close the connection. We can't expect a read to have any - * meaning if we reconnect, so always set an exception. - */ - - if (!camel_imap_store_connected (store, ex)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_NOT_CONNECTED, - g_strerror (errno)); - return -1; - } - - stream = CAMEL_STREAM_BUFFER (store->istream); - - ba = g_byte_array_new (); - while ((nread = camel_stream_buffer_gets (stream, linebuf, sizeof (linebuf))) > 0) { - g_byte_array_append (ba, linebuf, nread); - if (linebuf[nread - 1] == '\n') - break; - } - - if (nread <= 0) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Server unexpectedly disconnected: %s"), - g_strerror (errno)); - - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - g_byte_array_free (ba, TRUE); - return -1; - } - - if (camel_verbose_debug) { - fprintf (stderr, "received: "); - fwrite (ba->data, 1, ba->len, stderr); - } - - /* camel-imap-command.c:imap_read_untagged expects the CRLFs - to be stripped off and be nul-terminated *sigh* */ - nread = ba->len - 1; - ba->data[nread] = '\0'; - if (ba->data[nread - 1] == '\r') { - ba->data[nread - 1] = '\0'; - nread--; - } - - *dest = ba->data; - g_byte_array_free (ba, FALSE); - - return nread; -} diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h deleted file mode 100644 index b45fb2110e..0000000000 --- a/camel/providers/imap/camel-imap-store.h +++ /dev/null @@ -1,148 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-store.h : class for an imap store */ - -/* - * Authors: Jeffrey Stedfast - * - * Copyright (C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAP_STORE_H -#define CAMEL_IMAP_STORE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include "camel-imap-types.h" -#include - -#ifdef ENABLE_THREADS -#include - -typedef struct _CamelImapMsg CamelImapMsg; - -struct _CamelImapMsg { - EMsg msg; - - void (*receive)(CamelImapStore *store, struct _CamelImapMsg *m); - void (*free)(CamelImapStore *store, struct _CamelImapMsg *m); -}; - -CamelImapMsg *camel_imap_msg_new(void (*receive)(CamelImapStore *store, struct _CamelImapMsg *m), - void (*free)(CamelImapStore *store, struct _CamelImapMsg *m), - size_t size); -void camel_imap_msg_queue(CamelImapStore *store, CamelImapMsg *msg); - -#endif - -#define CAMEL_IMAP_STORE_TYPE (camel_imap_store_get_type ()) -#define CAMEL_IMAP_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAP_STORE_TYPE, CamelImapStore)) -#define CAMEL_IMAP_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAP_STORE_TYPE, CamelImapStoreClass)) -#define CAMEL_IS_IMAP_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAP_STORE_TYPE)) - -enum { - CAMEL_IMAP_STORE_ARG_FIRST = CAMEL_DISCO_STORE_ARG_FIRST + 100, - CAMEL_IMAP_STORE_ARG_NAMESPACE, - CAMEL_IMAP_STORE_ARG_OVERRIDE_NAMESPACE, - CAMEL_IMAP_STORE_ARG_CHECK_ALL, - CAMEL_IMAP_STORE_ARG_FILTER_INBOX -}; - -#define CAMEL_IMAP_STORE_NAMESPACE (CAMEL_IMAP_STORE_ARG_NAMESPACE | CAMEL_ARG_STR) -#define CAMEL_IMAP_STORE_OVERRIDE_NAMESPACE (CAMEL_IMAP_STORE_ARG_OVERRIDE_NAMESPACE | CAMEL_ARG_INT) -#define CAMEL_IMAP_STORE_CHECK_ALL (CAMEL_IMAP_STORE_ARG_CHECK_ALL | CAMEL_ARG_INT) -#define CAMEL_IMAP_STORE_FILTER_INBOX (CAMEL_IMAP_STORE_ARG_FILTER_INBOX | CAMEL_ARG_INT) - -/* CamelFolderInfo flags */ -#define CAMEL_IMAP_FOLDER_MARKED (1<<16) -#define CAMEL_IMAP_FOLDER_UNMARKED (1<<17) -#define CAMEL_IMAP_FOLDER_NOCHILDREN (1<<18) - - -typedef enum { - IMAP_LEVEL_UNKNOWN, - IMAP_LEVEL_IMAP4, - IMAP_LEVEL_IMAP4REV1 -} CamelImapServerLevel; - -#define IMAP_CAPABILITY_IMAP4 (1 << 0) -#define IMAP_CAPABILITY_IMAP4REV1 (1 << 1) -#define IMAP_CAPABILITY_STATUS (1 << 2) -#define IMAP_CAPABILITY_NAMESPACE (1 << 3) -#define IMAP_CAPABILITY_UIDPLUS (1 << 4) -#define IMAP_CAPABILITY_LITERALPLUS (1 << 5) -#define IMAP_CAPABILITY_STARTTLS (1 << 6) -#define IMAP_CAPABILITY_useful_lsub (1 << 7) -#define IMAP_CAPABILITY_utf8_search (1 << 8) - -#define IMAP_PARAM_OVERRIDE_NAMESPACE (1 << 0) -#define IMAP_PARAM_CHECK_ALL (1 << 1) -#define IMAP_PARAM_FILTER_INBOX (1 << 2) - -struct _CamelImapStore { - CamelDiscoStore parent_object; - - CamelStream *istream; - CamelStream *ostream; - - struct _CamelImapStoreSummary *summary; - - /* Information about the command channel / connection status */ - gboolean connected; - gboolean preauthed; - char tag_prefix; - guint32 command; - CamelFolder *current_folder; - - /* Information about the server */ - CamelImapServerLevel server_level; - guint32 capabilities, parameters; - /* NB: namespace should be handled by summary->namespace */ - char *namespace, dir_sep, *base_url, *storage_path; - GHashTable *authtypes; - - gboolean renaming; - -#ifdef ENABLE_THREADS - EThread *async_thread; -#endif -}; - - -typedef struct { - CamelDiscoStoreClass parent_class; - -} CamelImapStoreClass; - - -/* Standard Camel function */ -CamelType camel_imap_store_get_type (void); - - -gboolean camel_imap_store_connected (CamelImapStore *store, CamelException *ex); - -ssize_t camel_imap_store_readline (CamelImapStore *store, char **dest, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_IMAP_STORE_H */ diff --git a/camel/providers/imap/camel-imap-summary.c b/camel/providers/imap/camel-imap-summary.c deleted file mode 100644 index dba1134fa1..0000000000 --- a/camel/providers/imap/camel-imap-summary.c +++ /dev/null @@ -1,255 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: - * Michael Zucchi - * Dan Winship - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include "camel-imap-summary.h" -#include "camel-file-utils.h" - -#define CAMEL_IMAP_SUMMARY_VERSION (0x300) - -static int summary_header_load (CamelFolderSummary *, FILE *); -static int summary_header_save (CamelFolderSummary *, FILE *); - -static CamelMessageInfo *message_info_load (CamelFolderSummary *s, FILE *in); -static int message_info_save (CamelFolderSummary *s, FILE *out, - CamelMessageInfo *info); -static CamelMessageContentInfo *content_info_load (CamelFolderSummary *s, FILE *in); -static int content_info_save (CamelFolderSummary *s, FILE *out, - CamelMessageContentInfo *info); - -static void camel_imap_summary_class_init (CamelImapSummaryClass *klass); -static void camel_imap_summary_init (CamelImapSummary *obj); - -static CamelFolderSummaryClass *camel_imap_summary_parent; - -CamelType -camel_imap_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register( - camel_folder_summary_get_type(), "CamelImapSummary", - sizeof (CamelImapSummary), - sizeof (CamelImapSummaryClass), - (CamelObjectClassInitFunc) camel_imap_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_imap_summary_init, - NULL); - } - - return type; -} - -static void -camel_imap_summary_class_init (CamelImapSummaryClass *klass) -{ - CamelFolderSummaryClass *cfs_class = (CamelFolderSummaryClass *) klass; - - camel_imap_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS (camel_type_get_global_classfuncs (camel_folder_summary_get_type())); - - cfs_class->summary_header_load = summary_header_load; - cfs_class->summary_header_save = summary_header_save; - cfs_class->message_info_load = message_info_load; - cfs_class->message_info_save = message_info_save; - cfs_class->content_info_load = content_info_load; - cfs_class->content_info_save = content_info_save; -} - -static void -camel_imap_summary_init (CamelImapSummary *obj) -{ - CamelFolderSummary *s = (CamelFolderSummary *)obj; - - /* subclasses need to set the right instance data sizes */ - s->message_info_size = sizeof(CamelImapMessageInfo); - s->content_info_size = sizeof(CamelImapMessageContentInfo); - - /* and a unique file version */ - s->version += CAMEL_IMAP_SUMMARY_VERSION; -} - -/** - * camel_imap_summary_new: - * @filename: the file to store the summary in. - * - * This will create a new CamelImapSummary object and read in the - * summary data from disk, if it exists. - * - * Return value: A new CamelImapSummary object. - **/ -CamelFolderSummary * -camel_imap_summary_new (const char *filename) -{ - CamelFolderSummary *summary = CAMEL_FOLDER_SUMMARY ( - camel_object_new (camel_imap_summary_get_type ())); - - camel_folder_summary_set_build_content (summary, TRUE); - camel_folder_summary_set_filename (summary, filename); - - if (camel_folder_summary_load (summary) == -1) { - camel_folder_summary_clear (summary); - camel_folder_summary_touch (summary); - } - - return summary; -} - - -static int -summary_header_load (CamelFolderSummary *s, FILE *in) -{ - CamelImapSummary *ims = CAMEL_IMAP_SUMMARY (s); - - if (camel_imap_summary_parent->summary_header_load (s, in) == -1) - return -1; - - return camel_file_util_decode_uint32 (in, &ims->validity); -} - -static int -summary_header_save (CamelFolderSummary *s, FILE *out) -{ - CamelImapSummary *ims = CAMEL_IMAP_SUMMARY(s); - - if (camel_imap_summary_parent->summary_header_save (s, out) == -1) - return -1; - - return camel_file_util_encode_uint32 (out, ims->validity); -} - - -static CamelMessageInfo * -message_info_load (CamelFolderSummary *s, FILE *in) -{ - CamelMessageInfo *info; - CamelImapMessageInfo *iinfo; - - info = camel_imap_summary_parent->message_info_load (s, in); - if (info) { - iinfo = (CamelImapMessageInfo *)info; - - if (camel_file_util_decode_uint32 (in, &iinfo->server_flags) == -1) - goto error; - } - - return info; -error: - camel_folder_summary_info_free (s, info); - return NULL; -} - -static int -message_info_save (CamelFolderSummary *s, FILE *out, CamelMessageInfo *info) -{ - CamelImapMessageInfo *iinfo = (CamelImapMessageInfo *)info; - - if (camel_imap_summary_parent->message_info_save (s, out, info) == -1) - return -1; - - return camel_file_util_encode_uint32 (out, iinfo->server_flags); -} - - -static CamelMessageContentInfo * -content_info_load (CamelFolderSummary *s, FILE *in) -{ - if (fgetc (in)) - return camel_imap_summary_parent->content_info_load (s, in); - else - return camel_folder_summary_content_info_new (s); -} - -static int -content_info_save (CamelFolderSummary *s, FILE *out, - CamelMessageContentInfo *info) -{ - if (info->type) { - fputc (1, out); - return camel_imap_summary_parent->content_info_save (s, out, info); - } else - return fputc (0, out); -} - -void -camel_imap_summary_add_offline (CamelFolderSummary *summary, const char *uid, - CamelMimeMessage *message, - const CamelMessageInfo *info) -{ - CamelMessageInfo *mi; - CamelFlag *flag; - CamelTag *tag; - - /* Create summary entry */ - mi = camel_folder_summary_info_new_from_message (summary, message); - - /* Copy flags 'n' tags */ - mi->flags = info->flags; - flag = info->user_flags; - while (flag) { - camel_flag_set (&mi->user_flags, flag->name, TRUE); - flag = flag->next; - } - tag = info->user_tags; - while (tag) { - camel_tag_set (&mi->user_tags, tag->name, tag->value); - tag = tag->next; - } - - /* Set uid and add to summary */ - camel_message_info_set_uid (mi, g_strdup (uid)); - camel_folder_summary_add (summary, mi); -} - -void -camel_imap_summary_add_offline_uncached (CamelFolderSummary *summary, const char *uid, - const CamelMessageInfo *info) -{ - CamelMessageInfo *mi; - CamelMessageContentInfo *ci; - - /* Create summary entry */ - mi = camel_folder_summary_info_new (summary); - ci = camel_folder_summary_content_info_new (summary); - - camel_message_info_dup_to (info, mi); - mi->content = ci; - - /* copy our private fields */ - ((CamelImapMessageInfo *)mi)->server_flags = - ((CamelImapMessageInfo *)info)->server_flags; - - /* Set uid and add to summary */ - camel_message_info_set_uid (mi, g_strdup (uid)); - camel_folder_summary_add (summary, mi); -} diff --git a/camel/providers/imap/camel-imap-summary.h b/camel/providers/imap/camel-imap-summary.h deleted file mode 100644 index 817e884408..0000000000 --- a/camel/providers/imap/camel-imap-summary.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: - * Michael Zucchi - * Dan Winship - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_IMAP_SUMMARY_H -#define _CAMEL_IMAP_SUMMARY_H - -#include "camel-imap-types.h" -#include -#include - -#define CAMEL_IMAP_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_imap_summary_get_type (), CamelImapSummary) -#define CAMEL_IMAP_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imap_summary_get_type (), CamelImapSummaryClass) -#define CAMEL_IS_IMAP_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_imap_summary_get_type ()) - -#define CAMEL_IMAP_SERVER_FLAGS (CAMEL_MESSAGE_ANSWERED | \ - CAMEL_MESSAGE_DELETED | \ - CAMEL_MESSAGE_DRAFT | \ - CAMEL_MESSAGE_FLAGGED | \ - CAMEL_MESSAGE_SEEN) - -#define CAMEL_IMAP_MESSAGE_RECENT (1 << 8) - -typedef struct _CamelImapSummaryClass CamelImapSummaryClass; - -typedef struct _CamelImapMessageContentInfo { - CamelMessageContentInfo info; - -} CamelImapMessageContentInfo; - -typedef struct _CamelImapMessageInfo { - CamelMessageInfo info; - - guint32 server_flags; -} CamelImapMessageInfo; - -struct _CamelImapSummary { - CamelFolderSummary parent; - - guint32 validity; -}; - -struct _CamelImapSummaryClass { - CamelFolderSummaryClass parent_class; - -}; - -CamelType camel_imap_summary_get_type (void); -CamelFolderSummary *camel_imap_summary_new (const char *filename); - -void camel_imap_summary_add_offline (CamelFolderSummary *summary, - const char *uid, - CamelMimeMessage *message, - const CamelMessageInfo *info); - -void camel_imap_summary_add_offline_uncached (CamelFolderSummary *summary, - const char *uid, - const CamelMessageInfo *info); - -#endif /* ! _CAMEL_IMAP_SUMMARY_H */ - diff --git a/camel/providers/imap/camel-imap-types.h b/camel/providers/imap/camel-imap-types.h deleted file mode 100644 index c5ea41acff..0000000000 --- a/camel/providers/imap/camel-imap-types.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-types.h: IMAP types */ - -/* - * Copyright (C) 2001 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_IMAP_TYPES_H -#define CAMEL_IMAP_TYPES_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-types.h" - -typedef struct _CamelImapFolder CamelImapFolder; -typedef struct _CamelImapMessageCache CamelImapMessageCache; -typedef struct _CamelImapResponse CamelImapResponse; -typedef struct _CamelImapSearch CamelImapSearch; -typedef struct _CamelImapStore CamelImapStore; -typedef struct _CamelImapSummary CamelImapSummary; - -#endif /* CAMEL_IMAP_TYPES_H */ diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c deleted file mode 100644 index 879cc23cca..0000000000 --- a/camel/providers/imap/camel-imap-utils.c +++ /dev/null @@ -1,1261 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "camel-imap-utils.h" -#include "camel-imap-summary.h" -#include "camel-imap-store.h" -#include "camel-folder.h" -#include "camel-string-utils.h" -#include "camel-utf8.h" - -#define d(x) - -const char * -imap_next_word (const char *buf) -{ - const char *word; - - /* skip over current word */ - word = buf; - while (*word && *word != ' ') - word++; - - /* skip over white space */ - while (*word && *word == ' ') - word++; - - return word; -} - - -static void -imap_namespace_destroy (struct _namespace *namespace) -{ - struct _namespace *node, *next; - - node = namespace; - while (node) { - next = node->next; - g_free (node->prefix); - g_free (node); - node = next; - } -} - -void -imap_namespaces_destroy (struct _namespaces *namespaces) -{ - if (namespaces) { - imap_namespace_destroy (namespaces->personal); - imap_namespace_destroy (namespaces->other); - imap_namespace_destroy (namespaces->shared); - g_free (namespaces); - } -} - -static gboolean -imap_namespace_decode (const char **in, struct _namespace **namespace) -{ - struct _namespace *list, *tail, *node; - const char *inptr; - char *astring; - size_t len; - - inptr = *in; - - list = NULL; - tail = (struct _namespace *) &list; - - if (strncasecmp (inptr, "NIL", 3) != 0) { - if (*inptr++ != '(') - goto exception; - - while (*inptr && *inptr != ')') { - if (*inptr++ != '(') - goto exception; - - node = g_new (struct _namespace, 1); - node->next = NULL; - - /* get the namespace prefix */ - astring = imap_parse_astring (&inptr, &len); - if (!astring) { - g_free (node); - goto exception; - } - - /* decode IMAP's modified UTF-7 into UTF-8 */ - node->prefix = imap_mailbox_decode (astring, len); - g_free (astring); - if (!node->prefix) { - g_free (node); - goto exception; - } - - tail->next = node; - tail = node; - - /* get the namespace directory delimiter */ - inptr = imap_next_word (inptr); - - if (!strncasecmp (inptr, "NIL", 3)) { - inptr = imap_next_word (inptr); - node->delim = '\0'; - } else if (*inptr++ == '"') { - if (*inptr == '\\') - inptr++; - - node->delim = *inptr++; - - if (*inptr++ != '"') - goto exception; - } else - goto exception; - - if (*inptr == ' ') { - /* parse extra flags... for now we - don't save them, but in the future - we may want to? */ - while (*inptr == ' ') - inptr++; - - while (*inptr && *inptr != ')') { - /* this should be a QSTRING or ATOM */ - inptr = imap_next_word (inptr); - if (*inptr == '(') { - /* skip over the param list */ - imap_skip_list (&inptr); - } - - while (*inptr == ' ') - inptr++; - } - } - - if (*inptr++ != ')') - goto exception; - - /* there shouldn't be spaces according to the - ABNF grammar, but we all know how closely - people follow specs */ - while (*inptr == ' ') - inptr++; - } - - if (*inptr == ')') - inptr++; - } else { - inptr += 3; - } - - *in = inptr; - *namespace = list; - - return TRUE; - - exception: - - /* clean up any namespaces we may have allocated */ - imap_namespace_destroy (list); - - return FALSE; -} - -#if d(!)0 -static void -namespace_dump (struct _namespace *namespace) -{ - struct _namespace *node; - - if (namespace) { - printf ("("); - node = namespace; - while (node) { - printf ("(\"%s\" ", node->prefix); - if (node->delim) - printf ("\"%c\")", node->delim); - else - printf ("NUL)"); - - node = node->next; - if (node) - printf (" "); - } - - printf (")"); - } else { - printf ("NIL"); - } -} - -static void -namespaces_dump (struct _namespaces *namespaces) -{ - printf ("namespace dump: "); - namespace_dump (namespaces->personal); - printf (" "); - namespace_dump (namespaces->other); - printf (" "); - namespace_dump (namespaces->shared); - printf ("\n"); -} -#endif - -struct _namespaces * -imap_parse_namespace_response (const char *response) -{ - struct _namespaces *namespaces; - const char *inptr; - - d(printf ("parsing: %s\n", response)); - - if (*response != '*') - return NULL; - - inptr = imap_next_word (response); - if (strncasecmp (inptr, "NAMESPACE", 9) != 0) - return NULL; - - inptr = imap_next_word (inptr); - - namespaces = g_new (struct _namespaces, 1); - namespaces->personal = NULL; - namespaces->other = NULL; - namespaces->shared = NULL; - - if (!imap_namespace_decode (&inptr, &namespaces->personal)) - goto exception; - - if (*inptr != ' ') - goto exception; - - while (*inptr == ' ') - inptr++; - - if (!imap_namespace_decode (&inptr, &namespaces->other)) - goto exception; - - if (*inptr != ' ') - goto exception; - - while (*inptr == ' ') - inptr++; - - if (!imap_namespace_decode (&inptr, &namespaces->shared)) - goto exception; - - d(namespaces_dump (namespaces)); - - return namespaces; - - exception: - - imap_namespaces_destroy (namespaces); - - return NULL; -} - -/** - * imap_parse_list_response: - * @store: the IMAP store whose list response we're parsing - * @buf: the LIST or LSUB response - * @flags: a pointer to a variable to store the flags in, or %NULL - * @sep: a pointer to a variable to store the hierarchy separator in, or %NULL - * @folder: a pointer to a variable to store the folder name in, or %NULL - * - * Parses a LIST or LSUB response and returns the desired parts of it. - * If @folder is non-%NULL, its value must be freed by the caller. - * - * Return value: whether or not the response was successfully parsed. - **/ -gboolean -imap_parse_list_response (CamelImapStore *store, const char *buf, int *flags, char *sep, char **folder) -{ - gboolean is_lsub = FALSE; - const char *word; - size_t len; - - if (*buf != '*') - return FALSE; - - word = imap_next_word (buf); - if (strncasecmp (word, "LIST", 4) && strncasecmp (word, "LSUB", 4)) - return FALSE; - - /* check if we are looking at an LSUB response */ - if (word[1] == 'S' || word[1] == 's') - is_lsub = TRUE; - - /* get the flags */ - word = imap_next_word (word); - if (*word != '(') - return FALSE; - - if (flags) - *flags = 0; - - word++; - while (*word != ')') { - len = strcspn (word, " )"); - if (flags) { - if (!strncasecmp (word, "\\NoInferiors", len)) - *flags |= CAMEL_FOLDER_NOINFERIORS; - else if (!strncasecmp (word, "\\NoSelect", len)) - *flags |= CAMEL_FOLDER_NOSELECT; - else if (!strncasecmp (word, "\\Marked", len)) - *flags |= CAMEL_IMAP_FOLDER_MARKED; - else if (!strncasecmp (word, "\\Unmarked", len)) - *flags |= CAMEL_IMAP_FOLDER_UNMARKED; - else if (!strncasecmp (word, "\\HasChildren", len)) - *flags |= CAMEL_FOLDER_CHILDREN; - else if (!strncasecmp (word, "\\HasNoChildren", len)) - *flags |= CAMEL_IMAP_FOLDER_NOCHILDREN; - } - - word += len; - while (*word == ' ') - word++; - } - - /* get the directory separator */ - word = imap_next_word (word); - if (!strncmp (word, "NIL", 3)) { - if (sep) - *sep = '\0'; - } else if (*word++ == '"') { - if (*word == '\\') - word++; - if (sep) - *sep = *word; - word++; - if (*word++ != '"') - return FALSE; - } else - return FALSE; - - if (folder) { - char *astring; - - /* get the folder name */ - word = imap_next_word (word); - astring = imap_parse_astring (&word, &len); - if (!astring) - return FALSE; - - *folder = astring; -#if 0 - char *mailbox; - - mailbox = imap_mailbox_decode (astring, strlen (astring)); - g_free (astring); - if (!mailbox) - return FALSE; - - /* Kludge around Courier imap's LSUB response for INBOX when it - * isn't subscribed to. - * - * Ignore any \Noselect flags for INBOX when parsing - * an LSUB response to work around the following response: - * - * * LSUB (\Noselect \HasChildren) "." "INBOX" - * - * Fixes bug #28929 (albeight in a very dodgy way imho, but what - * can ya do when ya got the ignorance of marketing breathing - * down your neck?) - */ - if (is_lsub && flags && !strcasecmp (mailbox, "INBOX")) - *flags &= ~CAMEL_FOLDER_NOSELECT; - - *folder = mailbox; -#endif - } - - return TRUE; -} - - -/** - * imap_parse_folder_name: - * @store: - * @folder_name: - * - * Return an array of folder paths representing the folder heirarchy. - * For example: - * Full/Path/"to / from"/Folder - * Results in: - * Full, Full/Path, Full/Path/"to / from", Full/Path/"to / from"/Folder - **/ -char ** -imap_parse_folder_name (CamelImapStore *store, const char *folder_name) -{ - GPtrArray *heirarchy; - char **paths; - const char *p; - - p = folder_name; - if (*p == store->dir_sep) - p++; - - heirarchy = g_ptr_array_new (); - - while (*p) { - if (*p == '"') { - p++; - while (*p && *p != '"') - p++; - if (*p) - p++; - continue; - } - - if (*p == store->dir_sep) - g_ptr_array_add (heirarchy, g_strndup (folder_name, p - folder_name)); - - p++; - } - - g_ptr_array_add (heirarchy, g_strdup (folder_name)); - g_ptr_array_add (heirarchy, NULL); - - paths = (char **) heirarchy->pdata; - g_ptr_array_free (heirarchy, FALSE); - - return paths; -} - -char * -imap_create_flag_list (guint32 flags) -{ - GString *gstr; - char *flag_list; - - gstr = g_string_new ("("); - - if (flags & CAMEL_MESSAGE_ANSWERED) - g_string_append (gstr, "\\Answered "); - if (flags & CAMEL_MESSAGE_DELETED) - g_string_append (gstr, "\\Deleted "); - if (flags & CAMEL_MESSAGE_DRAFT) - g_string_append (gstr, "\\Draft "); - if (flags & CAMEL_MESSAGE_FLAGGED) - g_string_append (gstr, "\\Flagged "); - if (flags & CAMEL_MESSAGE_SEEN) - g_string_append (gstr, "\\Seen "); - - if (gstr->str[gstr->len - 1] == ' ') - gstr->str[gstr->len - 1] = ')'; - else - g_string_append_c (gstr, ')'); - - flag_list = gstr->str; - g_string_free (gstr, FALSE); - return flag_list; -} - -guint32 -imap_parse_flag_list (char **flag_list_p) -{ - char *flag_list = *flag_list_p; - guint32 flags = 0; - int len; - - if (*flag_list++ != '(') { - *flag_list_p = NULL; - return 0; - } - - while (*flag_list && *flag_list != ')') { - len = strcspn (flag_list, " )"); - if (!strncasecmp (flag_list, "\\Answered", len)) - flags |= CAMEL_MESSAGE_ANSWERED; - else if (!strncasecmp (flag_list, "\\Deleted", len)) - flags |= CAMEL_MESSAGE_DELETED; - else if (!strncasecmp (flag_list, "\\Draft", len)) - flags |= CAMEL_MESSAGE_DRAFT; - else if (!strncasecmp (flag_list, "\\Flagged", len)) - flags |= CAMEL_MESSAGE_FLAGGED; - else if (!strncasecmp (flag_list, "\\Seen", len)) - flags |= CAMEL_MESSAGE_SEEN; - else if (!strncasecmp (flag_list, "\\Recent", len)) - flags |= CAMEL_IMAP_MESSAGE_RECENT; - - flag_list += len; - if (*flag_list == ' ') - flag_list++; - } - - if (*flag_list++ != ')') { - *flag_list_p = NULL; - return 0; - } - - *flag_list_p = flag_list; - return flags; -} - -/* - From rfc2060 - -ATOM_CHAR ::= - -atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / - quoted_specials - -CHAR ::= - -CTL ::= - -SPACE ::= - -list_wildcards ::= "%" / "*" - -quoted_specials ::= <"> / "\" -*/ - -static unsigned char imap_atom_specials[256] = { -/* 00 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 10 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 20 */0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, -/* 30 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* 40 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* 50 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, -/* 60 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* 70 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 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, 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, 0, 0, 0, -}; - -#define imap_is_atom_char(c) ((imap_atom_specials[(c)&0xff] & 0x01) != 0) - -gboolean -imap_is_atom(const char *in) -{ - register unsigned char c; - register const char *p = in; - - while ((c = (unsigned char)*p)) { - if (!imap_is_atom_char(c)) - return FALSE; - p++; - } - - /* check for empty string */ - return p!=in; -} - -/** - * imap_parse_string_generic: - * @str_p: a pointer to a string - * @len: a pointer to a size_t to return the length in - * @type: type of string (#IMAP_STRING, #IMAP_ASTRING, or #IMAP_NSTRING) - * to parse. - * - * This parses an IMAP "string" (quoted string or literal), "nstring" - * (NIL or string), or "astring" (atom or string) starting at *@str_p. - * On success, *@str_p will point to the first character after the end - * of the string, and *@len will contain the length of the returned - * string. On failure, *@str_p will be set to %NULL. - * - * This assumes that the string is in the form returned by - * camel_imap_command(): that line breaks are indicated by LF rather - * than CRLF. - * - * Return value: the parsed string, or %NULL if a NIL or no string - * was parsed. (In the former case, *@str_p will be %NULL; in the - * latter, it will point to the character after the NIL.) - **/ -char * -imap_parse_string_generic (const char **str_p, size_t *len, int type) -{ - const char *str = *str_p; - char *out; - - if (!str) - return NULL; - else if (*str == '"') { - char *p; - size_t size; - - str++; - size = strcspn (str, "\"") + 1; - p = out = g_malloc (size); - - /* a quoted string cannot be broken into multiple lines */ - while (*str && *str != '"' && *str != '\n') { - if (*str == '\\') - str++; - *p++ = *str++; - if (p - out == size) { - out = g_realloc (out, size * 2); - p = out + size; - size *= 2; - } - } - if (*str != '"') { - *str_p = NULL; - g_free (out); - return NULL; - } - *p = '\0'; - *str_p = str + 1; - *len = strlen (out); - return out; - } else if (*str == '{') { - *len = strtoul (str + 1, (char **)&str, 10); - if (*str++ != '}' || *str++ != '\n' || strlen (str) < *len) { - *str_p = NULL; - return NULL; - } - - out = g_strndup (str, *len); - *str_p = str + *len; - return out; - } else if (type == IMAP_NSTRING && !strncasecmp (str, "nil", 3)) { - *str_p += 3; - *len = 0; - return NULL; - } else if (type == IMAP_ASTRING && imap_is_atom_char ((unsigned char)*str)) { - while (imap_is_atom_char ((unsigned char) *str)) - str++; - - *len = str - *str_p; - out = g_strndup (*str_p, *len); - *str_p += *len; - return out; - } else { - *str_p = NULL; - return NULL; - } -} - -static inline void -skip_char (const char **in, char ch) -{ - if (*in && **in == ch) - *in = *in + 1; - else - *in = NULL; -} - -/* Skip atom, string, or number */ -static void -skip_asn (const char **str_p) -{ - const char *str = *str_p; - - if (!str) - return; - else if (*str == '"') { - while (*++str && *str != '"') { - if (*str == '\\') { - str++; - if (!*str) - break; - } - } - if (*str == '"') - *str_p = str + 1; - else - *str_p = NULL; - } else if (*str == '{') { - unsigned long len; - - len = strtoul (str + 1, (char **) &str, 10); - if (*str != '}' || *(str + 1) != '\n' || - strlen (str + 2) < len) { - *str_p = NULL; - return; - } - *str_p = str + 2 + len; - } else { - /* We assume the string is well-formed and don't - * bother making sure it's a valid atom. - */ - while (*str && *str != ')' && *str != ' ') - str++; - *str_p = str; - } -} - -void -imap_skip_list (const char **str_p) -{ - skip_char (str_p, '('); - while (*str_p && **str_p != ')') { - if (**str_p == '(') - imap_skip_list (str_p); - else - skip_asn (str_p); - if (*str_p && **str_p == ' ') - skip_char (str_p, ' '); - } - skip_char (str_p, ')'); -} - -static int -parse_params (const char **parms_p, CamelContentType *type) -{ - const char *parms = *parms_p; - char *name, *value; - size_t len; - - if (!strncasecmp (parms, "nil", 3)) { - *parms_p += 3; - return 0; - } - - if (*parms++ != '(') - return -1; - - while (parms && *parms != ')') { - name = imap_parse_nstring (&parms, &len); - skip_char (&parms, ' '); - value = imap_parse_nstring (&parms, &len); - - if (name && value) - camel_content_type_set_param (type, name, value); - g_free (name); - g_free (value); - - if (parms && *parms == ' ') - parms++; - } - - if (!parms || *parms++ != ')') - return -1; - - *parms_p = parms; - - return 0; -} - - -static CamelMessageContentInfo * -imap_body_decode (const char **in, CamelMessageContentInfo *ci, CamelFolder *folder, GPtrArray *cis) -{ - const char *inptr = *in; - CamelMessageContentInfo *child = NULL; - char *type, *subtype, *id = NULL; - CamelContentType *ctype = NULL; - char *description = NULL; - char *encoding = NULL; - size_t len; - size_t size; - char *p; - - if (*inptr++ != '(') - return NULL; - - if (ci == NULL) { - ci = camel_folder_summary_content_info_new (folder->summary); - g_ptr_array_add (cis, ci); - } - - if (*inptr == '(') { - /* body_type_mpart */ - CamelMessageContentInfo *tail, *children = NULL; - - tail = (CamelMessageContentInfo *) &children; - - do { - if (!(child = imap_body_decode (&inptr, NULL, folder, cis))) - return NULL; - - child->parent = ci; - tail->next = child; - tail = child; - } while (*inptr == '('); - - if (*inptr++ != ' ') - return NULL; - - if (!strncasecmp (inptr, "nil", 3) != 0) { - subtype = imap_parse_string (&inptr, &len); - } else { - subtype = NULL; - inptr += 3; - } - - ctype = camel_content_type_new ("multipart", subtype ? subtype : "mixed"); - g_free (subtype); - - if (*inptr++ != ')') { - camel_content_type_unref (ctype); - return NULL; - } - - ci->type = ctype; - ci->childs = children; - } else { - /* body_type_1part */ - if (strncasecmp (inptr, "nil", 3) != 0) { - type = imap_parse_string (&inptr, &len); - if (inptr == NULL) - return NULL; - } else { - return NULL; - } - - if (*inptr++ != ' ') { - g_free (type); - return NULL; - } - - if (strncasecmp (inptr, "nil", 3) != 0) { - subtype = imap_parse_string (&inptr, &len); - if (inptr == NULL) { - g_free (type); - return NULL; - } - } else { - if (!strcasecmp (type, "text")) - subtype = g_strdup ("plain"); - else - subtype = NULL; - inptr += 3; - } - - camel_strdown (type); - camel_strdown (subtype); - ctype = camel_content_type_new (type, subtype); - g_free (subtype); - g_free (type); - - if (*inptr++ != ' ') - goto exception; - - /* content-type params */ - if (parse_params (&inptr, ctype) == -1) - goto exception; - - if (*inptr++ != ' ') - goto exception; - - /* content-id */ - if (strncasecmp (inptr, "nil", 3) != 0) { - id = imap_parse_string (&inptr, &len); - if (inptr == NULL) - goto exception; - } else - inptr += 3; - - if (*inptr++ != ' ') - goto exception; - - /* description */ - if (strncasecmp (inptr, "nil", 3) != 0) { - description = imap_parse_string (&inptr, &len); - if (inptr == NULL) - goto exception; - } else - inptr += 3; - - if (*inptr++ != ' ') - goto exception; - - /* encoding */ - if (strncasecmp (inptr, "nil", 3) != 0) { - encoding = imap_parse_string (&inptr, &len); - if (inptr == NULL) - goto exception; - } else - inptr += 3; - - if (*inptr++ != ' ') - goto exception; - - /* size */ - size = strtoul ((const char *) inptr, &p, 10); - inptr = (const unsigned char *) p; - - if (camel_content_type_is (ctype, "message", "rfc822")) { - /* body_type_msg */ - if (*inptr++ != ' ') - goto exception; - - /* envelope */ - imap_skip_list (&inptr); - - if (*inptr++ != ' ') - goto exception; - - /* body */ - if (!(child = imap_body_decode (&inptr, NULL, folder, cis))) - goto exception; - child->parent = ci; - - if (*inptr++ != ' ') - goto exception; - - /* lines */ - strtoul ((const char *) inptr, &p, 10); - inptr = (const unsigned char *) p; - } else if (camel_content_type_is (ctype, "text", "*")) { - if (*inptr++ != ' ') - goto exception; - - /* lines */ - strtoul ((const char *) inptr, &p, 10); - inptr = (const unsigned char *) p; - } else { - /* body_type_basic */ - } - - if (*inptr++ != ')') - goto exception; - - ci->type = ctype; - ci->id = id; - ci->description = description; - ci->encoding = encoding; - ci->size = size; - ci->childs = child; - } - - *in = inptr; - - return ci; - - exception: - - camel_content_type_unref (ctype); - g_free (id); - g_free (description); - g_free (encoding); - - return NULL; -} - - -/** - * imap_parse_body: - * @body_p: pointer to the start of an IMAP "body" - * @folder: an imap folder - * @ci: a CamelMessageContentInfo to fill in - * - * This fills in @ci with data from *@body_p. On success *@body_p - * will point to the character after the body. On failure, it will be - * set to %NULL and @ci will be unchanged. - **/ -void -imap_parse_body (const char **body_p, CamelFolder *folder, - CamelMessageContentInfo *ci) -{ - const char *inptr = *body_p; - CamelMessageContentInfo *child; - GPtrArray *children; - int i; - - if (!inptr || *inptr != '(') { - *body_p = NULL; - return; - } - - children = g_ptr_array_new (); - - if (!(imap_body_decode (&inptr, ci, folder, children))) { - for (i = 0; i < children->len; i++) { - child = children->pdata[i]; - - /* content_info_free will free all the child - * nodes, but we don't want that. */ - child->next = NULL; - child->parent = NULL; - child->childs = NULL; - - camel_folder_summary_content_info_free (folder->summary, child); - } - *body_p = NULL; - } else { - *body_p = inptr; - } - - g_ptr_array_free (children, TRUE); -} - - -/** - * imap_quote_string: - * @str: the string to quote, which must not contain CR or LF - * - * Return value: an IMAP "quoted" corresponding to the string, which - * the caller must free. - **/ -char * -imap_quote_string (const char *str) -{ - const char *p; - char *quoted, *q; - int len; - - g_assert (strchr (str, '\r') == NULL); - - len = strlen (str); - p = str; - while ((p = strpbrk (p, "\"\\"))) { - len++; - p++; - } - - quoted = q = g_malloc (len + 3); - *q++ = '"'; - for (p = str; *p; ) { - if (strchr ("\"\\", *p)) - *q++ = '\\'; - *q++ = *p++; - } - *q++ = '"'; - *q = '\0'; - - return quoted; -} - - -static inline unsigned long -get_summary_uid_numeric (CamelFolderSummary *summary, int index) -{ - CamelMessageInfo *info; - unsigned long uid; - - info = camel_folder_summary_index (summary, index); - uid = strtoul (camel_message_info_uid (info), NULL, 10); - camel_folder_summary_info_free (summary, info); - return uid; -} - -/* the max number of chars that an unsigned 32-bit int can be is 10 chars plus 1 for a possible : */ -#define UID_SET_FULL(setlen, maxlen) (maxlen > 0 ? setlen + 11 >= maxlen : FALSE) - -/** - * imap_uid_array_to_set: - * @summary: summary for the folder the UIDs come from - * @uids: a (sorted) array of UIDs - * @uid: uid index to start at - * @maxlen: max length of the set string (or -1 for infinite) - * @lastuid: index offset of the last uid used - * - * Creates an IMAP "set" up to @maxlen bytes long, covering the listed - * UIDs starting at index @uid and not covering any UIDs that are in - * @summary but not in @uids. It doesn't actually require that all (or - * any) of the UIDs be in @summary. - * - * After calling, @lastuid will be set the index of the first uid - * *not* included in the returned set string. - * - * Note: @uids MUST be in sorted order for this code to work properly. - * - * Return value: the set, which the caller must free with g_free() - **/ -char * -imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids, int uid, ssize_t maxlen, int *lastuid) -{ - unsigned long last_uid, next_summary_uid, this_uid; - gboolean range = FALSE; - int si, scount; - GString *gset; - char *set; - - g_return_val_if_fail (uids->len > uid, NULL); - - gset = g_string_new (uids->pdata[uid]); - last_uid = strtoul (uids->pdata[uid], NULL, 10); - next_summary_uid = 0; - scount = camel_folder_summary_count (summary); - - for (uid++, si = 0; uid < uids->len && !UID_SET_FULL (gset->len, maxlen); uid++) { - /* Find the next UID in the summary after the one we - * just wrote out. - */ - for ( ; last_uid >= next_summary_uid && si < scount; si++) - next_summary_uid = get_summary_uid_numeric (summary, si); - if (last_uid >= next_summary_uid) - next_summary_uid = (unsigned long) -1; - - /* Now get the next UID from @uids */ - this_uid = strtoul (uids->pdata[uid], NULL, 10); - if (this_uid == next_summary_uid || this_uid == last_uid + 1) - range = TRUE; - else { - if (range) { - g_string_append_printf (gset, ":%lu", last_uid); - range = FALSE; - } - g_string_append_printf (gset, ",%lu", this_uid); - } - - last_uid = this_uid; - } - - if (range) - g_string_append_printf (gset, ":%lu", last_uid); - - *lastuid = uid; - - set = gset->str; - g_string_free (gset, FALSE); - - return set; -} - -/** - * imap_uid_set_to_array: - * @summary: summary for the folder the UIDs come from - * @uids: a pointer to the start of an IMAP "set" of UIDs - * - * Fills an array with the UIDs corresponding to @uids and @summary. - * There can be text after the uid set in @uids, which will be - * ignored. - * - * If @uids specifies a range of UIDs that extends outside the range - * of @summary, the function will assume that all of the "missing" UIDs - * do exist. - * - * Return value: the array of uids, which the caller must free with - * imap_uid_array_free(). (Or %NULL if the uid set can't be parsed.) - **/ -GPtrArray * -imap_uid_set_to_array (CamelFolderSummary *summary, const char *uids) -{ - GPtrArray *arr; - char *p, *q; - unsigned long uid, suid; - int si, scount; - - arr = g_ptr_array_new (); - scount = camel_folder_summary_count (summary); - - p = (char *)uids; - si = 0; - do { - uid = strtoul (p, &q, 10); - if (p == q) - goto lose; - g_ptr_array_add (arr, g_strndup (p, q - p)); - - if (*q == ':') { - /* Find the summary entry for the UID after the one - * we just saw. - */ - while (++si < scount) { - suid = get_summary_uid_numeric (summary, si); - if (suid > uid) - break; - } - if (si >= scount) - suid = uid + 1; - - uid = strtoul (q + 1, &p, 10); - if (p == q + 1) - goto lose; - - /* Add each summary UID until we find one - * larger than the end of the range - */ - while (suid <= uid) { - g_ptr_array_add (arr, g_strdup_printf ("%lu", suid)); - if (++si < scount) - suid = get_summary_uid_numeric (summary, si); - else - suid++; - } - } else - p = q; - } while (*p++ == ','); - - return arr; - - lose: - g_warning ("Invalid uid set %s", uids); - imap_uid_array_free (arr); - return NULL; -} - -/** - * imap_uid_array_free: - * @arr: an array returned from imap_uid_set_to_array() - * - * Frees @arr - **/ -void -imap_uid_array_free (GPtrArray *arr) -{ - int i; - - for (i = 0; i < arr->len; i++) - g_free (arr->pdata[i]); - g_ptr_array_free (arr, TRUE); -} - -char * -imap_concat (CamelImapStore *imap_store, const char *prefix, const char *suffix) -{ - size_t len; - - len = strlen (prefix); - if (len == 0 || prefix[len - 1] == imap_store->dir_sep) - return g_strdup_printf ("%s%s", prefix, suffix); - else - return g_strdup_printf ("%s%c%s", prefix, imap_store->dir_sep, suffix); -} - -char * -imap_mailbox_encode (const unsigned char *in, size_t inlen) -{ - char *buf; - - buf = g_alloca (inlen + 1); - memcpy (buf, in, inlen); - buf[inlen] = 0; - - return camel_utf8_utf7 (buf); -} - -char * -imap_mailbox_decode (const unsigned char *in, size_t inlen) -{ - char *buf; - - buf = g_alloca (inlen + 1); - memcpy (buf, in, inlen); - buf[inlen] = 0; - - return camel_utf7_utf8 (buf); -} diff --git a/camel/providers/imap/camel-imap-utils.h b/camel/providers/imap/camel-imap-utils.h deleted file mode 100644 index e8f570137f..0000000000 --- a/camel/providers/imap/camel-imap-utils.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef CAMEL_IMAP_UTILS_H -#define CAMEL_IMAP_UTILS_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include - -#include "camel-folder-summary.h" -#include "camel-imap-types.h" - -const char *imap_next_word (const char *buf); - -struct _namespace { - struct _namespace *next; - char *prefix; - char delim; -}; - -struct _namespaces { - struct _namespace *personal; - struct _namespace *other; - struct _namespace *shared; -}; - -void imap_namespaces_destroy (struct _namespaces *namespaces); -struct _namespaces *imap_parse_namespace_response (const char *response); - -gboolean imap_parse_list_response (CamelImapStore *store, const char *buf, int *flags, - char *sep, char **folder); - -char **imap_parse_folder_name (CamelImapStore *store, const char *folder_name); - -char *imap_create_flag_list (guint32 flags); -guint32 imap_parse_flag_list (char **flag_list); - - -enum { IMAP_STRING, IMAP_NSTRING, IMAP_ASTRING }; - -char *imap_parse_string_generic (const char **str_p, size_t *len, int type); - -#define imap_parse_string(str_p, len_p) \ - imap_parse_string_generic (str_p, len_p, IMAP_STRING) -#define imap_parse_nstring(str_p, len_p) \ - imap_parse_string_generic (str_p, len_p, IMAP_NSTRING) -#define imap_parse_astring(str_p, len_p) \ - imap_parse_string_generic (str_p, len_p, IMAP_ASTRING) - -void imap_parse_body (const char **body_p, CamelFolder *folder, - CamelMessageContentInfo *ci); - -gboolean imap_is_atom (const char *in); -char *imap_quote_string (const char *str); - -void imap_skip_list (const char **str_p); - -char *imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids, int uid, ssize_t maxlen, int *lastuid); -GPtrArray *imap_uid_set_to_array (CamelFolderSummary *summary, const char *uids); -void imap_uid_array_free (GPtrArray *arr); - -char *imap_concat (CamelImapStore *imap_store, const char *prefix, const char *suffix); -char *imap_namespace_concat (CamelImapStore *store, const char *name); - -char *imap_mailbox_encode (const unsigned char *in, size_t inlen); -char *imap_mailbox_decode (const unsigned char *in, size_t inlen); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_IMAP_UTILS_H */ diff --git a/camel/providers/imap/camel-imap-wrapper.c b/camel/providers/imap/camel-imap-wrapper.c deleted file mode 100644 index 2cb07b3012..0000000000 --- a/camel/providers/imap/camel-imap-wrapper.c +++ /dev/null @@ -1,185 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; -*- */ -/* camel-imap-wrapper.c: data wrapper for offline IMAP data */ - -/* - * Author: Dan Winship - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "camel-imap-folder.h" -#include "camel-imap-wrapper.h" -#include "camel-imap-private.h" -#include "camel-exception.h" -#include "camel-stream-filter.h" -#include "camel-mime-filter-basic.h" -#include "camel-mime-filter-crlf.h" -#include "camel-mime-filter-charset.h" -#include "camel-mime-part.h" - -static CamelDataWrapperClass *parent_class = NULL; - -/* Returns the class for a CamelDataWrapper */ -#define CDW_CLASS(so) CAMEL_DATA_WRAPPER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static ssize_t write_to_stream (CamelDataWrapper *imap_wrapper, CamelStream *stream); - -static void -camel_imap_wrapper_class_init (CamelImapWrapperClass *camel_imap_wrapper_class) -{ - CamelDataWrapperClass *camel_data_wrapper_class = - CAMEL_DATA_WRAPPER_CLASS (camel_imap_wrapper_class); - - parent_class = CAMEL_DATA_WRAPPER_CLASS (camel_type_get_global_classfuncs (camel_data_wrapper_get_type ())); - - /* virtual method override */ - camel_data_wrapper_class->write_to_stream = write_to_stream; -} - -static void -camel_imap_wrapper_finalize (CamelObject *object) -{ - CamelImapWrapper *imap_wrapper = CAMEL_IMAP_WRAPPER (object); - - if (imap_wrapper->folder) - camel_object_unref (CAMEL_OBJECT (imap_wrapper->folder)); - if (imap_wrapper->uid) - g_free (imap_wrapper->uid); - if (imap_wrapper->part) - g_free (imap_wrapper->part_spec); - -#ifdef ENABLE_THREADS - g_mutex_free (imap_wrapper->priv->lock); -#endif - g_free (imap_wrapper->priv); -} - -static void -camel_imap_wrapper_init (gpointer object, gpointer klass) -{ - CamelImapWrapper *imap_wrapper = CAMEL_IMAP_WRAPPER (object); - - imap_wrapper->priv = g_new0 (struct _CamelImapWrapperPrivate, 1); -#ifdef ENABLE_THREADS - imap_wrapper->priv->lock = g_mutex_new (); -#endif -} - -CamelType -camel_imap_wrapper_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register ( - CAMEL_DATA_WRAPPER_TYPE, - "CamelImapWrapper", - sizeof (CamelImapWrapper), - sizeof (CamelImapWrapperClass), - (CamelObjectClassInitFunc) camel_imap_wrapper_class_init, - NULL, - (CamelObjectInitFunc) camel_imap_wrapper_init, - (CamelObjectFinalizeFunc) camel_imap_wrapper_finalize); - } - - return type; -} - - -static void -imap_wrapper_hydrate (CamelImapWrapper *imap_wrapper, CamelStream *stream) -{ - CamelDataWrapper *data_wrapper = (CamelDataWrapper *) imap_wrapper; - - camel_object_ref (stream); - data_wrapper->stream = stream; - data_wrapper->offline = FALSE; - - camel_object_unref (imap_wrapper->folder); - imap_wrapper->folder = NULL; - g_free (imap_wrapper->uid); - imap_wrapper->uid = NULL; - g_free (imap_wrapper->part_spec); - imap_wrapper->part = NULL; -} - - -static ssize_t -write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) -{ - CamelImapWrapper *imap_wrapper = CAMEL_IMAP_WRAPPER (data_wrapper); - - CAMEL_IMAP_WRAPPER_LOCK (imap_wrapper, lock); - if (data_wrapper->offline) { - CamelStream *datastream; - - datastream = camel_imap_folder_fetch_data ( - imap_wrapper->folder, imap_wrapper->uid, - imap_wrapper->part_spec, FALSE, NULL); - if (!datastream) { - CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock); - errno = ENETUNREACH; - return -1; - } - - imap_wrapper_hydrate (imap_wrapper, datastream); - camel_object_unref (datastream); - } - CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock); - - return parent_class->write_to_stream (data_wrapper, stream); -} - - -CamelDataWrapper * -camel_imap_wrapper_new (CamelImapFolder *imap_folder, CamelContentType *type, - const char *uid, const char *part_spec, - CamelMimePart *part) -{ - CamelImapWrapper *imap_wrapper; - CamelStream *stream; - - imap_wrapper = (CamelImapWrapper *)camel_object_new(camel_imap_wrapper_get_type()); - - camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (imap_wrapper), type); - ((CamelDataWrapper *)imap_wrapper)->offline = TRUE; - - imap_wrapper->folder = imap_folder; - camel_object_ref (imap_folder); - imap_wrapper->uid = g_strdup (uid); - imap_wrapper->part_spec = g_strdup (part_spec); - - /* Don't ref this, it's our parent. */ - imap_wrapper->part = part; - - /* Try the cache. */ - stream = camel_imap_folder_fetch_data (imap_folder, uid, part_spec, - TRUE, NULL); - if (stream) { - imap_wrapper_hydrate (imap_wrapper, stream); - camel_object_unref (stream); - } - - return (CamelDataWrapper *)imap_wrapper; -} diff --git a/camel/providers/imap/camel-imap-wrapper.h b/camel/providers/imap/camel-imap-wrapper.h deleted file mode 100644 index 4f7ca5097a..0000000000 --- a/camel/providers/imap/camel-imap-wrapper.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-wrapper.h: data wrapper for offline IMAP data */ - -/* - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAP_WRAPPER_H -#define CAMEL_IMAP_WRAPPER_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include "camel-imap-types.h" - -#define CAMEL_IMAP_WRAPPER_TYPE (camel_imap_wrapper_get_type ()) -#define CAMEL_IMAP_WRAPPER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAP_WRAPPER_TYPE, CamelImapWrapper)) -#define CAMEL_IMAP_WRAPPER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAP_WRAPPER_TYPE, CamelImapWrapperClass)) -#define CAMEL_IS_IMAP_WRAPPER(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAP_WRAPPER_TYPE)) - -typedef struct -{ - CamelDataWrapper parent_object; - - struct _CamelImapWrapperPrivate *priv; - - CamelImapFolder *folder; - char *uid, *part_spec; - CamelMimePart *part; -} CamelImapWrapper; - -typedef struct { - CamelDataWrapperClass parent_class; - -} CamelImapWrapperClass; - -/* Standard Camel function */ -CamelType camel_imap_wrapper_get_type (void); - -/* Constructor */ -CamelDataWrapper *camel_imap_wrapper_new (CamelImapFolder *imap_folder, - CamelContentType *type, - const char *uid, - const char *part_spec, - CamelMimePart *part); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_DATA_WRAPPER_H */ diff --git a/camel/providers/imap/libcamelimap.urls b/camel/providers/imap/libcamelimap.urls deleted file mode 100644 index c301c0ffac..0000000000 --- a/camel/providers/imap/libcamelimap.urls +++ /dev/null @@ -1 +0,0 @@ -imap diff --git a/camel/providers/imapp/.cvsignore b/camel/providers/imapp/.cvsignore deleted file mode 100644 index 3fa8afaa38..0000000000 --- a/camel/providers/imapp/.cvsignore +++ /dev/null @@ -1,11 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/imapp/Makefile.am b/camel/providers/imapp/Makefile.am deleted file mode 100644 index 7ce8c65fcd..0000000000 --- a/camel/providers/imapp/Makefile.am +++ /dev/null @@ -1,45 +0,0 @@ -## Process this file with automake to produce Makefile.in - -libcamelimappincludedir = $(privincludedir)/camel - -camel_provider_LTLIBRARIES = libcamelimapp.la -camel_provider_DATA = libcamelimapp.urls - -INCLUDES = -I.. \ - -I$(srcdir)/.. \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir) \ - $(CAMEL_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(GTK_INCLUDEDIR) \ - -DG_LOG_DOMAIN=\"camel-imapp-provider\" - -libcamelimapp_la_SOURCES = \ - camel-imapp-utils.c \ - camel-imapp-engine.c \ - camel-imapp-stream.c \ - camel-imapp-store.c \ - camel-imapp-folder.c \ - camel-imapp-provider.c \ - camel-imapp-store-summary.c \ - camel-imapp-driver.c \ - camel-imapp-summary.c - -libcamelimappinclude_HEADERS = \ - camel-imapp-utils.h \ - camel-imapp-engine.h \ - camel-imapp-stream.h \ - camel-imapp-store.h \ - camel-imapp-folder.h \ - camel-imapp-store-summary.h \ - camel-imapp-driver.h \ - camel-imapp-summary.h - -libcamelimapp_la_LDFLAGS = -avoid-version -module - -#noinst_HEADERS = \ -# camel-imap-private.h - -EXTRA_DIST = libcamelimapp.urls diff --git a/camel/providers/imapp/camel-imapp-driver.c b/camel/providers/imapp/camel-imapp-driver.c deleted file mode 100644 index 106e98fbb3..0000000000 --- a/camel/providers/imapp/camel-imapp-driver.c +++ /dev/null @@ -1,771 +0,0 @@ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "camel-imapp-driver.h" -#include "camel-imapp-utils.h" -#include "camel-imapp-folder.h" -#include "camel-imapp-engine.h" -#include "camel-imapp-summary.h" -#include "camel-imapp-exception.h" - -#include -#include - -#include -#include -#include -#include - -#define d(x) x - -static int driver_resp_fetch(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata); -static int driver_resp_expunge(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata); -static int driver_resp_exists(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata); -static int driver_resp_list(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata); - -static void driver_status(CamelIMAPPEngine *ie, struct _status_info *sinfo, CamelIMAPPDriver *sdata); - -static void -class_init(CamelIMAPPDriverClass *ieclass) -{ -} - -static void -object_init(CamelIMAPPDriver *ie, CamelIMAPPDriverClass *ieclass) -{ - ie->summary = g_ptr_array_new(); - e_dlist_init(&ie->body_fetch); - e_dlist_init(&ie->body_fetch_done); -} - -static void -object_finalise(CamelIMAPPDriver *ie, CamelIMAPPDriverClass *ieclass) -{ - if (ie->folder) - camel_object_unref((CamelObject *)ie->folder); - if (ie->engine) - camel_object_unref((CamelObject *)ie->engine); - if (ie->summary) - g_ptr_array_free(ie->summary, TRUE); -} - -CamelType -camel_imapp_driver_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register ( - camel_object_get_type (), - "CamelIMAPPDriver", - sizeof (CamelIMAPPDriver), - sizeof (CamelIMAPPDriverClass), - (CamelObjectClassInitFunc) class_init, - NULL, - (CamelObjectInitFunc) object_init, - (CamelObjectFinalizeFunc) object_finalise); - } - - return type; -} - -CamelIMAPPDriver * -camel_imapp_driver_new(CamelIMAPPStream *stream) -{ - CamelIMAPPDriver *driver; - CamelIMAPPEngine *ie; - - driver = CAMEL_IMAPP_DRIVER (camel_object_new (CAMEL_IMAPP_DRIVER_TYPE)); - ie = driver->engine = camel_imapp_engine_new(stream); - - camel_imapp_engine_add_handler(ie, "FETCH", (CamelIMAPPEngineFunc)driver_resp_fetch, driver); - camel_imapp_engine_add_handler(ie, "EXPUNGE", (CamelIMAPPEngineFunc)driver_resp_expunge, driver); - camel_imapp_engine_add_handler(ie, "EXISTS", (CamelIMAPPEngineFunc)driver_resp_exists, driver); - camel_imapp_engine_add_handler(ie, "LIST", (CamelIMAPPEngineFunc)driver_resp_list, driver); - camel_object_hook_event(ie, "status", (CamelObjectEventHookFunc)driver_status, driver); - - return driver; -} - -void -camel_imapp_driver_set_sasl_factory(CamelIMAPPDriver *id, CamelIMAPPSASLFunc get_sasl, void *sasl_data) -{ - id->get_sasl = get_sasl; - id->get_sasl_data = sasl_data; -} - -void -camel_imapp_driver_set_login_query(CamelIMAPPDriver *id, CamelIMAPPLoginFunc get_login, void *login_data) -{ - id->get_login = get_login; - id->get_login_data = login_data; -} - -void -camel_imapp_driver_login(CamelIMAPPDriver *id) -/* throws SERVICE_CANT_AUTHENTICATE, SYSTEM_IO */ -{ - CamelIMAPPCommand * volatile ic = NULL; - - /* connect? */ - /* camel_imapp_engine_connect() */ - /* or above? */ - - CAMEL_TRY { - CamelSasl *sasl; - - if (id->get_sasl - && (sasl = id->get_sasl(id, id->get_sasl_data))) { - ic = camel_imapp_engine_command_new(id->engine, "AUTHENTICATE", NULL, "AUTHENTICATE %A", sasl); - camel_object_unref(sasl); - } else { - char *user, *pass; - - g_assert(id->get_login); - id->get_login(id, &user, &pass, id->get_login_data); - ic = camel_imapp_engine_command_new(id->engine, "LOGIN", NULL, "LOGIN %s %s", user, pass); - g_free(user); - g_free(pass); - } - - camel_imapp_engine_command_queue(id->engine, ic); - while (camel_imapp_engine_iterate(id->engine, ic) > 0) - ; - - if (ic->status->result != IMAP_OK) - camel_exception_throw(CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, "Login failed: %s", ic->status->text); - camel_imapp_engine_command_free(id->engine, ic); - } CAMEL_CATCH(ex) { - if (ic) - camel_imapp_engine_command_free(id->engine, ic); - camel_exception_throw_ex(ex); - } CAMEL_DONE; -} - -void -camel_imapp_driver_select(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder) -{ - CamelIMAPPSelectResponse *sr; - CamelIMAPPCommand * volatile ic = NULL; - CamelIMAPPCommand * volatile ic2 = NULL; - guint32 count; - CamelFolderSummary *summary; - - if (id->folder) { - if (folder == id->folder) - return; - camel_imapp_driver_sync(id, FALSE, id->folder); - if (camel_folder_change_info_changed(id->folder->changes)) { - camel_object_trigger_event(id->folder, "folder_changed", id->folder->changes); - camel_folder_change_info_clear(id->folder->changes); - } - camel_object_unref(id->folder); - id->folder = NULL; - } - - summary = ((CamelFolder *)folder)->summary; - - ic = camel_imapp_engine_command_new(id->engine, "SELECT", NULL, "SELECT %t", folder->raw_name); - camel_imapp_engine_command_queue(id->engine, ic); - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - - id->folder = folder; - camel_object_ref(folder); - - count = camel_folder_summary_count(summary); - if (count > 0 && count <= id->exists) { - ic = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, - "FETCH 1:%u (UID FLAGS)", count); - camel_imapp_engine_command_queue(id->engine, ic); - if (count < id->exists) { - ic2 = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, - "FETCH %u:* (UID FLAGS ENVELOPE)", count+1); - camel_imapp_engine_command_queue(id->engine, ic2); - } else { - ic2 = NULL; - } - - while (camel_imapp_engine_iterate(id->engine, ic2?ic2:ic)>0) - ; - - camel_imapp_engine_command_free(id->engine, ic); - if (ic2) - camel_imapp_engine_command_free(id->engine, ic2); - } else { - ic = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, - "FETCH 1:* (UID FLAGS ENVELOPE)"); - camel_imapp_engine_command_queue(id->engine, ic); - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - } - - /* TODO: need to set exists/etc in summary */ - folder->exists = id->exists; - folder->uidvalidity = id->uidvalidity; - - printf("saving summary '%s'\n", summary->summary_path); - camel_folder_summary_save(summary); - - if (camel_folder_change_info_changed(id->folder->changes)) { - camel_object_trigger_event(id->folder, "folder_changed", id->folder->changes); - camel_folder_change_info_clear(id->folder->changes); - } -} - -static void -imapp_driver_check(CamelIMAPPDriver *id) -{ - guint32 count; - CamelIMAPPCommand *ic; - - /* FIXME: exception handling */ - - if (id->folder->exists != id->exists) { - count = camel_folder_summary_count(((CamelFolder *)id->folder)->summary); - if (count < id->exists) { - printf("fetching new messages\n"); - ic = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, - "FETCH %u:* (UID FLAGS ENVELOPE)", count+1); - camel_imapp_engine_command_queue(id->engine, ic); - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - } else if (count > id->exists) { - printf("folder shrank with no expunge notificaitons!? uh, dunno what to do\n"); - } - } - - printf("checking for change info changes\n"); - if (camel_folder_change_info_changed(id->folder->changes)) { - printf("got somechanges! added=%d changed=%d removed=%d\n", - id->folder->changes->uid_added->len, - id->folder->changes->uid_changed->len, - id->folder->changes->uid_removed->len); - camel_object_trigger_event(id->folder, "folder_changed", id->folder->changes); - camel_folder_change_info_clear(id->folder->changes); - } -} - -void -camel_imapp_driver_update(CamelIMAPPDriver *id, CamelIMAPPFolder *folder) -{ - if (id->folder == folder) { - CamelIMAPPCommand *ic; - - /* this will automagically update flags & expunge items */ - ic = camel_imapp_engine_command_new(id->engine, "NOOP", NULL, "NOOP"); - camel_imapp_engine_command_queue(id->engine, ic); - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - - imapp_driver_check(id); - } else { - camel_imapp_driver_select(id, folder); - } -} - -/* FIXME: this is basically a copy of the same in camel-imapp-utils.c */ -static struct { - char *name; - guint32 flag; -} flag_table[] = { - { "\\ANSWERED", CAMEL_MESSAGE_ANSWERED }, - { "\\DELETED", CAMEL_MESSAGE_DELETED }, - { "\\DRAFT", CAMEL_MESSAGE_DRAFT }, - { "\\FLAGGED", CAMEL_MESSAGE_FLAGGED }, - { "\\SEEN", CAMEL_MESSAGE_SEEN }, - /* { "\\RECENT", CAMEL_IMAPP_MESSAGE_RECENT }, */ -}; - -/* - flags 00101000 - sflags 01001000 - ^ 01100000 -~flags 11010111 -& 01000000 - -&flags 00100000 -*/ - -static void -imapp_write_flags(CamelIMAPPDriver *id, guint32 orset, gboolean on, CamelFolderSummary *summary) -{ - guint32 i, j, count; - CamelIMAPPMessageInfo *info; - CamelIMAPPCommand *ic = NULL; - struct _uidset_state ss; - GSList *commands = NULL; - - /* FIXME: exception handling */ - - count = camel_folder_summary_count(summary); - for (j=0;jengine); - for (i=0;iinfo.flags & CAMEL_IMAPP_SERVER_FLAGS; - guint32 sflags = info->server_flags & CAMEL_IMAPP_SERVER_FLAGS; - - if ( (on && (((flags ^ sflags) & flags) & flag_table[j].flag)) - || (!on && (((flags ^ sflags) & ~flags) & flag_table[j].flag))) { - if (ic == NULL) - ic = camel_imapp_engine_command_new(id->engine, "STORE", NULL, "UID STORE "); - flush = imapp_uidset_add(&ss, ic, camel_message_info_uid(info)); - } - camel_folder_summary_info_free(summary, (CamelMessageInfo *)info); - } - - if (i == count-1 && ic != NULL) - flush |= imapp_uidset_done(&ss, ic); - - if (flush) { - flush = 0; - camel_imapp_engine_command_add(id->engine, ic, " %tFLAGS.SILENT (%t)", on?"+":"-", flag_table[j].name); - camel_imapp_engine_command_queue(id->engine, ic); - commands = g_slist_prepend(commands, ic); - ic = NULL; - } - } - } - - /* flush off any requests we may have outstanding */ - /* TODO: for max benefit, should have this routine do both on and off flags in one go */ - while (commands) { - GSList *next = commands->next; - - ic = commands->data; - g_slist_free_1(commands); - commands = next; - - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - } -} - -void -camel_imapp_driver_sync(CamelIMAPPDriver *id, gboolean expunge, CamelIMAPPFolder *folder) -{ - CamelFolderSummary *summary; - guint i, count, on_orset, off_orset; - CamelIMAPPMessageInfo *info; - CamelIMAPPCommand *ic; - - /* FIXME: exception handling */ - - camel_imapp_driver_update(id, folder); - - summary = ((CamelFolder *)folder)->summary; - count = camel_folder_summary_count(summary); - /* find out which flags have turned on, which have tunred off */ - off_orset = on_orset = 0; - for (i=0;iinfo.flags & CAMEL_IMAPP_SERVER_FLAGS; - sflags = info->server_flags & CAMEL_IMAPP_SERVER_FLAGS; - if (flags != sflags) { - off_orset |= ( flags ^ sflags ) & ~flags; - on_orset |= (flags ^ sflags) & flags; - } - camel_folder_summary_info_free(summary, (CamelMessageInfo *)info); - } - - if (on_orset || off_orset) { - /* turn on or off all messages matching */ - if (on_orset) - imapp_write_flags(id, on_orset, TRUE, summary); - if (off_orset) - imapp_write_flags(id, off_orset, FALSE, summary); - - /* success (no exception), make sure we match what we're supposed to */ - for (i=0;iserver_flags = info->info.flags & CAMEL_IMAPP_SERVER_FLAGS; - camel_folder_summary_info_free(summary, (CamelMessageInfo *)info); - } - camel_folder_summary_touch(summary); - /* could save summary here, incase of failure? */ - } - - if (expunge) { - ic = camel_imapp_engine_command_new(id->engine, "EXPUNGE", NULL, "EXPUNGE"); - camel_imapp_engine_command_queue(id->engine, ic); - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - } - - printf("saving summary '%s'\n", summary->summary_path); - camel_folder_summary_save(summary); - - if (camel_folder_change_info_changed(id->folder->changes)) { - camel_object_trigger_event(id->folder, "folder_changed", id->folder->changes); - camel_folder_change_info_clear(id->folder->changes); - } -} - -struct _fetch_data { - struct _fetch_data *next; - struct _fetch_data *prev; - - CamelStream *data; - const char *uid; - const char *section; -}; - -CamelStream * -camel_imapp_driver_fetch(CamelIMAPPDriver *id, CamelIMAPPFolder *folder, const char *uid, const char *section) -{ - struct _fetch_data fd; - CamelIMAPPCommand *ic; - - fd.data = NULL; - fd.uid = uid; - fd.section = section; - e_dlist_addtail(&id->body_fetch, (EDListNode *)&fd); - - CAMEL_TRY { - camel_imapp_driver_select(id, folder); - - ic = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, "UID FETCH %t (BODY.PEEK[%t])", uid, section); - camel_imapp_engine_command_queue(id->engine, ic); - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - imapp_driver_check(id); - } CAMEL_CATCH(e) { - /* FIXME: do exception properly */ - } CAMEL_DONE; - - e_dlist_remove((EDListNode *)&fd); - - return fd.data; -} - -GPtrArray * -camel_imapp_driver_list(CamelIMAPPDriver *id, const char *name, guint32 flags) -{ - CamelIMAPPCommand * volatile ic; - GPtrArray *res; - - g_assert(id->list_commands == NULL); - g_assert(id->list_result == NULL); - - /* FIXME: make sure we only have a single list running at a time */ - /* sem_wait(id->list_sem); */ - - /* FIXME: namespace stuff (done in store code?) */ - - /* FIXME: if name != "", we need to also do list "name.%" (. == sep) */ - - id->list_result = g_ptr_array_new(); - id->list_flags = flags; - CAMEL_TRY { - ic = camel_imapp_engine_command_new(id->engine, "LIST", NULL, "LIST \"\" %f", name[0]?name:"%"); - camel_imapp_engine_command_queue(id->engine, ic); - while (ic) { - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - - if (id->list_commands) { - GSList *top = id->list_commands; - - id->list_commands = top->next; - ic = top->data; - g_slist_free_1(top); - } else { - ic = NULL; - } - } - } CAMEL_CATCH(e) { - GSList *top = id->list_commands; - int i; - - camel_imapp_engine_command_free(id->engine, ic); - - while (top) { - GSList *topn = top->next; - - camel_imapp_engine_command_free(id->engine, ic); - g_slist_free_1(top); - top = topn; - } - id->list_commands = NULL; - - res = id->list_result; - for (i=0;ilen;i++) - imap_free_list(res->pdata[i]); - g_ptr_array_free(res, TRUE); - id->list_result = NULL; - - camel_exception_throw_ex(e); - } CAMEL_DONE; - - res = id->list_result; - id->list_result = NULL; - - /* sem_post(id->list_sem); */ - - return res; -} - -static int -driver_resp_list(CamelIMAPPEngine *ie, guint32 idx, CamelIMAPPDriver *id) -{ - struct _list_info *linfo; - - /* FIXME: exceptions */ - - linfo = imap_parse_list(ie->stream); - printf("store list: '%s' ('%c')\n", linfo->name, linfo->separator); - if (id->list_result) { - if ((linfo->flags & CAMEL_FOLDER_NOINFERIORS) == 0 - && (id->list_flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) - && linfo->separator) { - int depth = 0; - char *p = linfo->name; - char c = linfo->separator; - - /* this is expensive ... but if we've listed this deep we're going slow anyway */ - while (*p && depth < 10) { - if (*p == c) - depth++; - p++; - } - - if (depth < 10 - && (linfo->name[0] == 0 || linfo->name[strlen(linfo->name)-1] != c)) { - CamelIMAPPCommand *ic; - - ic = camel_imapp_engine_command_new(id->engine, "LIST", NULL, "LIST \"\" %t%c%%", linfo->name, c); - id->list_commands = g_slist_prepend(id->list_commands, ic); - camel_imapp_engine_command_queue(id->engine, ic); - } - } - /* FIXME: dont add to list if name ends in separator */ - g_ptr_array_add(id->list_result, linfo); - } else { - g_warning("unexpected list response\n"); - imap_free_list(linfo); - } - - return camel_imapp_engine_skip(ie); -} - -/* ********************************************************************** */ - -static void -driver_status(CamelIMAPPEngine *ie, struct _status_info *sinfo, CamelIMAPPDriver *sdata) -{ - printf("got status response ...\n"); - switch(sinfo->condition) { - case IMAP_READ_WRITE: - printf("folder is read-write\n"); - break; - case IMAP_READ_ONLY: - printf("folder is read-only\n"); - break; - case IMAP_UIDVALIDITY: - sdata->uidvalidity = sinfo->u.uidvalidity; - break; -#if 0 - /* not defined yet ... */ - case IMAP_UIDNEXT: - printf("got uidnext for folder: %d\n", sinfo->u.uidnext); - break; -#endif - case IMAP_UNSEEN: - sdata->unseen = sinfo->u.unseen; - break; - case IMAP_PERMANENTFLAGS: - sdata->permanentflags = sinfo->u.permanentflags; - break; - case IMAP_ALERT: - printf("ALERT!: %s\n", sinfo->text); - break; - case IMAP_PARSE: - printf("PARSE: %s\n", sinfo->text); - break; - default: - break; - } -} - -static int -driver_resp_exists(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata) -{ - /* should this be an event instead? */ - - sdata->exists = id; - - return camel_imapp_engine_skip(ie); -} - -static int -driver_resp_expunge(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata) -{ - printf("got expunge response %u\n", id); - if (sdata->folder != NULL) { - CamelMessageInfo *info; - CamelFolderSummary *summary = ((CamelFolder *)sdata->folder)->summary; - - info = camel_folder_summary_index(summary, id-1); - if (info) { - printf("expunging msg %d\n", id); - camel_folder_summary_remove(summary, info); - camel_folder_summary_info_free(summary, info); - camel_folder_change_info_remove_uid(sdata->folder->changes, camel_message_info_uid(info)); - } else { - printf("can not find msg %u from expunge\n", id); - } - } - - return camel_imapp_engine_skip(ie); -} - -static int -driver_resp_fetch(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata) -{ - struct _fetch_info *finfo = NULL; - CamelMessageInfo *info, *uinfo; - unsigned int i; - CamelFolderSummary *summary; - - printf("got fetch response %d\n", id); - - if (sdata->folder == NULL) - goto done; - - summary = ((CamelFolder *)sdata->folder)->summary; - - finfo = imap_parse_fetch(ie->stream); - imap_dump_fetch(finfo); - - info = camel_folder_summary_index(summary, id-1); - if (info == NULL) { - if (finfo->uid == NULL) { - printf("got fetch response for currently unknown message %u\n", id); - goto done; - } - uinfo = camel_folder_summary_uid(summary, finfo->uid); - if (uinfo) { - /* we have a problem ... index mismatch */ - printf("index mismatch, uid '%s' not at index '%u'\n", - finfo->uid, id); - camel_folder_summary_info_free(summary, uinfo); - } - /* pad out the summary till we have enough indexes */ - for (i=camel_folder_summary_count(summary);iuid)); - } else { - char uidtmp[32]; - - sprintf(uidtmp, "blank-%u", i); - camel_message_info_set_uid(info, g_strdup(uidtmp)); - printf("inserting empty uid %s\n", uidtmp); - } - - camel_folder_summary_add(summary, info); - } - info = camel_folder_summary_index(summary, id-1); - g_assert(info != NULL); - } else { - if (finfo->uid) { - /* FIXME: need to handle blank-* uids, somehow */ - while (info && strcmp(camel_message_info_uid(info), finfo->uid) != 0) { - printf("index mismatch, uid '%s' not at index '%u', got '%s' instead (removing)\n", - finfo->uid, id, camel_message_info_uid(info)); - - camel_folder_change_info_remove_uid(sdata->folder->changes, camel_message_info_uid(info)); - camel_folder_summary_remove(summary, info); - camel_folder_summary_info_free(summary, info); - info = camel_folder_summary_index(summary, id-1); - } - } else { - printf("got info for unknown message %u\n", id); - } - } - - if (info) { - if (finfo->got & FETCH_MINFO) { - /* if we only use ENVELOPE? */ - camel_message_info_set_subject(info, g_strdup(camel_message_info_subject(finfo->minfo))); - camel_message_info_set_from(info, g_strdup(camel_message_info_from(finfo->minfo))); - camel_message_info_set_to(info, g_strdup(camel_message_info_to(finfo->minfo))); - camel_message_info_set_cc(info, g_strdup(camel_message_info_cc(finfo->minfo))); - info->date_sent = finfo->minfo->date_sent; - camel_folder_change_info_add_uid(sdata->folder->changes, camel_message_info_uid(info)); - printf("adding change info uid '%s'\n", camel_message_info_uid(info)); - } - - if (finfo->got & FETCH_FLAGS) { - if ((info->flags & CAMEL_IMAPP_SERVER_FLAGS) != (finfo->flags & CAMEL_IMAPP_SERVER_FLAGS)) { - camel_folder_change_info_change_uid(sdata->folder->changes, camel_message_info_uid(info)); - info->flags = (info->flags & ~(CAMEL_IMAPP_SERVER_FLAGS)) | (finfo->flags & CAMEL_IMAPP_SERVER_FLAGS); - camel_folder_summary_touch(summary); - } - ((CamelIMAPPMessageInfo *)info)->server_flags = finfo->flags & CAMEL_IMAPP_SERVER_FLAGS; - } - - if ((finfo->got & (FETCH_BODY|FETCH_UID)) == (FETCH_BODY|FETCH_UID)) { - struct _fetch_data *fd, *fn; - - fd = (struct _fetch_data *)sdata->body_fetch.head; - fn = fd->next; - while (fn) { - if (!strcmp(finfo->uid, fd->uid) && !strcmp(finfo->section, fd->section)) { - if (fd->data) - camel_object_unref(fd->data); - fd->data = finfo->body; - camel_object_ref(fd->data); - e_dlist_remove((EDListNode *)fd); - e_dlist_addtail(&sdata->body_fetch_done, (EDListNode *)fd); - break; - } - fd = fn; - fn = fn->next; - } - } - - camel_folder_summary_info_free(summary, info); - } else { - printf("dont know what to do with message\n"); - } - done: - imap_free_fetch(finfo); - - return camel_imapp_engine_skip(ie); -} diff --git a/camel/providers/imapp/camel-imapp-driver.h b/camel/providers/imapp/camel-imapp-driver.h deleted file mode 100644 index 3124700619..0000000000 --- a/camel/providers/imapp/camel-imapp-driver.h +++ /dev/null @@ -1,81 +0,0 @@ - -#ifndef _CAMEL_IMAPP_DRIVER_H -#define _CAMEL_IMAPP_DRIVER_H - -#include -#include "camel-imapp-stream.h" -#include - -#define CAMEL_IMAPP_DRIVER_TYPE (camel_imapp_driver_get_type ()) -#define CAMEL_IMAPP_DRIVER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAPP_DRIVER_TYPE, CamelIMAPPDriver)) -#define CAMEL_IMAPP_DRIVER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAPP_DRIVER_TYPE, CamelIMAPPDriverClass)) -#define CAMEL_IS_IMAP_DRIVER(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAPP_DRIVER_TYPE)) - -typedef struct _CamelIMAPPDriver CamelIMAPPDriver; -typedef struct _CamelIMAPPDriverClass CamelIMAPPDriverClass; - -typedef int (*CamelIMAPPDriverFunc)(struct _CamelIMAPPDriver *driver, void *data); -typedef struct _CamelSasl * (*CamelIMAPPSASLFunc)(struct _CamelIMAPPDriver *driver, void *data); -typedef void (*CamelIMAPPLoginFunc)(struct _CamelIMAPPDriver *driver, char **login, char **pass, void *data); - -struct _CamelMimeMessage; - -struct _CamelIMAPPDriver { - CamelObject parent_object; - - struct _CamelIMAPPEngine *engine; - - struct _CamelIMAPPFolder *folder; - - /* current folder stuff */ - GPtrArray *summary; - guint32 uidvalidity; - guint32 exists; - guint32 recent; - guint32 unseen; - guint32 permanentflags; - - /* list stuff */ - GPtrArray *list_result; - GSList *list_commands; - guint32 list_flags; - - /* sem_t list_sem; for controlled access to list variables */ - - /* this is so the node is always in a list - easier exception management */ - EDList body_fetch; - EDList body_fetch_done; - - /* factory to get an appropriate sasl mech */ - CamelIMAPPSASLFunc get_sasl; - void *get_sasl_data; - - /* callbacks, get login username/pass */ - CamelIMAPPLoginFunc get_login; - void *get_login_data; -}; - -struct _CamelIMAPPDriverClass { - CamelObjectClass parent_class; -}; - -CamelType camel_imapp_driver_get_type (void); - -CamelIMAPPDriver * camel_imapp_driver_new(CamelIMAPPStream *stream); - -void camel_imapp_driver_set_sasl_factory(CamelIMAPPDriver *id, CamelIMAPPSASLFunc get_sasl, void *sasl_data); -void camel_imapp_driver_set_login_query(CamelIMAPPDriver *id, CamelIMAPPLoginFunc get_login, void *login_data); - -void camel_imapp_driver_login(CamelIMAPPDriver *id); - -void camel_imapp_driver_select(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder); -void camel_imapp_driver_update(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder); -void camel_imapp_driver_sync(CamelIMAPPDriver *id, gboolean expunge, struct _CamelIMAPPFolder *folder); - -struct _CamelStream * camel_imapp_driver_fetch(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder, const char *uid, const char *body); -GPtrArray * camel_imapp_driver_list(CamelIMAPPDriver *id, const char *name, guint32 flags); - -struct _CamelStream *camel_imapp_driver_get(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder, const char *uid); -void camel_imapp_driver_append(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder, struct _CamelDataWrapper *); - -#endif diff --git a/camel/providers/imapp/camel-imapp-engine.c b/camel/providers/imapp/camel-imapp-engine.c deleted file mode 100644 index df14903c5a..0000000000 --- a/camel/providers/imapp/camel-imapp-engine.c +++ /dev/null @@ -1,1180 +0,0 @@ - -#include "config.h" - -#include -#include - -#include "camel-imapp-engine.h" -#include "camel-imapp-stream.h" -#include "camel-imapp-utils.h" -#include "camel-imapp-exception.h" - -#include -#include -#include -#include -#include - -#include - -#define e(x) -#define c(x) /* command build debug */ - -static void imap_engine_command_addv(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic, const char *fmt, va_list ap); -static void imap_engine_command_complete(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic); - -struct _handler { - CamelIMAPPEngineFunc func; - void *data; - char name[1]; -}; - -static void -class_init(CamelIMAPPEngineClass *ieclass) -{ - ieclass->tagprefix = 'A'; - - camel_object_class_add_event((CamelObjectClass *)ieclass, "status", NULL); -} - -static void -object_init(CamelIMAPPEngine *ie, CamelIMAPPEngineClass *ieclass) -{ - ie->handlers = g_hash_table_new(g_str_hash, g_str_equal); - e_dlist_init(&ie->active); - e_dlist_init(&ie->queue); - e_dlist_init(&ie->done); - - ie->tagprefix = ieclass->tagprefix; - ieclass->tagprefix++; - if (ieclass->tagprefix > 'Z') - ieclass->tagprefix = 'A'; - ie->tagprefix = 'A'; - - ie->state = IMAP_ENGINE_DISCONNECT; -} - -static void -handler_free(void *key, void *mem, void *data) -{ - g_free(mem); -} - -static void -object_finalise(CamelIMAPPEngine *ie, CamelIMAPPEngineClass *ieclass) -{ - /* FIXME: need to free the commands ... */ - while (camel_imapp_engine_iterate(ie, NULL) > 0) - ; - - g_hash_table_foreach(ie->handlers, (GHFunc)handler_free, NULL); - g_hash_table_destroy(ie->handlers); -} - -CamelType -camel_imapp_engine_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register ( - camel_object_get_type (), - "CamelIMAPPEngine", - sizeof (CamelIMAPPEngine), - sizeof (CamelIMAPPEngineClass), - (CamelObjectClassInitFunc) class_init, - NULL, - (CamelObjectInitFunc) object_init, - (CamelObjectFinalizeFunc) object_finalise); - } - - return type; -} - -/* FIXME: check this, just taken from old code, not rfc */ -struct { - char *name; - guint32 flag; -} capa_table[] = { - { "IMAP4", IMAP_CAPABILITY_IMAP4 }, - { "IMAP4REV1", IMAP_CAPABILITY_IMAP4REV1 }, - { "STATUS", IMAP_CAPABILITY_STATUS } , - { "NAMESPACE", IMAP_CAPABILITY_NAMESPACE }, - { "UIDPLUS", IMAP_CAPABILITY_UIDPLUS }, - { "LITERAL+", IMAP_CAPABILITY_LITERALPLUS }, - { "STARTTLS", IMAP_CAPABILITY_STARTTLS }, -}; - - -/* -capability_data ::= "CAPABILITY" SPACE [1#capability SPACE] "IMAP4rev1" - [SPACE 1#capability] - ;; IMAP4rev1 servers which offer RFC 1730 - ;; compatibility MUST list "IMAP4" as the first - ;; capability. -*/ -static int resp_capability(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - int tok, len, i; - unsigned char *token, *p, c; - - /* FIXME: handle auth types */ - - printf("got capability response:\n"); - while (1) { - tok = camel_imapp_stream_token(ie->stream, &token, &len); - switch(tok) { - case IMAP_TOK_TOKEN: - p = token; - while ((c = *p)) - *p++ = toupper(c); - case IMAP_TOK_INT: - printf(" cap: '%s'\n", token); - for (i=0;i<(int)(sizeof(capa_table)/sizeof(capa_table[0]));i++) - if (strcmp(token, capa_table[i].name)) - ie->capa |= capa_table[i].flag; - break; - case '\n': - return 0; - case IMAP_TOK_ERROR: - case IMAP_TOK_PROTOCOL: - camel_imapp_engine_skip(ie); - return -1; - default: - printf("Unknown Response token %02x '%c'\n", tok, isprint(tok)?tok:'.'); - } - } while (tok != '\n'); - - return 0; -} - -/* expunge command, id is expunged seq number */ -/* message_data ::= nz_number SPACE ("EXPUNGE" / - ("FETCH" SPACE msg_att)) */ -static int resp_expunge(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - printf("message expunged: %d\n", id); - - return camel_imapp_engine_skip(ie); -} - -static int resp_flags(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - guint32 flags; - - imap_parse_flags(ie->stream, &flags); - - printf("flags: %08x\n", flags); - - return camel_imapp_engine_skip(ie); -} - -/* exists count */ -static int resp_exists(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - printf("messages exist: %d\n", id); - - if (ie->select_response) - ie->select_response->exists = id; - - return camel_imapp_engine_skip(ie); -} - -static int resp_recent(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - printf("messages recent: %d\n", id); - - if (ie->select_response) - ie->select_response->recent = id; - - return camel_imapp_engine_skip(ie); -} - -static int resp_fetch(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - struct _fetch_info *finfo; - - finfo = imap_parse_fetch(ie->stream); - imap_dump_fetch(finfo); - imap_free_fetch(finfo); - - return camel_imapp_engine_skip(ie); -} - -#if 0 -static int resp_list(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - struct _list_info *linfo; - - linfo = imap_parse_list(ie->stream); - printf("list: '%s' (%c)\n", linfo->name, linfo->separator); - imap_free_list(linfo); - - return camel_imapp_engine_skip(ie); -} -#endif - -CamelIMAPPEngine * -camel_imapp_engine_new(CamelIMAPPStream *stream) -{ - CamelIMAPPEngine * volatile engine; - - engine = CAMEL_IMAPP_ENGINE (camel_object_new (CAMEL_IMAPP_ENGINE_TYPE)); - engine->stream = stream; - camel_object_ref((CamelObject *)stream); - - camel_imapp_engine_add_handler(engine, "CAPABILITY", resp_capability, engine); - - /* mailbox_data */ - camel_imapp_engine_add_handler(engine, "FLAGS", (CamelIMAPPEngineFunc)resp_flags, engine); - camel_imapp_engine_add_handler(engine, "EXISTS", (CamelIMAPPEngineFunc)resp_exists, engine); - camel_imapp_engine_add_handler(engine, "RECENT", (CamelIMAPPEngineFunc)resp_recent, engine); - -#if 0 - camel_imapp_engine_add_handler(engine, "LIST", (CamelIMAPPEngineFunc)resp_list, engine); - camel_imapp_engine_add_handler(engine, "LSUB", (CamelIMAPPEngineFunc)resp_list, engine); -#endif - /* message_data */ - camel_imapp_engine_add_handler(engine, "EXPUNGE", (CamelIMAPPEngineFunc)resp_expunge, engine); - camel_imapp_engine_add_handler(engine, "FETCH", (CamelIMAPPEngineFunc)resp_fetch, engine); - - /* TODO: move this to a driver:connect call? */ - CAMEL_TRY { - unsigned char *token; - unsigned int len; - int tok; - - tok = camel_imapp_stream_token(stream, &token, &len); - if (tok == '*') { - struct _status_info *sinfo = imap_parse_status(stream); - - switch (sinfo->result) { - case IMAP_OK: - engine->state = IMAP_ENGINE_CONNECT; - printf("Server connected ok: %s\n", sinfo->text); - break; - case IMAP_PREAUTH: - printf("pre-authenticated ...\n"); - engine->state = IMAP_ENGINE_AUTH; - break; - default: - imap_free_status(sinfo); - camel_exception_throw(1, "Server refused connection: %s", sinfo->text); - break; - } - imap_free_status(sinfo); - } else { - engine->state = IMAP_ENGINE_CONNECT; - printf("unknwon server greeting, ignored\n"); - camel_imapp_engine_skip(engine); - } - camel_imapp_engine_capabilities(engine); - } CAMEL_CATCH(ex) { - printf("connection failed: %s\n", ex->desc); - camel_object_unref((CamelObject *)engine); - engine = NULL; - } CAMEL_DONE; - - return engine; -} - -void -camel_imapp_engine_add_handler(CamelIMAPPEngine *imap, const char *response, CamelIMAPPEngineFunc func, void *data) -{ - struct _handler *h; - const unsigned char *p; - unsigned char *o, c; - - h = g_malloc0(sizeof(*h) + strlen(response)); - h->func = func; - h->data = data; - - p = response; - o = h->name; - while ((c = *p++)) - *o++ = toupper(c); - *o = 0; - - g_hash_table_insert(imap->handlers, h->name, h); -} - -int -camel_imapp_engine_capabilities(CamelIMAPPEngine *ie) -{ - CamelIMAPPCommand *ic; - - /* reset capabilities */ - ie->capa = 0; - - ic = camel_imapp_engine_command_new(ie, "CAPABILITY", NULL, "CAPABILITY"); - camel_imapp_engine_command_queue(ie, ic); - while (camel_imapp_engine_iterate(ie, ic)>0) - ; - camel_imapp_engine_command_free(ie, ic); - - return 0; -} - -/* skip the rest of the line of tokens */ -int -camel_imapp_engine_skip(CamelIMAPPEngine *imap) -{ - int tok; - unsigned char *token; - unsigned int len; - - do { - tok = camel_imapp_stream_token(imap->stream, &token, &len); - if (tok == IMAP_TOK_LITERAL) { - camel_imapp_stream_set_literal(imap->stream, len); - while ((tok = camel_imapp_stream_getl(imap->stream, &token, &len)) > 0) { - printf("Skip literal data '%.*s'\n", (int)len, token); - } - } - } while (tok != '\n' && tok >= 0); - - if (tok < 0) - return -1; - - return 0; -} - -/* handle any untagged responses */ -static int -iterate_untagged(CamelIMAPPEngine *imap) -{ - unsigned int id, len; - unsigned char *token, *p, c; - int tok; - struct _handler *h; - struct _status_info *sinfo; - - e(printf("got untagged response\n")); - id = 0; - tok = camel_imapp_stream_token(imap->stream, &token, &len); - if (tok == IMAP_TOK_INT) { - id = strtoul(token, NULL, 10); - tok = camel_imapp_stream_token(imap->stream, &token, &len); - } - - if (tok == '\n') - camel_exception_throw(1, "truncated server response"); - - e(printf("Have token '%s' id %d\n", token, id)); - p = token; - while ((c = *p)) - *p++ = toupper(c); - - /* first, check for generic unsolicited response */ - h = g_hash_table_lookup(imap->handlers, token); - if (h) { - tok = h->func(imap, id, h->data); - if (tok < 0) - return tok; - return 1; - } - - /* TODO: apart from bye/preauth, these could be callbacks/events? */ - - /* now, check for status responses */ - switch (imap_tokenise(token, len)) { - case IMAP_BYE: - case IMAP_OK: - case IMAP_NO: - case IMAP_BAD: - case IMAP_PREAUTH: - /* TODO: validate which ones of these can happen as unsolicited responses */ - /* TODO: handle bye/preauth differently */ - /* FIXME: free sinfo */ - camel_imapp_stream_ungettoken(imap->stream, tok, token, len); - sinfo = imap_parse_status(imap->stream); - camel_object_trigger_event(imap, "status", sinfo); - imap_free_status(sinfo); -#if 0 - switch(sinfo->condition) { - case IMAP_READ_WRITE: - printf("folder is read-write\n"); - break; - case IMAP_READ_ONLY: - printf("folder is read-only\n"); - break; - case IMAP_UIDVALIDITY: - if (imap->select_response) - imap->select_response->uidvalidity = sinfo->u.uidvalidity; - break; -#if 0 - /* not defined yet ... */ - case IMAP_UIDNEXT: - printf("got uidnext for folder: %d\n", sinfo->u.uidnext); - break; -#endif - case IMAP_UNSEEN: - if (imap->select_response) - imap->select_response->unseen = sinfo->u.unseen; - break; - case IMAP_PERMANENTFLAGS: - if (imap->select_response) - imap->select_response->permanentflags = sinfo->u.permanentflags; - break; - case IMAP_ALERT: - printf("ALERT!: %s\n", sinfo->text); - break; - case IMAP_PARSE: - printf("PARSE: %s\n", sinfo->text); - break; - default: - break; - } -#endif - break; - default: - printf("unknown token: %s\n", token); - camel_imapp_engine_skip(imap); - /* unknown response, just ignore it */ - } - - return 1; -} - -/* handle any continuation requests - either data continuations, or auth continuation */ -int -iterate_continuation(CamelIMAPPEngine *imap) -{ - CamelIMAPPCommand *ic; - CamelIMAPPCommandPart *cp; - - printf("got continuation response\n"); - - ic = imap->literal; - imap->literal = NULL; - if (ic == NULL) { - camel_imapp_engine_skip(imap); - printf("got continuation response with no outstanding continuation requests?\n"); - return 1; - } - - printf("got continuation response for data\n"); - cp = ic->current; - switch(cp->type & CAMEL_IMAPP_COMMAND_MASK) { - case CAMEL_IMAPP_COMMAND_DATAWRAPPER: - printf("writing data wrapper to literal\n"); - camel_data_wrapper_write_to_stream((CamelDataWrapper *)cp->ob, (CamelStream *)imap->stream); - break; - case CAMEL_IMAPP_COMMAND_STREAM: - printf("writing stream to literal\n"); - camel_stream_write_to_stream((CamelStream *)cp->ob, (CamelStream *)imap->stream); - break; - case CAMEL_IMAPP_COMMAND_AUTH: { - CamelException *ex = camel_exception_new(); - char *resp; - unsigned char *token; - int tok, len; - - tok = camel_imapp_stream_token(imap->stream, &token, &len); - resp = camel_sasl_challenge_base64((CamelSasl *)cp->ob, token, ex); - if (camel_exception_is_set(ex)) - camel_exception_throw_ex(ex); - camel_exception_free(ex); - - printf("got auth continuation, feeding token '%s' back to auth mech\n", resp); - - camel_stream_write((CamelStream *)imap->stream, resp, strlen(resp)); - - /* we want to keep getting called until we get a status reponse from the server - ignore what sasl tells us */ - imap->literal = ic; - - break; } - default: - /* should we just ignore? */ - camel_exception_throw(1, "continuation response for non-continuation request"); - } - - camel_imapp_engine_skip(imap); - - cp = cp->next; - if (cp->next) { - ic->current = cp; - printf("next part of command \"A%05u: %s\"\n", ic->tag, cp->data); - camel_stream_printf((CamelStream *)imap->stream, "%s\r\n", cp->data); - if (cp->type & CAMEL_IMAPP_COMMAND_CONTINUATION) { - imap->literal = ic; - } else { - g_assert(cp->next->next == NULL); - } - } else { - printf("%p: queueing continuation\n", ic); - camel_stream_printf((CamelStream *)imap->stream, "\r\n"); - } - - if (imap->literal == NULL) { - ic = (CamelIMAPPCommand *)e_dlist_remhead(&imap->queue); - if (ic) { - printf("found outstanding op, queueing\n"); - camel_imapp_engine_command_queue(imap, ic); - } - } - - return 1; -} - -/* handle a completion line */ -int -iterate_completion(CamelIMAPPEngine *imap, unsigned char *token) -{ - CamelIMAPPCommand *ic; - unsigned int tag; - - if (token[0] != imap->tagprefix) - camel_exception_throw(1, "Server sent unexpected response: %s", token); - - tag = strtoul(token+1, NULL, 10); - ic = camel_imapp_engine_command_find_tag(imap, tag); - if (ic) { - printf("Got completion response for command %05u '%s'\n", ic->tag, ic->name); - printf("%p: removing command from qwueue, we were at '%s'\n", ic, ic->current->data); - printf("%p: removing command\n", ic); - e_dlist_remove((EDListNode *)ic); - e_dlist_addtail(&imap->done, (EDListNode *)ic); - if (imap->literal == ic) - imap->literal = NULL; - ic->status = imap_parse_status(imap->stream); - printf("got response code: %s\n", ic->status->text); - - /* TODO: remove this stuff and use a completion handler? */ - /* TODO: handle 'SELECT' command cleanup here */ - /* FIXME: have this use tokeniser, have this handle close/logout/select etc as well */ - /* ok response from login/authenticate, then we're in happy land */ - if ((!strcmp(ic->name, "LOGIN") || !strcmp(ic->name, "AUTHENTICATE")) - && ic->status->result == IMAP_OK) - imap->state = IMAP_ENGINE_AUTH; - - if (ic->complete) - ic->complete(imap, ic, ic->complete_data); - } else { - camel_exception_throw(1, "got response tag unexpectedly: %s", token); - } - - if (imap->literal != NULL) { - printf("Warning: continuation command '%s' finished with outstanding continuation\n", imap->literal->name); - ic = imap->literal; - /* set the command complete with a failure code? */ - e_dlist_remove((EDListNode *)ic); - e_dlist_addtail(&imap->done, (EDListNode *)ic); - imap->literal = NULL; - } - - ic = (CamelIMAPPCommand *)e_dlist_remhead(&imap->queue); - if (ic) { - printf("found outstanding op, queueing\n"); - camel_imapp_engine_command_queue(imap, ic); - } - - return 1; -} - - -/* Do work if there's any to do */ -int -camel_imapp_engine_iterate(CamelIMAPPEngine *imap, CamelIMAPPCommand *icwait) -/* throws IO,PARSE exception */ -{ - unsigned int len; - unsigned char *token; - int tok; - - if ((icwait && icwait->status != NULL) || e_dlist_empty(&imap->active)) - return 0; - - /* handle exceptions here? */ - - /* lock here? */ - - tok = camel_imapp_stream_token(imap->stream, &token, &len); - if (tok == '*') - iterate_untagged(imap); - else if (tok == IMAP_TOK_TOKEN) - iterate_completion(imap, token); - else if (tok == '+') - iterate_continuation(imap); - else - camel_exception_throw(1, "unexpected server response: %s", token); - - if (e_dlist_empty(&imap->active)) - return 0; - - return 1; -} - -CamelIMAPPCommand * -camel_imapp_engine_command_new(CamelIMAPPEngine *imap, const char *name, const char *select, const char *fmt, ...) -{ - CamelIMAPPCommand *ic; - va_list ap; - - ic = g_malloc0(sizeof(*ic)); - ic->tag = imap->tag++; - ic->name = name; - ic->mem = (CamelStreamMem *)camel_stream_mem_new(); - ic->select = g_strdup(select); - e_dlist_init(&ic->parts); - - if (fmt && fmt[0]) { - va_start(ap, fmt); - imap_engine_command_addv(imap, ic, fmt, ap); - va_end(ap); - } - - return ic; -} - -void -camel_imapp_engine_command_add(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic, const char *fmt, ...) -{ - va_list ap; - - g_assert(ic->mem); /* gets reset on queue */ - - if (fmt && fmt[0]) { - va_start(ap, fmt); - imap_engine_command_addv(imap, ic, fmt, ap); - va_end(ap); - } -} - -void -camel_imapp_engine_command_complete(CamelIMAPPEngine *imap, struct _CamelIMAPPCommand *ic, CamelIMAPPCommandFunc func, void *data) -{ - ic->complete = func; - ic->complete_data = data; -} - -/* FIXME: make imap command's refcounted */ -void -camel_imapp_engine_command_free (CamelIMAPPEngine *imap, CamelIMAPPCommand *ic) -{ - CamelIMAPPCommandPart *cp, *cn; - - if (ic == NULL) - return; - - /* validity check - we cant' free items still in any queue ... */ - /* maybe we should just have another queue to keep them? */ - { - CamelIMAPPCommand *iw; - int found = 0; - - iw = (CamelIMAPPCommand *)imap->active.head; - while (iw->next) { - if (iw == ic) { - found = 1; - g_warning("command '%s' still in active queue", iw->name); - break; - } - iw = iw->next; - } - iw = (CamelIMAPPCommand *)imap->queue.head; - while (iw->next) { - if (iw == ic) { - found = 1; - g_warning("command '%s' still in waiting queue", iw->name); - break; - } - iw = iw->next; - } - iw = (CamelIMAPPCommand *)imap->done.head; - while (iw->next) { - if (iw == ic) { - found = 1; - break; - } - iw = iw->next; - } - if (!found) { - g_warning("command '%s' not found anywhere", ic->name); - abort(); - } - } - - e_dlist_remove((EDListNode *)ic); - - if (ic->mem) - camel_object_unref((CamelObject *)ic->mem); - imap_free_status(ic->status); - g_free(ic->select); - - cp = (CamelIMAPPCommandPart *)ic->parts.head; - cn = cp->next; - while (cn) { - g_free(cp->data); - if (cp->ob) - camel_object_unref(cp->ob); - g_free(cp); - cp = cn; - cn = cn->next; - } - - g_free(ic); -} - -/* FIXME: error handling */ -void -camel_imapp_engine_command_queue(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic) -{ - CamelIMAPPCommandPart *cp; - - if (ic->mem) - imap_engine_command_complete(imap, ic); - - /* FIXME: remove select stuff */ - - /* see if we need to pre-queue a select command to select the right folder first */ - if (ic->select && (imap->last_select == NULL || strcmp(ic->select, imap->last_select) != 0)) { - CamelIMAPPCommand *select; - - /* of course ... we can't do anything like store/search if we have to select - first, because it'll mess up all the sequence numbers ... hrm ... bugger */ - - select = camel_imapp_engine_command_new(imap, "SELECT", NULL, "SELECT %s", ic->select); - g_free(imap->last_select); - imap->last_select = g_strdup(ic->select); - camel_imapp_engine_command_queue(imap, select); - /* how does it get freed? handle inside engine? */ - } - - /* first, check if command can be sent yet ... queue if not */ - if (imap->literal != NULL) { - printf("%p: queueing while literal active\n", ic); - e_dlist_addtail(&imap->queue, (EDListNode *)ic); - return; - } - - cp = (CamelIMAPPCommandPart *)ic->parts.head; - g_assert(cp); - ic->current = cp; - - /* how to handle exceptions here? */ - - printf("queueing command \"%c%05u %s\"\n", imap->tagprefix, ic->tag, cp->data); - camel_stream_printf((CamelStream *)imap->stream, "%c%05u %s\r\n", imap->tagprefix, ic->tag, cp->data); - - if (cp->type & CAMEL_IMAPP_COMMAND_CONTINUATION) { - printf("%p: active literal\n", ic); - g_assert(cp->next); - imap->literal = ic; - e_dlist_addtail(&imap->active, (EDListNode *)ic); - } else { - printf("%p: active non-literal\n", ic); - g_assert(cp->next && cp->next->next == NULL); - e_dlist_addtail(&imap->active, (EDListNode *)ic); - } -} - -CamelIMAPPCommand * -camel_imapp_engine_command_find (CamelIMAPPEngine *imap, const char *name) -{ - CamelIMAPPCommand *ic, *in; - - ic = imap->literal; - if (ic && strcmp(ic->name, name) == 0) - return ic; - - /* first, try active */ - ic = (CamelIMAPPCommand *)imap->active.head; - in = ic->next; - while (in) { - if (strcmp(ic->name, name) == 0) - return ic; - ic = in; - in = in->next; - } - - return NULL; -} - -CamelIMAPPCommand * -camel_imapp_engine_command_find_tag(CamelIMAPPEngine *imap, unsigned int tag) -{ - CamelIMAPPCommand *ic, *in; - - ic = imap->literal; - if (ic && ic->tag == tag) - return ic; - - ic = (CamelIMAPPCommand *)imap->active.head; - in = ic->next; - while (in) { - if (ic->tag == tag) - return ic; - ic = in; - in = in->next; - } - - return NULL; -} - -/* ********************************************************************** */ - -CamelIMAPPSelectResponse * -camel_imapp_engine_select(CamelIMAPPEngine *imap, const char *name) -{ - CamelIMAPPSelectResponse * volatile resp; - CamelIMAPPCommand * volatile ic = NULL; - - resp = g_malloc0(sizeof(*resp)); - imap->select_response = resp; - - CAMEL_TRY { - ic = camel_imapp_engine_command_new(imap, "SELECT", NULL, "SELECT %s", name); - camel_imapp_engine_command_queue(imap, ic); - while (camel_imapp_engine_iterate(imap, ic) > 0) - ; - - if (ic->status->result != IMAP_OK) - camel_exception_throw(1, "select failed: %s", ic->status->text); - resp->status = ic->status; - ic->status = NULL; - } CAMEL_CATCH (e) { - camel_imapp_engine_command_free(imap, ic); - camel_imapp_engine_select_free(imap, resp); - imap->select_response = NULL; - camel_exception_throw_ex(e); - } CAMEL_DONE; - - camel_imapp_engine_command_free(imap, ic); - imap->select_response = NULL; - - return resp; -} - -void -camel_imapp_engine_select_free(CamelIMAPPEngine *imap, CamelIMAPPSelectResponse *select) -{ - if (select) { - imap_free_status(select->status); - g_free(select); - } -} - -/* ********************************************************************** */ - -static void -imap_engine_command_add_part(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic, camel_imapp_command_part_t type, CamelObject *ob) -{ - CamelIMAPPCommandPart *cp; - CamelStreamNull *null; - unsigned int ob_size = 0; - - switch(type & CAMEL_IMAPP_COMMAND_MASK) { - case CAMEL_IMAPP_COMMAND_DATAWRAPPER: - case CAMEL_IMAPP_COMMAND_STREAM: - null = (CamelStreamNull *)camel_stream_null_new(); - if ( (type & CAMEL_IMAPP_COMMAND_MASK) == CAMEL_IMAPP_COMMAND_DATAWRAPPER) { - camel_data_wrapper_write_to_stream((CamelDataWrapper *)ob, (CamelStream *)null); - } else { - camel_stream_reset((CamelStream *)ob); - camel_stream_write_to_stream((CamelStream *)ob, (CamelStream *)null); - camel_stream_reset((CamelStream *)ob); - } - type |= CAMEL_IMAPP_COMMAND_CONTINUATION; - camel_object_ref(ob); - ob_size = null->written; - camel_object_unref((CamelObject *)null); - camel_stream_printf((CamelStream *)ic->mem, "{%u}", ob_size); - break; - case CAMEL_IMAPP_COMMAND_AUTH: - /* we presume we'll need to get additional data only if we're not authenticated yet */ - camel_object_ref(ob); - camel_stream_printf((CamelStream *)ic->mem, "%s", ((CamelSasl *)ob)->mech); - if (!camel_sasl_authenticated((CamelSasl *)ob)) - type |= CAMEL_IMAPP_COMMAND_CONTINUATION; - break; - default: - ob_size = 0; - } - - cp = g_malloc0(sizeof(*cp)); - cp->type = type; - cp->ob_size = ob_size; - cp->ob = ob; - cp->data_size = ic->mem->buffer->len; - cp->data = g_malloc(cp->data_size+1); - memcpy(cp->data, ic->mem->buffer->data, cp->data_size); - cp->data[cp->data_size] = 0; - - camel_stream_reset((CamelStream *)ic->mem); - /* FIXME: hackish? */ - g_byte_array_set_size(ic->mem->buffer, 0); - - e_dlist_addtail(&ic->parts, (EDListNode *)cp); -} - -static int len(EDList *list) -{ - int count = 0; - EDListNode *n = list->head; - - while (n->next) { - n = n->next; - count++; - } - return count; -} - -static void -imap_engine_command_complete(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic) -{ - c(printf("completing command buffer is [%d] '%.*s'\n", ic->mem->buffer->len, (int)ic->mem->buffer->len, ic->mem->buffer->data)); - c(printf("command has %d parts\n", len(&ic->parts))); - if (ic->mem->buffer->len > 0) - imap_engine_command_add_part(imap, ic, CAMEL_IMAPP_COMMAND_SIMPLE, NULL); - - c(printf("command has %d parts\n", len(&ic->parts))); - - camel_object_unref((CamelObject *)ic->mem); - ic->mem = NULL; -} - -static void -imap_engine_command_addv(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic, const char *fmt, va_list ap) -{ - const unsigned char *p, *ps, *start; - unsigned char c; - unsigned int width; - char ch; - int llong; - int left; - int fill; - int zero; - char *s; - int d; - long int l; - guint32 f; - CamelStream *S; - CamelDataWrapper *D; - CamelSasl *A; - char buffer[16]; - - c(printf("adding command, fmt = '%s'\n", fmt)); - - p = fmt; - ps = fmt; - while ( ( c = *p++ ) ) { - switch(c) { - case '%': - if (*p == '%') { - camel_stream_write((CamelStream *)ic->mem, ps, p-ps); - p++; - ps = p; - } else { - camel_stream_write((CamelStream *)ic->mem, ps, p-ps-1); - start = p-1; - width = 0; - left = FALSE; - fill = FALSE; - zero = FALSE; - llong = FALSE; - - do { - c = *p++; - if (c == '0') - zero = TRUE; - else if ( c== '-') - left = TRUE; - else - break; - } while (c); - - do { - if (isdigit(c)) - width = width * 10 + (c-'0'); - else - break; - } while ((c = *p++)); - - if (c == 'l') { - llong = TRUE; - c = *p++; - } - - switch(c) { - case 'A': /* auth object - sasl auth, treat as special kind of continuation */ - A = va_arg(ap, CamelSasl *); - imap_engine_command_add_part(imap, ic, CAMEL_IMAPP_COMMAND_AUTH, (CamelObject *)A); - break; - case 'S': /* stream */ - S = va_arg(ap, CamelStream *); - c(printf("got stream '%p'\n", S)); - imap_engine_command_add_part(imap, ic, CAMEL_IMAPP_COMMAND_STREAM, (CamelObject *)S); - break; - case 'D': /* datawrapper */ - D = va_arg(ap, CamelDataWrapper *); - c(printf("got data wrapper '%p'\n", D)); - imap_engine_command_add_part(imap, ic, CAMEL_IMAPP_COMMAND_DATAWRAPPER, (CamelObject *)D); - break; - case 't': /* token */ - s = va_arg(ap, char *); - camel_stream_write((CamelStream *)ic->mem, s, strlen(s)); - break; - case 's': /* simple string */ - s = va_arg(ap, char *); - c(printf("got string '%s'\n", s)); - /* FIXME: escpae chars, convert to literal or literal+, etc */ - camel_stream_printf((CamelStream *)ic->mem, "\"%s\"", s); - break; - case 'f': /* imap folder name */ - s = va_arg(ap, char *); - c(printf("got folder '%s'\n", s)); - /* FIXME: encode folder name */ - /* FIXME: namespace? */ - camel_stream_printf((CamelStream *)ic->mem, "\"%s\"", s?s:""); - break; - case 'F': /* IMAP flags set */ - f = va_arg(ap, guint32); - imap_write_flags((CamelStream *)ic->mem, f); - break; - case 'c': - d = va_arg(ap, int); - ch = d; - camel_stream_write((CamelStream *)ic->mem, &ch, 1); - break; - case 'd': /* int/unsigned */ - case 'u': - if (llong) { - l = va_arg(ap, long int); - c(printf("got long int '%d'\n", (int)l)); - memcpy(buffer, start, p-start); - buffer[p-start] = 0; - camel_stream_printf((CamelStream *)ic->mem, buffer, l); - } else { - d = va_arg(ap, int); - c(printf("got int '%d'\n", d)); - memcpy(buffer, start, p-start); - buffer[p-start] = 0; - camel_stream_printf((CamelStream *)ic->mem, buffer, d); - } - break; - } - - ps = p; - } - break; - case '\\': /* only for \\ really, we dont support \n\r etc at all */ - c = *p; - if (c) { - g_assert(c == '\\'); - camel_stream_write((CamelStream *)ic->mem, ps, p-ps); - p++; - ps = p; - } - } - } - - camel_stream_write((CamelStream *)ic->mem, ps, p-ps-1); -} - - -/* here temporarily while its experimental */ - - -#ifdef ENABLE_THREADS -#include - -static pthread_key_t handler_key = 0; - -void camel_exception_setup(void) -{ - pthread_key_create(&handler_key, NULL); -} - -#else -/* this is per-thread in threaded mode */ -static struct _CamelExceptionEnv *handler = NULL; - -void camel_exception_setup(void) -{ -} -#endif - -void -camel_exception_try(struct _CamelExceptionEnv *env) -{ -#ifdef ENABLE_THREADS - struct _CamelExceptionEnv *handler; - - handler = pthread_getspecific(handler_key); -#endif - env->parent = handler; - handler = env; - env->ex = NULL; - -#ifdef ENABLE_THREADS - pthread_setspecific(handler_key, handler); -#endif -} - -void -camel_exception_throw_ex(CamelException *ex) -{ - struct _CamelExceptionEnv *env; -#ifdef ENABLE_THREADS - struct _CamelExceptionEnv *handler; - - handler = pthread_getspecific(handler_key); -#endif - printf("throwing exception '%s'\n", ex->desc); - - env = handler; - if (env != NULL) { - env->ex = ex; - handler = env->parent; -#ifdef ENABLE_THREADS - pthread_setspecific(handler_key, handler); -#endif - longjmp(env->env, ex->id); - } else { - g_warning("Uncaught exception: %s\n", ex->desc); - /* we just crash and burn, this is a code problem */ - /* we dont use g_assert_not_reached() since its not a noreturn function */ - abort(); - } -} - -void -camel_exception_throw(int id, char *fmt, ...) -{ - CamelException *ex; - va_list ap; - - ex = camel_exception_new(); - ex->id = id; - va_start(ap, fmt); - ex->desc = g_strdup_vprintf(fmt, ap); - va_end(ap); - - camel_exception_throw_ex(ex); -} - -void -camel_exception_drop(struct _CamelExceptionEnv *env) -{ -#ifdef ENABLE_THREADS - pthread_setspecific(handler_key, env->parent); -#else - handler = env->parent; -#endif -} - -void -camel_exception_done(struct _CamelExceptionEnv *env) -{ -#ifdef ENABLE_THREADS - pthread_setspecific(handler_key, env->parent); -#else - handler = env->parent; -#endif - if (env->ex != NULL) { - camel_exception_free(env->ex); - } -} diff --git a/camel/providers/imapp/camel-imapp-engine.h b/camel/providers/imapp/camel-imapp-engine.h deleted file mode 100644 index 5f74d0654a..0000000000 --- a/camel/providers/imapp/camel-imapp-engine.h +++ /dev/null @@ -1,155 +0,0 @@ - -#ifndef _CAMEL_IMAPP_ENGINE_H -#define _CAMEL_IMAPP_ENGINE_H - -#include - -#include "camel-imapp-stream.h" -#include -#include "camel-imapp-folder.h" - -#define CAMEL_IMAPP_ENGINE_TYPE (camel_imapp_engine_get_type ()) -#define CAMEL_IMAPP_ENGINE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAPP_ENGINE_TYPE, CamelIMAPPEngine)) -#define CAMEL_IMAPP_ENGINE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAPP_ENGINE_TYPE, CamelIMAPPEngineClass)) -#define CAMEL_IS_IMAP_ENGINE(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAPP_ENGINE_TYPE)) - -typedef struct _CamelIMAPPEngine CamelIMAPPEngine; -typedef struct _CamelIMAPPEngineClass CamelIMAPPEngineClass; - -typedef struct _CamelIMAPPCommandPart CamelIMAPPCommandPart; -typedef struct _CamelIMAPPCommand CamelIMAPPCommand; - -typedef enum { - CAMEL_IMAPP_COMMAND_SIMPLE = 0, - CAMEL_IMAPP_COMMAND_DATAWRAPPER, - CAMEL_IMAPP_COMMAND_STREAM, - CAMEL_IMAPP_COMMAND_AUTH, - CAMEL_IMAPP_COMMAND_MASK = 0xff, - CAMEL_IMAPP_COMMAND_CONTINUATION = 0x8000 /* does this command expect continuation? */ -} camel_imapp_command_part_t; - -struct _CamelIMAPPCommandPart { - struct _CamelIMAPPCommandPart *next; - struct _CamelIMAPPCommandPart *prev; - - struct _CamelIMAPPCommand *parent; - - int data_size; - char *data; - - camel_imapp_command_part_t type; - - int ob_size; - CamelObject *ob; -}; - -typedef int (*CamelIMAPPEngineFunc)(struct _CamelIMAPPEngine *engine, guint32 id, void *data); -typedef void (*CamelIMAPPCommandFunc)(struct _CamelIMAPPEngine *engine, struct _CamelIMAPPCommand *, void *data); - -/* FIXME: make this refcounted */ -struct _CamelIMAPPCommand { - struct _CamelIMAPPCommand *next; - struct _CamelIMAPPCommand *prev; - - const char *name; /* command name/type (e.g. FETCH) */ - - /* FIXME: remove this select stuff */ - char *select; /* if we need to run against a specific folder */ - struct _status_info *status; /* status for command, indicates it is complete if != NULL */ - - unsigned int tag; - - struct _CamelStreamMem *mem; /* for building the part */ - EDList parts; - CamelIMAPPCommandPart *current; - - CamelIMAPPCommandFunc complete; - void *complete_data; -}; - -typedef struct _CamelIMAPPSelectResponse CamelIMAPPSelectResponse; - -struct _CamelIMAPPSelectResponse { - struct _status_info *status; - guint32 exists; - guint32 recent; - guint32 uidvalidity; - guint32 unseen; - guint32 permanentflags; -}; - -enum { - IMAP_CAPABILITY_IMAP4 = (1 << 0), - IMAP_CAPABILITY_IMAP4REV1 = (1 << 1), - IMAP_CAPABILITY_STATUS = (1 << 2), - IMAP_CAPABILITY_NAMESPACE = (1 << 3), - IMAP_CAPABILITY_UIDPLUS = (1 << 4), - IMAP_CAPABILITY_LITERALPLUS = (1 << 5), - IMAP_CAPABILITY_STARTTLS = (1 << 6), -}; - -/* currently selected states */ -typedef enum _camel_imapp_engine_state_t { - IMAP_ENGINE_DISCONNECT, /* only happens during shutdown */ - IMAP_ENGINE_CONNECT, /* connected, not authenticated */ - IMAP_ENGINE_AUTH, /* connected, and authenticated */ - IMAP_ENGINE_SELECT, /* and selected, select holds selected folder */ -} camel_imapp_engine_state_t; - -struct _CamelIMAPPEngine { - CamelObject parent_object; - - CamelIMAPPStream *stream; - - camel_imapp_engine_state_t state; - - guint32 capa; /* capabilities for this server, refresh with :capabilities() */ - - GHashTable *handlers; - - unsigned char tagprefix; /* out tag prefix 'A' 'B' ... 'Z' */ - unsigned int tag; /* next command tag */ - - char *select; /* *currently* selected folder */ - char *last_select; /* last selected or to-be selected folder (e.g. outstanding queued select) */ - CamelIMAPPCommand *literal;/* current literal op */ - EDList active; /* active queue */ - EDList queue; /* outstanding queue */ - EDList done; /* done queue, awaiting reclamation */ - - /* keep track of running a select */ - struct _CamelIMAPPSelectResponse *select_response; -}; - -struct _CamelIMAPPEngineClass { - CamelObjectClass parent_class; - - unsigned char tagprefix; - - /* Events: - status(struct _status_info *); - */ -}; - -CamelType camel_imapp_engine_get_type (void); - -CamelIMAPPEngine *camel_imapp_engine_new(CamelIMAPPStream *stream); - -void camel_imapp_engine_add_handler(CamelIMAPPEngine *imap, const char *response, CamelIMAPPEngineFunc func, void *data); -int camel_imapp_engine_iterate(CamelIMAPPEngine *imap, CamelIMAPPCommand *wait); /* throws PARSE,IO exception */ -int camel_imapp_engine_skip(CamelIMAPPEngine *imap); -int camel_imapp_engine_capabilities(CamelIMAPPEngine *imap); - -CamelIMAPPCommand *camel_imapp_engine_command_new (CamelIMAPPEngine *imap, const char *name, const char *select, const char *fmt, ...); -void camel_imapp_engine_command_complete(CamelIMAPPEngine *imap, struct _CamelIMAPPCommand *, CamelIMAPPCommandFunc func, void *data); -void camel_imapp_engine_command_add (CamelIMAPPEngine *imap, CamelIMAPPCommand *ic, const char *fmt, ...); -void camel_imapp_engine_command_free (CamelIMAPPEngine *imap, CamelIMAPPCommand *ic); -void camel_imapp_engine_command_queue(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic); /* throws IO exception */ -CamelIMAPPCommand *camel_imapp_engine_command_find (CamelIMAPPEngine *imap, const char *name); -CamelIMAPPCommand *camel_imapp_engine_command_find_tag(CamelIMAPPEngine *imap, unsigned int tag); - -/* util functions */ -CamelIMAPPSelectResponse *camel_imapp_engine_select(CamelIMAPPEngine *imap, const char *name); -void camel_imapp_engine_select_free(CamelIMAPPEngine *imap, CamelIMAPPSelectResponse *select); - -#endif diff --git a/camel/providers/imapp/camel-imapp-exception.h b/camel/providers/imapp/camel-imapp-exception.h deleted file mode 100644 index 5e18b6c815..0000000000 --- a/camel/providers/imapp/camel-imapp-exception.h +++ /dev/null @@ -1,35 +0,0 @@ - -/* This implements 'real' exceptions that work a bit like c++/java exceptions */ - -/* Still experimental code */ - -#ifndef __CAMEL_IMAPP_EXCEPTION_H -#define __CAMEL_IMAPP_EXCEPTION_H - -#include -#include "camel/camel-exception.h" - -struct _CamelExceptionEnv { - struct _CamelExceptionEnv *parent; - CamelException *ex; - jmp_buf env; -}; - -#define CAMEL_TRY { struct _CamelExceptionEnv __env; camel_exception_try(&__env); if (setjmp(__env.env) == 0) -#define CAMEL_IGNORE camel_exception_done(&__env); } -#define CAMEL_CATCH(x) { CamelException *x; x=__env.ex; if (x != NULL) -#define CAMEL_DONE } camel_exception_done(&__env); } -#define CAMEL_DROP() camel_exception_drop(&__env) - -void camel_exception_setup(void); - -/* internal functions, use macro's above */ -void camel_exception_try(struct _CamelExceptionEnv *env); -void camel_exception_done(struct _CamelExceptionEnv *env); -void camel_exception_drop(struct _CamelExceptionEnv *env); - -/* user functions */ -void camel_exception_throw_ex(CamelException *ex) __attribute__ ((noreturn)); -void camel_exception_throw(int id, char *fmt, ...) __attribute__ ((noreturn)); - -#endif diff --git a/camel/providers/imapp/camel-imapp-fetch-stream.c b/camel/providers/imapp/camel-imapp-fetch-stream.c deleted file mode 100644 index bf18aac57b..0000000000 --- a/camel/providers/imapp/camel-imapp-fetch-stream.c +++ /dev/null @@ -1,183 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Author: - * Michael Zucchi - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include - -#include - -#include "camel-imapp-stream.h" -#include "camel-imapp-exception.h" - -#define t(x) -#define io(x) x - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelStream */ -#define CS_CLASS(so) CAMEL_IMAPP_FETCH_STREAM_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -static ssize_t -stream_read(CamelStream *stream, char *buffer, size_t n) -{ - CamelIMAPPFetchStream *is = (CamelIMAPPFetchStream *)stream; - ssize_t max; - - /* make sure we have all the data read in */ - while (camel_imapp_engine_iterate(is->engine, is->command)>0) - ; - - if (is->literal == 0 || n == 0) - return 0; - - max = is->end - is->ptr; - if (max > 0) { - max = MIN(max, is->literal); - max = MIN(max, n); - memcpy(buffer, is->ptr, max); - is->ptr += max; - } else { - max = MIN(is->literal, n); - max = camel_stream_read(is->source, buffer, max); - if (max <= 0) - return max; - } - - is->literal -= max; - - return max; -} - -static ssize_t -stream_write(CamelStream *stream, const char *buffer, size_t n) -{ - CamelIMAPPFetchStream *is = (CamelIMAPPFetchStream *)stream; - - return camel_stream_write(is->source, buffer, n); -} - -static int -stream_close(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static int -stream_flush(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static gboolean -stream_eos(CamelStream *stream) -{ - CamelIMAPPFetchStream *is = (CamelIMAPPFetchStream *)stream; - - return is->literal == 0; -} - -static int -stream_reset(CamelStream *stream) -{ - /* nop? reset literal mode? */ - return 0; -} - -static void -camel_imapp_fetch_stream_class_init (CamelStreamClass *camel_imapp_fetch_stream_class) -{ - CamelStreamClass *camel_stream_class = (CamelStreamClass *)camel_imapp_fetch_stream_class; - - parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE ); - - /* virtual method definition */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->close = stream_close; - camel_stream_class->flush = stream_flush; - camel_stream_class->eos = stream_eos; - camel_stream_class->reset = stream_reset; -} - -static void -camel_imapp_fetch_stream_init(CamelIMAPPFetchStream *is, CamelIMAPPFetchStreamClass *isclass) -{ - ; -} - -static void -camel_imapp_fetch_stream_finalise(CamelIMAPPFetchStream *is) -{ - if (is->engine) - camel_object_unref(is->engine); -} - -CamelType -camel_imapp_fetch_stream_get_type (void) -{ - static CamelType camel_imapp_fetch_stream_type = CAMEL_INVALID_TYPE; - - if (camel_imapp_fetch_stream_type == CAMEL_INVALID_TYPE) { - setup_table(); - camel_imapp_fetch_stream_type = camel_type_register( camel_stream_get_type(), - "CamelIMAPPFetchStream", - sizeof( CamelIMAPPFetchStream ), - sizeof( CamelIMAPPFetchStreamClass ), - (CamelObjectClassInitFunc) camel_imapp_fetch_stream_class_init, - NULL, - (CamelObjectInitFunc) camel_imapp_fetch_stream_init, - (CamelObjectFinalizeFunc) camel_imapp_fetch_stream_finalise ); - } - - return camel_imapp_fetch_stream_type; -} - -/** - * camel_imapp_fetch_stream_new: - * - * Return value: the stream - **/ -CamelStream * -camel_imapp_fetch_stream_new(CamelIMAPPEngine *ie, const char *uid, const char *body) -{ - CamelIMAPPFetchStream *is; - - is = (CamelIMAPPFetchStream *)camel_object_new(camel_imapp_fetch_stream_get_type ()); - is->engine = ie; - camel_object_ref(ie); - - is->command = camel_imapp_engine_command_new(ie, "FETCH", NULL, "FETCH %t (BODY[%t]<0.4096>", uid, body); - camel_imapp_engine_command_queue(ie, command); - - return (CamelStream *)is; -} - diff --git a/camel/providers/imapp/camel-imapp-fetch-stream.h b/camel/providers/imapp/camel-imapp-fetch-stream.h deleted file mode 100644 index c9281ff64f..0000000000 --- a/camel/providers/imapp/camel-imapp-fetch-stream.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_IMAPP_FETCH_STREAM_H -#define _CAMEL_IMAPP_FETCH_STREAM_H - -#include - -#define CAMEL_IMAPP_FETCH_STREAM(obj) CAMEL_CHECK_CAST (obj, camel_imapp_fetch_stream_get_type (), CamelIMAPPFetchStream) -#define CAMEL_IMAPP_FETCH_STREAM_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imapp_fetch_stream_get_type (), CamelIMAPPFetchStreamClass) -#define CAMEL_IS_IMAP_FETCH_STREAM(obj) CAMEL_CHECK_TYPE (obj, camel_imapp_fetch_stream_get_type ()) - -typedef struct _CamelIMAPPFetchStreamClass CamelIMAPPFetchStreamClass; -typedef struct _CamelIMAPPFetchStream CamelIMAPPFetchStream; - -struct _CamelIMAPPFetchStream { - CamelStream parent; - - struct _CamelIMAPPEngine *engine; -}; - -struct _CamelIMAPPFetchStreamClass { - CamelStreamClass parent_class; -}; - -CamelType camel_imapp_fetch_stream_get_type (void); - -CamelStream *camel_imapp_fetch_stream_new (struct _CamelIMAPPEngine *src, const char *uid, const char *spec); - -#endif /* ! _CAMEL_IMAPP_FETCH_STREAM_H */ diff --git a/camel/providers/imapp/camel-imapp-folder.c b/camel/providers/imapp/camel-imapp-folder.c deleted file mode 100644 index 967ab541f6..0000000000 --- a/camel/providers/imapp/camel-imapp-folder.c +++ /dev/null @@ -1,269 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-folder.c : class for a imap folder */ - -/* - * Authors: Michael Zucchi - * - * Copyright (C) 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "camel/camel-exception.h" -#include "camel/camel-stream-mem.h" -#include "camel/camel-stream-filter.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-operation.h" -#include "camel/camel-data-cache.h" -#include "camel/camel-session.h" -#include "camel/camel-file-utils.h" - -#include "camel-imapp-store.h" -#include "camel-imapp-folder.h" -#include "camel-imapp-summary.h" -#include "camel-imapp-exception.h" - -#include - -#include -#include - -#define d(x) - -#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o))) -static CamelFolderClass *parent_class; - -static void imap_finalize (CamelObject *object); -static void imap_refresh_info (CamelFolder *folder, CamelException *ex); -static void imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex); -static CamelMimeMessage *imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex); - -static void -imap_folder_class_init (CamelIMAPPFolderClass *camel_imapp_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_imapp_folder_class); - - parent_class = CAMEL_FOLDER_CLASS(camel_folder_get_type()); - - /* virtual method overload */ - camel_folder_class->refresh_info = imap_refresh_info; - camel_folder_class->sync = imap_sync; - - camel_folder_class->get_message = imap_get_message; - /*camel_folder_class->set_message_flags = imap_set_message_flags;*/ -} - -static void -imap_folder_init(CamelObject *o, CamelObjectClass *klass) -{ - CamelFolder *folder = (CamelFolder *)o; - CamelIMAPPFolder *ifolder = (CamelIMAPPFolder *)o; - - folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | - CAMEL_FOLDER_HAS_SEARCH_CAPABILITY); - - folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | - CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_DRAFT | - CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_USER; - - /* FIXME: this is just a skeleton */ - - ifolder->changes = camel_folder_change_info_new(); -} - -CamelType -camel_imapp_folder_get_type (void) -{ - static CamelType camel_imapp_folder_type = CAMEL_INVALID_TYPE; - - if (!camel_imapp_folder_type) { - camel_imapp_folder_type = camel_type_register (CAMEL_FOLDER_TYPE, "CamelIMAPPFolder", - sizeof (CamelIMAPPFolder), - sizeof (CamelIMAPPFolderClass), - (CamelObjectClassInitFunc) imap_folder_class_init, - NULL, - imap_folder_init, - (CamelObjectFinalizeFunc) imap_finalize); - } - - return camel_imapp_folder_type; -} - -void -imap_finalize (CamelObject *object) -{ - CamelIMAPPFolder *folder = (CamelIMAPPFolder *)object; - - camel_folder_change_info_free(folder->changes); -} - -CamelFolder * -camel_imapp_folder_new(CamelStore *store, const char *path) -{ - CamelFolder *folder; - char *root; - - d(printf("opening imap folder '%s'\n", path)); - - folder = CAMEL_FOLDER (camel_object_new (CAMEL_IMAPP_FOLDER_TYPE)); - camel_folder_construct(folder, store, path, path); - - ((CamelIMAPPFolder *)folder)->raw_name = g_strdup(path); - - folder->summary = camel_imapp_summary_new(); - - root = camel_session_get_storage_path(((CamelService *)store)->session, (CamelService *)store, NULL); - if (root) { - char *base = g_build_filename(root, path, NULL); - char *file = g_build_filename(base, ".ev-summary", NULL); - - camel_mkdir(base, 0777); - g_free(base); - - camel_folder_summary_set_filename(folder->summary, file); - printf("loading summary from '%s' (root=%s)\n", file, root); - g_free(file); - camel_folder_summary_load(folder->summary); - g_free(root); - } - - return folder; -} - -void -camel_imapp_folder_open(CamelIMAPPFolder *folder, CamelException *ex) -{ - /* */ -} - -void -camel_imapp_folder_delete(CamelIMAPPFolder *folder, CamelException *ex) -{ -} - -void -camel_imapp_folder_rename(CamelIMAPPFolder *folder, const char *new, CamelException *ex) -{ -} - -void -camel_imapp_folder_close(CamelIMAPPFolder *folder, CamelException *ex) -{ -} - -static void -imap_refresh_info (CamelFolder *folder, CamelException *ex) -{ - printf("imapp refresh info?\n"); -} - -static void -imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - camel_imapp_driver_sync(((CamelIMAPPStore *)(folder->parent_store))->driver, expunge, (CamelIMAPPFolder *) folder); -} - -static CamelMimeMessage * -imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex) -{ - CamelMimeMessage * volatile msg = NULL; - CamelStream * volatile stream = NULL; - - printf("get message '%s'\n", uid); - - CAMEL_TRY { - /* simple implementation, just get whole message in 1 go */ - stream = camel_imapp_driver_fetch(((CamelIMAPPStore *)(folder->parent_store))->driver, (CamelIMAPPFolder *)folder, uid, ""); - camel_stream_reset(stream); - msg = camel_mime_message_new(); - if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)msg, stream) != -1) { - /* do we care? */ - } - } CAMEL_CATCH(e) { - if (msg) - camel_object_unref(msg); - msg = NULL; - camel_exception_xfer(ex, e); - } CAMEL_DONE; - - if (stream) - camel_object_unref(stream); - - return msg; -} - - -/* Algorithm for selecting a folder: - - - If uidvalidity == old uidvalidity - and exsists == old exists - and recent == old recent - and unseen == old unseen - Assume our summary is correct - for each summary item - mark the summary item as 'old/not updated' - rof - fetch flags from 1:* - for each fetch response - info = summary[index] - if info.uid != uid - info = summary_by_uid[uid] - fi - if info == NULL - create new info @ index - fi - if got.flags - update flags - fi - if got.header - update based on header - mark as retrieved - else if got.body - update based on imap body - mark as retrieved - fi - - Async fetch response: - info = summary[index] - if info == null - if uid == null - force resync/select? - info = empty @ index - else if uid && info.uid != uid - force a resync? - return - fi - - if got.flags { - info.flags = flags - } - if got.header { - info.init(header) - info.empty = false - } - -info.state - 2 bit field in flags - 0 = empty, nothing set - 1 = uid & flags set - 2 = update required - 3 = up to date -*/ - diff --git a/camel/providers/imapp/camel-imapp-folder.h b/camel/providers/imapp/camel-imapp-folder.h deleted file mode 100644 index 329c66b7fc..0000000000 --- a/camel/providers/imapp/camel-imapp-folder.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-folder.h : Class for a IMAP folder */ - -/* - * Authors: Michael Zucchi - * - * Copyright (C) 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_IMAPP_FOLDER_H -#define CAMEL_IMAPP_FOLDER_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include - -#define CAMEL_IMAPP_FOLDER_TYPE (camel_imapp_folder_get_type ()) -#define CAMEL_IMAPP_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAPP_FOLDER_TYPE, CamelIMAPPFolder)) -#define CAMEL_IMAPP_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAPP_FOLDER_TYPE, CamelIMAPPFolderClass)) -#define CAMEL_IS_IMAP_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAPP_FOLDER_TYPE)) - -typedef struct _CamelIMAPPFolder { - CamelFolder parent_object; - - char *raw_name; - CamelFolderChangeInfo *changes; - - guint32 exists; - guint32 recent; - guint32 uidvalidity; - guint32 unseen; - guint32 permanentflags; -} CamelIMAPPFolder; - -typedef struct _CamelIMAPPFolderClass { - CamelFolderClass parent_class; -} CamelIMAPPFolderClass; - -/* Standard Camel function */ -CamelType camel_imapp_folder_get_type (void); - -/* public methods */ -CamelFolder *camel_imapp_folder_new(CamelStore *parent, const char *path); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_IMAPP_FOLDER_H */ diff --git a/camel/providers/imapp/camel-imapp-provider.c b/camel/providers/imapp/camel-imapp-provider.c deleted file mode 100644 index 6b0cdd2d43..0000000000 --- a/camel/providers/imapp/camel-imapp-provider.c +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-pop3-provider.c: pop3 provider registration code */ - -/* - * Authors : - * Dan Winship - * Michael Zucchi - * - * Copyright (C) 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "camel/camel-provider.h" -#include "camel/camel-session.h" -#include "camel/camel-url.h" -#include "camel/camel-sasl.h" - -#include "camel-imapp-store.h" - -CamelProviderConfEntry imapp_conf_entries[] = { - { CAMEL_PROVIDER_CONF_SECTION_START, NULL, NULL, - N_("Message storage") }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider imapp_provider = { - "imapp", - - N_("IMAP+"), - - N_("Experimental IMAP 4(.1) client\n" - "This is untested and unsupported code, you want to use plain imap instead.\n\n" - " !!! DO NOT USE THIS FOR PRODUCTION EMAIL !!!\n"), - "mail", - - CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE | - CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL, - - CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH, - - imapp_conf_entries, - - /* ... */ -}; - -CamelServiceAuthType camel_imapp_password_authtype = { - N_("Password"), - - N_("This option will connect to the IMAP server using a " - "plaintext password."), - - "", - TRUE -}; - -void -camel_imapp_module_init(CamelSession *session) -{ - extern void camel_exception_setup(void); - - imapp_provider.object_types[CAMEL_PROVIDER_STORE] = camel_imapp_store_get_type(); - imapp_provider.url_hash = camel_url_hash; - imapp_provider.url_equal = camel_url_equal; - - imapp_provider.authtypes = g_list_prepend(imapp_provider.authtypes, camel_sasl_authtype_list(FALSE)); - imapp_provider.authtypes = g_list_prepend(imapp_provider.authtypes, &camel_imapp_password_authtype); - - /* blah ... could just use it in object setup? */ - /* TEMPORARY */ - camel_exception_setup(); - - camel_session_register_provider(session, &imapp_provider); -} - -void -camel_provider_module_init(CamelSession *session) -{ - camel_imapp_module_init(session); -} diff --git a/camel/providers/imapp/camel-imapp-store-summary.c b/camel/providers/imapp/camel-imapp-store-summary.c deleted file mode 100644 index a3ad57fb11..0000000000 --- a/camel/providers/imapp/camel-imapp-store-summary.c +++ /dev/null @@ -1,616 +0,0 @@ -/* - * Copyright (C) 2002 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "camel-imapp-store-summary.h" - -#include "camel/camel-file-utils.h" - -#include "camel-string-utils.h" -#include "e-util/md5-utils.h" -#include "e-util/e-memory.h" - -#include "camel-private.h" -#include "camel-utf8.h" - -#define d(x) -#define io(x) /* io debug */ - -#define CAMEL_IMAPP_STORE_SUMMARY_VERSION_0 (0) - -#define CAMEL_IMAPP_STORE_SUMMARY_VERSION (0) - -#define _PRIVATE(o) (((CamelIMAPPStoreSummary *)(o))->priv) - -static int summary_header_load(CamelStoreSummary *, FILE *); -static int summary_header_save(CamelStoreSummary *, FILE *); - -/*static CamelStoreInfo * store_info_new(CamelStoreSummary *, const char *);*/ -static CamelStoreInfo * store_info_load(CamelStoreSummary *, FILE *); -static int store_info_save(CamelStoreSummary *, FILE *, CamelStoreInfo *); -static void store_info_free(CamelStoreSummary *, CamelStoreInfo *); - -static const char *store_info_string(CamelStoreSummary *, const CamelStoreInfo *, int); -static void store_info_set_string(CamelStoreSummary *, CamelStoreInfo *, int, const char *); - -static void camel_imapp_store_summary_class_init (CamelIMAPPStoreSummaryClass *klass); -static void camel_imapp_store_summary_init (CamelIMAPPStoreSummary *obj); -static void camel_imapp_store_summary_finalise (CamelObject *obj); - -static CamelStoreSummaryClass *camel_imapp_store_summary_parent; - -static void -camel_imapp_store_summary_class_init (CamelIMAPPStoreSummaryClass *klass) -{ - CamelStoreSummaryClass *ssklass = (CamelStoreSummaryClass *)klass; - - ssklass->summary_header_load = summary_header_load; - ssklass->summary_header_save = summary_header_save; - - /*ssklass->store_info_new = store_info_new;*/ - ssklass->store_info_load = store_info_load; - ssklass->store_info_save = store_info_save; - ssklass->store_info_free = store_info_free; - - ssklass->store_info_string = store_info_string; - ssklass->store_info_set_string = store_info_set_string; -} - -static void -camel_imapp_store_summary_init (CamelIMAPPStoreSummary *s) -{ - /*struct _CamelIMAPPStoreSummaryPrivate *p; - - p = _PRIVATE(s) = g_malloc0(sizeof(*p));*/ - - ((CamelStoreSummary *)s)->store_info_size = sizeof(CamelIMAPPStoreInfo); - s->version = CAMEL_IMAPP_STORE_SUMMARY_VERSION; -} - -static void -camel_imapp_store_summary_finalise (CamelObject *obj) -{ - /*struct _CamelIMAPPStoreSummaryPrivate *p;*/ - /*CamelIMAPPStoreSummary *s = (CamelIMAPPStoreSummary *)obj;*/ - - /*p = _PRIVATE(obj); - g_free(p);*/ -} - -CamelType -camel_imapp_store_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - camel_imapp_store_summary_parent = (CamelStoreSummaryClass *)camel_store_summary_get_type(); - type = camel_type_register((CamelType)camel_imapp_store_summary_parent, "CamelIMAPPStoreSummary", - sizeof (CamelIMAPPStoreSummary), - sizeof (CamelIMAPPStoreSummaryClass), - (CamelObjectClassInitFunc) camel_imapp_store_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_imapp_store_summary_init, - (CamelObjectFinalizeFunc) camel_imapp_store_summary_finalise); - } - - return type; -} - -/** - * camel_imapp_store_summary_new: - * - * Create a new CamelIMAPPStoreSummary object. - * - * Return value: A new CamelIMAPPStoreSummary widget. - **/ -CamelIMAPPStoreSummary * -camel_imapp_store_summary_new (void) -{ - CamelIMAPPStoreSummary *new = CAMEL_IMAPP_STORE_SUMMARY ( camel_object_new (camel_imapp_store_summary_get_type ())); - - return new; -} - -/** - * camel_imapp_store_summary_full_name: - * @s: - * @path: - * - * Retrieve a summary item by full name. - * - * A referenced to the summary item is returned, which may be - * ref'd or free'd as appropriate. - * - * Return value: The summary item, or NULL if the @full_name name - * is not available. - * It must be freed using camel_store_summary_info_free(). - **/ -CamelIMAPPStoreInfo * -camel_imapp_store_summary_full_name(CamelIMAPPStoreSummary *s, const char *full_name) -{ - int count, i; - CamelIMAPPStoreInfo *info; - - count = camel_store_summary_count((CamelStoreSummary *)s); - for (i=0;ifull_name, full_name) == 0) - return info; - camel_store_summary_info_free((CamelStoreSummary *)s, (CamelStoreInfo *)info); - } - } - - return NULL; -} - -char * -camel_imapp_store_summary_full_to_path(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep) -{ - char *path, *p; - int c; - const char *f; - - if (dir_sep != '/') { - p = path = alloca(strlen(full_name)*3+1); - f = full_name; - while ( (c = *f++ & 0xff) ) { - if (c == dir_sep) - *p++ = '/'; - else if (c == '/' || c == '%') - p += sprintf(p, "%%%02X", c); - else - *p++ = c; - } - *p = 0; - } else - path = (char *)full_name; - - return camel_utf7_utf8(path); -} - -static guint32 hexnib(guint32 c) -{ - if (c >= '0' && c <= '9') - return c-'0'; - else if (c>='A' && c <= 'Z') - return c-'A'+10; - else - return 0; -} - -char * -camel_imapp_store_summary_path_to_full(CamelIMAPPStoreSummary *s, const char *path, char dir_sep) -{ - unsigned char *full, *f; - guint32 c, v = 0; - const char *p; - int state=0; - char *subpath, *last = NULL; - CamelStoreInfo *si; - CamelIMAPPStoreNamespace *ns; - - /* check to see if we have a subpath of path already defined */ - subpath = alloca(strlen(path)+1); - strcpy(subpath, path); - do { - si = camel_store_summary_path((CamelStoreSummary *)s, subpath); - if (si == NULL) { - last = strrchr(subpath, '/'); - if (last) - *last = 0; - } - } while (si == NULL && last); - - /* path is already present, use the raw version we have */ - if (si && strlen(subpath) == strlen(path)) { - f = g_strdup(camel_imapp_store_info_full_name(s, si)); - camel_store_summary_info_free((CamelStoreSummary *)s, si); - return f; - } - - ns = camel_imapp_store_summary_namespace_find_path(s, path); - - f = full = alloca(strlen(path)*2+1); - if (si) - p = path + strlen(subpath); - else if (ns) - p = path + strlen(ns->path); - else - p = path; - - while ( (c = camel_utf8_getc((const unsigned char **)&p)) ) { - switch(state) { - case 0: - if (c == '%') - state = 1; - else { - if (c == '/') - c = dir_sep; - camel_utf8_putc(&f, c); - } - break; - case 1: - state = 2; - v = hexnib(c)<<4; - break; - case 2: - state = 0; - v |= hexnib(c); - camel_utf8_putc(&f, v); - break; - } - } - camel_utf8_putc(&f, c); - - /* merge old path part if required */ - f = camel_utf8_utf7(full); - if (si) { - full = g_strdup_printf("%s%s", camel_imapp_store_info_full_name(s, si), f); - g_free(f); - camel_store_summary_info_free((CamelStoreSummary *)s, si); - f = full; - } else if (ns) { - full = g_strdup_printf("%s%s", ns->full_name, f); - g_free(f); - f = full; - } - - return f; -} - -CamelIMAPPStoreInfo * -camel_imapp_store_summary_add_from_full(CamelIMAPPStoreSummary *s, const char *full, char dir_sep) -{ - CamelIMAPPStoreInfo *info; - char *pathu8, *prefix; - int len; - char *full_name; - CamelIMAPPStoreNamespace *ns; - - d(printf("adding full name '%s' '%c'\n", full, dir_sep)); - - len = strlen(full); - full_name = alloca(len+1); - strcpy(full_name, full); - if (full_name[len-1] == dir_sep) - full_name[len-1] = 0; - - info = camel_imapp_store_summary_full_name(s, full_name); - if (info) { - camel_store_summary_info_free((CamelStoreSummary *)s, (CamelStoreInfo *)info); - d(printf(" already there\n")); - return info; - } - - ns = camel_imapp_store_summary_namespace_find_full(s, full_name); - if (ns) { - d(printf("(found namespace for '%s' ns '%s') ", full_name, ns->path)); - len = strlen(ns->full_name); - if (len >= strlen(full_name)) { - pathu8 = g_strdup(ns->path); - } else { - if (full_name[len] == ns->sep) - len++; - - prefix = camel_imapp_store_summary_full_to_path(s, full_name+len, ns->sep); - if (*ns->path) { - pathu8 = g_strdup_printf ("%s/%s", ns->path, prefix); - g_free (prefix); - } else { - pathu8 = prefix; - } - } - d(printf(" (pathu8 = '%s')", pathu8)); - } else { - d(printf("(Cannot find namespace for '%s')\n", full_name)); - pathu8 = camel_imapp_store_summary_full_to_path(s, full_name, dir_sep); - } - - info = (CamelIMAPPStoreInfo *)camel_store_summary_add_from_path((CamelStoreSummary *)s, pathu8); - if (info) { - d(printf(" '%s' -> '%s'\n", pathu8, full_name)); - camel_store_info_set_string((CamelStoreSummary *)s, (CamelStoreInfo *)info, CAMEL_IMAPP_STORE_INFO_FULL_NAME, full_name); - } else - d(printf(" failed\n")); - - return info; -} - -/* should this be const? */ -/* TODO: deprecate/merge this function with path_to_full */ -char * -camel_imapp_store_summary_full_from_path(CamelIMAPPStoreSummary *s, const char *path) -{ - CamelIMAPPStoreNamespace *ns; - char *name = NULL; - - ns = camel_imapp_store_summary_namespace_find_path(s, path); - if (ns) - name = camel_imapp_store_summary_path_to_full(s, path, ns->sep); - - d(printf("looking up path %s -> %s\n", path, name?name:"not found")); - - return name; -} - -/* TODO: this api needs some more work */ -CamelIMAPPStoreNamespace *camel_imapp_store_summary_namespace_new(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep) -{ - CamelIMAPPStoreNamespace *ns; - char *p; - int len; - - ns = g_malloc0(sizeof(*ns)); - ns->full_name = g_strdup(full_name); - len = strlen(ns->full_name)-1; - if (len >= 0 && ns->full_name[len] == dir_sep) - ns->full_name[len] = 0; - ns->sep = dir_sep; - - p = ns->path = camel_imapp_store_summary_full_to_path(s, ns->full_name, dir_sep); - while (*p) { - if (*p == '/') - *p = '.'; - p++; - } - - return ns; -} - -void camel_imapp_store_summary_namespace_set(CamelIMAPPStoreSummary *s, CamelIMAPPStoreNamespace *ns) -{ - static void namespace_clear(CamelStoreSummary *s); - - d(printf("Setting namesapce to '%s' '%c' -> '%s'\n", ns->full_name, ns->sep, ns->path)); - namespace_clear((CamelStoreSummary *)s); - s->namespace = ns; - camel_store_summary_touch((CamelStoreSummary *)s); -} - -CamelIMAPPStoreNamespace * -camel_imapp_store_summary_namespace_find_path(CamelIMAPPStoreSummary *s, const char *path) -{ - int len; - CamelIMAPPStoreNamespace *ns; - - /* NB: this currently only compares against 1 namespace, in future compare against others */ - ns = s->namespace; - while (ns) { - len = strlen(ns->path); - if (len == 0 - || (strncmp(ns->path, path, len) == 0 - && (path[len] == '/' || path[len] == 0))) - break; - ns = NULL; - } - - /* have a default? */ - return ns; -} - -CamelIMAPPStoreNamespace * -camel_imapp_store_summary_namespace_find_full(CamelIMAPPStoreSummary *s, const char *full) -{ - int len; - CamelIMAPPStoreNamespace *ns; - - /* NB: this currently only compares against 1 namespace, in future compare against others */ - ns = s->namespace; - while (ns) { - len = strlen(ns->full_name); - d(printf("find_full: comparing namespace '%s' to name '%s'\n", ns->full_name, full)); - if (len == 0 - || (strncmp(ns->full_name, full, len) == 0 - && (full[len] == ns->sep || full[len] == 0))) - break; - ns = NULL; - } - - /* have a default? */ - return ns; -} - -static void -namespace_free(CamelStoreSummary *s, CamelIMAPPStoreNamespace *ns) -{ - g_free(ns->path); - g_free(ns->full_name); - g_free(ns); -} - -static void -namespace_clear(CamelStoreSummary *s) -{ - CamelIMAPPStoreSummary *is = (CamelIMAPPStoreSummary *)s; - - if (is->namespace) - namespace_free(s, is->namespace); - is->namespace = NULL; -} - -static CamelIMAPPStoreNamespace * -namespace_load(CamelStoreSummary *s, FILE *in) -{ - CamelIMAPPStoreNamespace *ns; - guint32 sep = '/'; - - ns = g_malloc0(sizeof(*ns)); - if (camel_file_util_decode_string(in, &ns->path) == -1 - || camel_file_util_decode_string(in, &ns->full_name) == -1 - || camel_file_util_decode_uint32(in, &sep) == -1) { - namespace_free(s, ns); - ns = NULL; - } else { - ns->sep = sep; - } - - return ns; -} - -static int -namespace_save(CamelStoreSummary *s, FILE *in, CamelIMAPPStoreNamespace *ns) -{ - if (camel_file_util_encode_string(in, ns->path) == -1 - || camel_file_util_encode_string(in, ns->full_name) == -1 - || camel_file_util_encode_uint32(in, (guint32)ns->sep) == -1) - return -1; - - return 0; -} - -static int -summary_header_load(CamelStoreSummary *s, FILE *in) -{ - CamelIMAPPStoreSummary *is = (CamelIMAPPStoreSummary *)s; - gint32 version, capabilities, count; - - namespace_clear(s); - - if (camel_imapp_store_summary_parent->summary_header_load((CamelStoreSummary *)s, in) == -1 - || camel_file_util_decode_fixed_int32(in, &version) == -1) - return -1; - - is->version = version; - - if (version < CAMEL_IMAPP_STORE_SUMMARY_VERSION_0) { - g_warning("Store summary header version too low"); - return -1; - } - - /* note file format can be expanded to contain more namespaces, but only 1 at the moment */ - if (camel_file_util_decode_fixed_int32(in, &capabilities) == -1 - || camel_file_util_decode_fixed_int32(in, &count) == -1 - || count > 1) - return -1; - - is->capabilities = capabilities; - if (count == 1) { - if ((is->namespace = namespace_load(s, in)) == NULL) - return -1; - } - - return 0; -} - -static int -summary_header_save(CamelStoreSummary *s, FILE *out) -{ - CamelIMAPPStoreSummary *is = (CamelIMAPPStoreSummary *)s; - guint32 count; - - count = is->namespace?1:0; - - /* always write as latest version */ - if (camel_imapp_store_summary_parent->summary_header_save((CamelStoreSummary *)s, out) == -1 - || camel_file_util_encode_fixed_int32(out, CAMEL_IMAPP_STORE_SUMMARY_VERSION) == -1 - || camel_file_util_encode_fixed_int32(out, is->capabilities) == -1 - || camel_file_util_encode_fixed_int32(out, count) == -1) - return -1; - - if (is->namespace && namespace_save(s, out, is->namespace) == -1) - return -1; - - return 0; -} - -static CamelStoreInfo * -store_info_load(CamelStoreSummary *s, FILE *in) -{ - CamelIMAPPStoreInfo *mi; - - mi = (CamelIMAPPStoreInfo *)camel_imapp_store_summary_parent->store_info_load(s, in); - if (mi) { - if (camel_file_util_decode_string(in, &mi->full_name) == -1) { - camel_store_summary_info_free(s, (CamelStoreInfo *)mi); - mi = NULL; - } - } - - return (CamelStoreInfo *)mi; -} - -static int -store_info_save(CamelStoreSummary *s, FILE *out, CamelStoreInfo *mi) -{ - CamelIMAPPStoreInfo *isi = (CamelIMAPPStoreInfo *)mi; - - if (camel_imapp_store_summary_parent->store_info_save(s, out, mi) == -1 - || camel_file_util_encode_string(out, isi->full_name) == -1) - return -1; - - return 0; -} - -static void -store_info_free(CamelStoreSummary *s, CamelStoreInfo *mi) -{ - CamelIMAPPStoreInfo *isi = (CamelIMAPPStoreInfo *)mi; - - g_free(isi->full_name); - camel_imapp_store_summary_parent->store_info_free(s, mi); -} - -static const char * -store_info_string(CamelStoreSummary *s, const CamelStoreInfo *mi, int type) -{ - CamelIMAPPStoreInfo *isi = (CamelIMAPPStoreInfo *)mi; - - /* FIXME: Locks? */ - - g_assert (mi != NULL); - - switch (type) { - case CAMEL_IMAPP_STORE_INFO_FULL_NAME: - return isi->full_name; - default: - return camel_imapp_store_summary_parent->store_info_string(s, mi, type); - } -} - -static void -store_info_set_string(CamelStoreSummary *s, CamelStoreInfo *mi, int type, const char *str) -{ - CamelIMAPPStoreInfo *isi = (CamelIMAPPStoreInfo *)mi; - - g_assert(mi != NULL); - - switch(type) { - case CAMEL_IMAPP_STORE_INFO_FULL_NAME: - d(printf("Set full name %s -> %s\n", isi->full_name, str)); - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - g_free(isi->full_name); - isi->full_name = g_strdup(str); - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - break; - default: - camel_imapp_store_summary_parent->store_info_set_string(s, mi, type, str); - break; - } -} diff --git a/camel/providers/imapp/camel-imapp-store-summary.h b/camel/providers/imapp/camel-imapp-store-summary.h deleted file mode 100644 index 154fe8798e..0000000000 --- a/camel/providers/imapp/camel-imapp-store-summary.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2002 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_IMAPP_STORE_SUMMARY_H -#define _CAMEL_IMAPP_STORE_SUMMARY_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include - -#define CAMEL_IMAPP_STORE_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_imapp_store_summary_get_type (), CamelIMAPPStoreSummary) -#define CAMEL_IMAPP_STORE_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imapp_store_summary_get_type (), CamelIMAPPStoreSummaryClass) -#define CAMEL_IS_IMAP_STORE_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_imapp_store_summary_get_type ()) - -typedef struct _CamelIMAPPStoreSummary CamelIMAPPStoreSummary; -typedef struct _CamelIMAPPStoreSummaryClass CamelIMAPPStoreSummaryClass; - -typedef struct _CamelIMAPPStoreInfo CamelIMAPPStoreInfo; - -enum { - CAMEL_IMAPP_STORE_INFO_FULL_NAME = CAMEL_STORE_INFO_LAST, - CAMEL_IMAPP_STORE_INFO_LAST, -}; - -struct _CamelIMAPPStoreInfo { - CamelStoreInfo info; - char *full_name; -}; - -typedef struct _CamelIMAPPStoreNamespace CamelIMAPPStoreNamespace; - -struct _CamelIMAPPStoreNamespace { - char *path; /* display path */ - char *full_name; /* real name */ - char sep; /* directory separator */ -}; - -struct _CamelIMAPPStoreSummary { - CamelStoreSummary summary; - - struct _CamelIMAPPStoreSummaryPrivate *priv; - - /* header info */ - guint32 version; /* version of base part of file */ - guint32 capabilities; - CamelIMAPPStoreNamespace *namespace; /* eventually to be a list */ -}; - -struct _CamelIMAPPStoreSummaryClass { - CamelStoreSummaryClass summary_class; -}; - -CamelType camel_imapp_store_summary_get_type (void); -CamelIMAPPStoreSummary *camel_imapp_store_summary_new (void); - -/* TODO: this api needs some more work, needs to support lists */ -CamelIMAPPStoreNamespace *camel_imapp_store_summary_namespace_new(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep); -void camel_imapp_store_summary_namespace_set(CamelIMAPPStoreSummary *s, CamelIMAPPStoreNamespace *ns); -CamelIMAPPStoreNamespace *camel_imapp_store_summary_namespace_find_path(CamelIMAPPStoreSummary *s, const char *path); -CamelIMAPPStoreNamespace *camel_imapp_store_summary_namespace_find_full(CamelIMAPPStoreSummary *s, const char *full_name); - -/* converts to/from utf8 canonical nasmes */ -char *camel_imapp_store_summary_full_to_path(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep); -char *camel_imapp_store_summary_path_to_full(CamelIMAPPStoreSummary *s, const char *path, char dir_sep); - -CamelIMAPPStoreInfo *camel_imapp_store_summary_full_name(CamelIMAPPStoreSummary *s, const char *full_name); -CamelIMAPPStoreInfo *camel_imapp_store_summary_add_from_full(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep); - -/* a convenience lookup function. always use this if path known */ -char *camel_imapp_store_summary_full_from_path(CamelIMAPPStoreSummary *s, const char *path); - -/* helper macro's */ -#define camel_imapp_store_info_full_name(s, i) (camel_store_info_string((CamelStoreSummary *)s, (const CamelStoreInfo *)i, CAMEL_IMAPP_STORE_INFO_FULL_NAME)) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_IMAPP_STORE_SUMMARY_H */ diff --git a/camel/providers/imapp/camel-imapp-store.c b/camel/providers/imapp/camel-imapp-store.c deleted file mode 100644 index 9123102a03..0000000000 --- a/camel/providers/imapp/camel-imapp-store.c +++ /dev/null @@ -1,1006 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-store.c : class for a imap store */ - -/* - * Authors: Michael Zucchi - * - * Copyright (C) 2000-2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "camel/camel-operation.h" - -#include "camel/camel-stream-buffer.h" -#include "camel/camel-session.h" -#include "camel/camel-exception.h" -#include "camel/camel-url.h" -#include "camel/camel-sasl.h" -#include "camel/camel-data-cache.h" -#include "camel/camel-tcp-stream.h" -#include "camel/camel-tcp-stream-raw.h" -#ifdef HAVE_SSL -#include "camel/camel-tcp-stream-ssl.h" -#endif - -#include "camel-imapp-store-summary.h" -#include "camel-imapp-store.h" -#include "camel-imapp-folder.h" -#include "camel-imapp-engine.h" -#include "camel-imapp-exception.h" -#include "camel-imapp-utils.h" -#include "camel-imapp-driver.h" - -/* Specified in RFC 2060 section 2.1 */ -#define IMAP_PORT 143 - -static CamelStoreClass *parent_class = NULL; - -static void finalize (CamelObject *object); - -static void imap_construct(CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex); -/* static char *imap_get_name(CamelService *service, gboolean brief);*/ -static gboolean imap_connect (CamelService *service, CamelException *ex); -static gboolean imap_disconnect (CamelService *service, gboolean clean, CamelException *ex); -static GList *imap_query_auth_types (CamelService *service, CamelException *ex); - -static void imap_init_trash (CamelStore *store); -static CamelFolder *imap_get_trash (CamelStore *store, CamelException *ex); - -static CamelFolder *imap_get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex); -static CamelFolder *imap_get_inbox (CamelStore *store, CamelException *ex); -static void imap_rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex); -static CamelFolderInfo *imap_get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); -static void imap_delete_folder(CamelStore *store, const char *folder_name, CamelException *ex); -static void imap_rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex); -static CamelFolderInfo *imap_create_folder(CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex); - -static int store_resp_list(CamelIMAPPEngine *ie, guint32 id, void *data); - -/* yet to see if this should go global or not */ -void camel_imapp_store_folder_selected(CamelIMAPPStore *store, CamelIMAPPFolder *folder, CamelIMAPPSelectResponse *select); - -static void -camel_imapp_store_class_init (CamelIMAPPStoreClass *camel_imapp_store_class) -{ - CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_imapp_store_class); - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_imapp_store_class); - - parent_class = CAMEL_STORE_CLASS(camel_type_get_global_classfuncs(camel_store_get_type())); - - /* virtual method overload */ - camel_service_class->construct = imap_construct; - /*camel_service_class->get_name = imap_get_name;*/ - camel_service_class->query_auth_types = imap_query_auth_types; - camel_service_class->connect = imap_connect; - camel_service_class->disconnect = imap_disconnect; - - camel_store_class->init_trash = imap_init_trash; - camel_store_class->get_trash = imap_get_trash; - - camel_store_class->get_folder = imap_get_folder; - camel_store_class->get_inbox = imap_get_inbox; - - camel_store_class->create_folder = imap_create_folder; - camel_store_class->rename_folder = imap_rename_folder; - camel_store_class->delete_folder = imap_delete_folder; - camel_store_class->get_folder_info = imap_get_folder_info; -} - -static void -camel_imapp_store_init (gpointer object, gpointer klass) -{ - CamelIMAPPStore *istore = object; -} - -CamelType -camel_imapp_store_get_type (void) -{ - static CamelType camel_imapp_store_type = CAMEL_INVALID_TYPE; - - if (!camel_imapp_store_type) { - camel_imapp_store_type = camel_type_register(CAMEL_STORE_TYPE, - "CamelIMAPPStore", - sizeof (CamelIMAPPStore), - sizeof (CamelIMAPPStoreClass), - (CamelObjectClassInitFunc) camel_imapp_store_class_init, - NULL, - (CamelObjectInitFunc) camel_imapp_store_init, - finalize); - } - - return camel_imapp_store_type; -} - -static void -finalize (CamelObject *object) -{ - CamelIMAPPStore *imap_store = CAMEL_IMAPP_STORE (object); - - /* force disconnect so we dont have it run later, after we've cleaned up some stuff */ - /* SIGH */ - - camel_service_disconnect((CamelService *)imap_store, TRUE, NULL); - - if (imap_store->driver) - camel_object_unref(imap_store->driver); - if (imap_store->cache) - camel_object_unref(imap_store->cache); -} - -static void imap_construct(CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex) -{ - char *root, *summary; - CamelIMAPPStore *store = (CamelIMAPPStore *)service; - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set(ex)) - return; - - CAMEL_TRY { - store->summary = camel_imapp_store_summary_new(); - root = camel_session_get_storage_path(service->session, service, ex); - if (root) { - summary = g_build_filename(root, ".ev-store-summary", NULL); - camel_store_summary_set_filename((CamelStoreSummary *)store->summary, summary); - /* FIXME: need to remove params, passwords, etc */ - camel_store_summary_set_uri_base((CamelStoreSummary *)store->summary, service->url); - camel_store_summary_load((CamelStoreSummary *)store->summary); - } - } CAMEL_CATCH(e) { - camel_exception_xfer(ex, e); - } CAMEL_DONE; -} - -enum { - USE_SSL_NEVER, - USE_SSL_ALWAYS, - USE_SSL_WHEN_POSSIBLE -}; - -#define SSL_PORT_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3) -#define STARTTLS_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_TLS) - -static void -connect_to_server (CamelService *service, int ssl_mode, int try_starttls) -/* throws IO exception */ -{ - CamelIMAPPStore *store = CAMEL_IMAPP_STORE (service); - CamelStream * volatile tcp_stream = NULL; - CamelIMAPPStream * volatile imap_stream = NULL; - struct hostent *h = NULL; - int ret, port; - CamelException *ex; - - ex = camel_exception_new(); - CAMEL_TRY { - /* parent class connect initialization */ - CAMEL_SERVICE_CLASS (parent_class)->connect (service, ex); - if (ex->id) - camel_exception_throw_ex(ex); - - h = camel_service_gethost(service, ex); - if (ex->id) - camel_exception_throw_ex(ex); - - port = service->url->port ? service->url->port : IMAP_PORT; - -#ifdef HAVE_SSL - if (camel_url_get_param (service->url, "use_ssl")) { - if (try_starttls) - tcp_stream = camel_tcp_stream_ssl_new_raw (service->session, service->url->host, STARTTLS_FLAGS); - else { - port = service->url->port ? service->url->port : 995; - tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, SSL_PORT_FLAGS); - } - } else { - tcp_stream = camel_tcp_stream_raw_new (); - } -#else - tcp_stream = camel_tcp_stream_raw_new (); -#endif /* HAVE_SSL */ - - ret = camel_tcp_stream_connect (CAMEL_TCP_STREAM (tcp_stream), h, port); - camel_free_host (h); - if (ret == -1) { - if (errno == EINTR) - camel_exception_throw(CAMEL_EXCEPTION_USER_CANCEL, _("Connection cancelled")); - else - camel_exception_throw(CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s (port %d): %s"), - service->url->host, port, strerror(errno)); - } - - imap_stream = (CamelIMAPPStream *)camel_imapp_stream_new(tcp_stream); - store->driver = camel_imapp_driver_new(imap_stream); - - camel_object_unref(imap_stream); - camel_object_unref(tcp_stream); - } CAMEL_CATCH(e) { - if (tcp_stream) - camel_object_unref(tcp_stream); - if (imap_stream) - camel_object_unref((CamelObject *)imap_stream); - camel_exception_throw_ex(e); - } CAMEL_DONE; - - camel_exception_free(ex); -} - -#if 0 - -/* leave this stuff out for now */ - - -static struct { - char *value; - int mode; -} ssl_options[] = { - { "", USE_SSL_ALWAYS }, - { "always", USE_SSL_ALWAYS }, - { "when-possible", USE_SSL_WHEN_POSSIBLE }, - { "never", USE_SSL_NEVER }, - { NULL, USE_SSL_NEVER }, -}; - -static gboolean -connect_to_server_wrapper (CamelService *service, CamelException *ex) -{ -#ifdef HAVE_SSL - const char *use_ssl; - int i, ssl_mode; - - use_ssl = camel_url_get_param (service->url, "use_ssl"); - if (use_ssl) { - for (i = 0; ssl_options[i].value; i++) - if (!strcmp (ssl_options[i].value, use_ssl)) - break; - ssl_mode = ssl_options[i].mode; - } else - ssl_mode = USE_SSL_NEVER; - - if (ssl_mode == USE_SSL_ALWAYS) { - /* First try the ssl port */ - if (!connect_to_server (service, ssl_mode, FALSE, ex)) { - if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE) { - /* The ssl port seems to be unavailable, lets try STARTTLS */ - camel_exception_clear (ex); - return connect_to_server (service, ssl_mode, TRUE, ex); - } else { - return FALSE; - } - } - - return TRUE; - } else if (ssl_mode == USE_SSL_WHEN_POSSIBLE) { - /* If the server supports STARTTLS, use it */ - return connect_to_server (service, ssl_mode, TRUE, ex); - } else { - /* User doesn't care about SSL */ - return connect_to_server (service, ssl_mode, FALSE, ex); - } -#else - return connect_to_server (service, USE_SSL_NEVER, FALSE, ex); -#endif -} -#endif - -extern CamelServiceAuthType camel_imapp_password_authtype; -extern CamelServiceAuthType camel_imapp_apop_authtype; - -static GList * -imap_query_auth_types (CamelService *service, CamelException *ex) -{ - /*CamelIMAPPStore *store = CAMEL_IMAPP_STORE (service);*/ - GList *types = NULL; - - types = CAMEL_SERVICE_CLASS (parent_class)->query_auth_types (service, ex); - if (types == NULL) - return NULL; - -#if 0 - if (connect_to_server_wrapper (service, NULL)) { - types = g_list_concat(types, g_list_copy(store->engine->auth)); - imap_disconnect (service, TRUE, NULL); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to POP server on %s"), - service->url->host); - } -#endif - return types; -} - -static void -store_get_pass(CamelIMAPPStore *store) -{ - if (((CamelService *)store)->url->passwd == NULL) { - char *prompt; - CamelException ex; - - camel_exception_init(&ex); - - prompt = g_strdup_printf (_("%sPlease enter the IMAP password for %s@%s"), - store->login_error?store->login_error:"", - ((CamelService *)store)->url->user, - ((CamelService *)store)->url->host); - ((CamelService *)store)->url->passwd = camel_session_get_password(camel_service_get_session((CamelService *)store), - prompt, FALSE, TRUE, (CamelService*)store, "password", &ex); - g_free (prompt); - if (camel_exception_is_set(&ex)) - camel_exception_throw_ex(&ex); - } -} - -static struct _CamelSasl * -store_get_sasl(struct _CamelIMAPPDriver *driver, CamelIMAPPStore *store) -{ - store_get_pass(store); - - if (((CamelService *)store)->url->authmech) - return camel_sasl_new("imap", ((CamelService *)store)->url->authmech, (CamelService *)store); - - return NULL; -} - -static void -store_get_login(struct _CamelIMAPPDriver *driver, char **login, char **pass, CamelIMAPPStore *store) -{ - store_get_pass(store); - - *login = g_strdup(((CamelService *)store)->url->user); - *pass = g_strdup(((CamelService *)store)->url->passwd); -} - -static gboolean -imap_connect (CamelService *service, CamelException *ex) -{ - CamelIMAPPStore *store = (CamelIMAPPStore *)service; - volatile int ret = FALSE; - - CAMEL_TRY { - volatile int retry = TRUE; - - if (store->cache == NULL) { - char *root; - - root = camel_session_get_storage_path(service->session, service, ex); - if (root) { - store->cache = camel_data_cache_new(root, 0, ex); - g_free(root); - if (store->cache) { - /* Default cache expiry - 1 week or not visited in a day */ - camel_data_cache_set_expire_age(store->cache, 60*60*24*7); - camel_data_cache_set_expire_access(store->cache, 60*60*24); - } - } - if (camel_exception_is_set(ex)) - camel_exception_throw_ex(ex); - } - - connect_to_server(service, USE_SSL_NEVER, FALSE); - - camel_imapp_driver_set_sasl_factory(store->driver, (CamelIMAPPSASLFunc)store_get_sasl, store); - camel_imapp_driver_set_login_query(store->driver, (CamelIMAPPLoginFunc)store_get_login, store); - store->login_error = NULL; - - do { - CAMEL_TRY { - if (store->driver->engine->state != IMAP_ENGINE_AUTH) - camel_imapp_driver_login(store->driver); - ret = TRUE; - retry = FALSE; - } CAMEL_CATCH(e) { - g_free(store->login_error); - store->login_error = NULL; - switch (e->id) { - case CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE: - store->login_error = g_strdup_printf("%s\n\n", e->desc); - camel_session_forget_password(service->session, service, "password", ex); - camel_url_set_passwd(service->url, NULL); - break; - default: - camel_exception_throw_ex(e); - break; - } - } CAMEL_DONE; - } while (retry); - } CAMEL_CATCH(e) { - camel_exception_xfer(ex, e); - camel_service_disconnect(service, TRUE, NULL); - ret = FALSE; - } CAMEL_DONE; - - g_free(store->login_error); - store->login_error = NULL; - - return ret; -} - -static gboolean -imap_disconnect (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelIMAPPStore *store = CAMEL_IMAPP_STORE (service); - - /* FIXME: logout */ - - if (!CAMEL_SERVICE_CLASS (parent_class)->disconnect (service, clean, ex)) - return FALSE; - - /* logout/disconnect */ - if (store->driver) { - camel_object_unref(store->driver); - store->driver = NULL; - } - - return TRUE; -} - -static void -imap_init_trash (CamelStore *store) -{ - /* no-op */ - ; -} - -static CamelFolder * -imap_get_trash (CamelStore *store, CamelException *ex) -{ - /* no-op */ - return NULL; -} - -static CamelFolder * -imap_get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) -{ - CamelIMAPPStore *istore = (CamelIMAPPStore *)store; - CamelIMAPPFolder * volatile folder = NULL; - - /* ??? */ - - /* 1. create the folder */ - /* 2. run select? */ - /* 3. update the folder */ - - CAMEL_TRY { - folder = (CamelIMAPPFolder *)camel_imapp_folder_new(store, folder_name); - camel_imapp_driver_select(istore->driver, folder); - } CAMEL_CATCH (e) { - if (folder) { - camel_object_unref(folder); - folder = NULL; - } - camel_exception_xfer(ex, e); - } CAMEL_DONE; - - return (CamelFolder *)folder; -} - -static CamelFolder * -imap_get_inbox(CamelStore *store, CamelException *ex) -{ - camel_exception_setv(ex, 1, "get_inbox::unimplemented"); - - return NULL; -} - -/* 8 bit, string compare */ -static int folders_build_cmp(const void *app, const void *bpp) -{ - struct _list_info *a = *((struct _list_info **)app); - struct _list_info *b = *((struct _list_info **)bpp); - unsigned char *ap = (unsigned char *)(a->name); - unsigned char *bp = (unsigned char *)(b->name); - - printf("qsort, cmp '%s' <> '%s'\n", ap, bp); - - while (*ap && *ap == *bp) { - ap++; - bp++; - } - - if (*ap < *bp) - return -1; - else if (*ap > *bp) - return 1; - return 0; -} - -/* FIXME: this should go via storesummary? */ -static CamelFolderInfo * -folders_build_info(CamelURL *base, struct _list_info *li) -{ - char *path, *full_name, *name; - CamelFolderInfo *fi; - - full_name = imapp_list_get_path(li); - name = strrchr(full_name, '/'); - if (name) - name++; - else - name = full_name; - - path = alloca(strlen(full_name)+2); - sprintf(path, "/%s", full_name); - camel_url_set_path(base, path); - - fi = g_malloc0(sizeof(*fi)); - fi->url = camel_url_to_string(base, CAMEL_URL_HIDE_ALL); - fi->name = g_strdup(name); - fi->full_name = full_name; - fi->path = g_strdup(path); - fi->unread_message_count = -1; - fi->flags = li->flags; - - /* TODO: could look up count here ... */ - /* ?? */ - /*folder = camel_object_bag_get(store->folders, "INBOX");*/ - - return fi; -} - -/* - a - a/b - a/b/c - a/d - b - c/d - -*/ - -/* note, pname is the raw name, not the folderinfo name */ -/* note also this free's as we go, since we never go 'backwards' */ -static CamelFolderInfo * -folders_build_rec(CamelURL *base, GPtrArray *folders, int *ip, CamelFolderInfo *pfi, char *pname) -{ - int plen = 0; - CamelFolderInfo *last = NULL, *first = NULL; - - if (pfi) - plen = strlen(pname); - - for(;(*ip)<(int)folders->len;) { - CamelFolderInfo *fi; - struct _list_info *li; - - li = folders->pdata[*ip]; - printf("checking '%s' is child of '%s'\n", li->name, pname); - - /* is this a child of the parent? */ - if (pfi != NULL - && (strncmp(pname, li->name, strlen(pname)) != 0 - || li->name[plen] != li->separator)) { - printf(" nope\n"); - break; - } - printf(" yep\n"); - - /* is this not an immediate child of the parent? */ -#if 0 - char *p; - if (pfi != NULL - && li->separator != 0 - && (p = strchr(li->name + plen + 1, li->separator)) != NULL) { - if (last == NULL) { - struct _list_info tli; - - tli.flags = CAMEL_FOLDER_NOSELECT|CAMEL_FOLDER_CHILDREN; - tli.separator = li->separator; - tli.name = g_strndup(li->name, p-li->name+1); - fi = folders_build_info(base, &tli); - fi->parent = pfi; - if (pfi && pfi->child == NULL) - pfi->child = fi; - i = folders_build_rec(folders, i, fi, tli.name); - break; - } - } -#endif - - fi = folders_build_info(base, li); - fi->parent = pfi; - if (last != NULL) - last->sibling = fi; - last = fi; - if (first == NULL) - first = fi; - - (*ip)++; - fi->child = folders_build_rec(base, folders, ip, fi, li->name); - imap_free_list(li); - } - - return first; -} - -static void -folder_info_dump(CamelFolderInfo *fi, int depth) -{ - char *s; - - s = alloca(depth+1); - memset(s, ' ', depth); - s[depth] = 0; - while (fi) { - printf("%s%s (%s)\n", s, fi->name, fi->url); - if (fi->child) - folder_info_dump(fi->child, depth+2); - fi = fi->sibling; - } - -} - -static CamelFolderInfo * -imap_get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelIMAPPStore *istore = (CamelIMAPPStore *)store; - CamelFolderInfo * fi= NULL; - char *name; - - /* FIXME: temporary, since this is not a disco store */ - if (istore->driver == NULL - && !camel_service_connect((CamelService *)store, ex)) - return NULL; - - name = (char *)top; - if (name == NULL || name[0] == 0) { - /* namespace? */ - name = ""; - } - - name = ""; - - CAMEL_TRY { - CamelURL *base; - int i; - GPtrArray *folders; - - /* FIXME: subscriptions? lsub? */ - folders = camel_imapp_driver_list(istore->driver, name, flags); - - /* this greatly simplifies the tree algorithm ... but it might - be faster just to use a hashtable to find parents? */ - qsort(folders->pdata, folders->len, sizeof(folders->pdata[0]), folders_build_cmp); - - i = 0; - base = camel_url_copy(((CamelService *)store)->url); - fi = folders_build_rec(base, folders, &i, NULL, NULL); - camel_url_free(base); - g_ptr_array_free(folders, TRUE); - } CAMEL_CATCH(e) { - camel_exception_xfer(ex, e); - } CAMEL_DONE; - - printf("built folder info:\n"); - folder_info_dump(fi, 2); - - return fi; - -#if 0 - if (top == NULL || !g_ascii_strcasecmp(top, "inbox")) { - CamelURL *uri = camel_url_copy(((CamelService *)store)->url); - - camel_url_set_path(uri, "/INBOX"); - fi = g_malloc0(sizeof(*fi)); - fi->url = camel_url_to_string(uri, CAMEL_URL_HIDE_ALL); - camel_url_free(uri); - fi->name = g_strdup("INBOX"); - fi->full_name = g_strdup("INBOX"); - fi->path = g_strdup("/INBOX"); - fi->unread_message_count = -1; - fi->flags = 0; - - folder = camel_object_bag_get(store->folders, "INBOX"); - if (folder) { - /*if (!cflags & FAST)*/ - camel_imapp_driver_update(istore->driver, (CamelIMAPPFolder *)folder); - fi->unread_message_count = camel_folder_get_unread_message_count(folder); - camel_object_unref(folder); - } - } else { - camel_exception_setv(ex, 1, "not implemented"); - } -#endif - return fi; - -#if 0 - istore->pending_list = g_ptr_array_new(); - - CAMEL_TRY { - ic = camel_imapp_engine_command_new(istore->driver->engine, "LIST", NULL, "LIST \"\" %f", top); - camel_imapp_engine_command_queue(istore->driver->engine, ic); - while (camel_imapp_engine_iterate(istore->driver->engine, ic) > 0) - ; - - if (ic->status->result != IMAP_OK) - camel_exception_throw(1, "list failed: %s", ic->status->text); - } CAMEL_CATCH (e) { - camel_exception_xfer(ex, e); - } CAMEL_DONE; - - camel_imapp_engine_command_free(istore->driver->engine, ic); - - printf("got folder list:\n"); - for (i=0;i<(int)istore->pending_list->len;i++) { - struct _list_info *linfo = istore->pending_list->pdata[i]; - - printf("%s (%c)\n", linfo->name, linfo->separator); - imap_free_list(linfo); - } - istore->pending_list = NULL; - - return NULL; -#endif -} - -static void -imap_delete_folder(CamelStore *store, const char *folder_name, CamelException *ex) -{ - camel_exception_setv(ex, 1, "delete_folder::unimplemented"); -} - -static void -imap_rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex) -{ - camel_exception_setv(ex, 1, "rename_folder::unimplemented"); -} - -static CamelFolderInfo * -imap_create_folder(CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex) -{ - camel_exception_setv(ex, 1, "create_folder::unimplemented"); - return NULL; -} - -/* ********************************************************************** */ -#if 0 -static int store_resp_fetch(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - struct _fetch_info *finfo; - CamelIMAPPStore *istore = data; - CamelMessageInfo *info; - struct _pending_fetch *pending; - - finfo = imap_parse_fetch(ie->stream); - if (istore->selected) { - if ((finfo->got & FETCH_UID) == 0) { - printf("didn't get uid in fetch response?\n"); - } else { - info = camel_folder_summary_index(((CamelFolder *)istore->selected)->summary, id-1); - /* exists, check/update */ - if (info) { - if (strcmp(finfo->uid, camel_message_info_uid(info)) != 0) { - printf("summary at index %d has uid %s expected %s\n", id, camel_message_info_uid(info), finfo->uid); - /* uid mismatch??? try do it based on uid instead? try to reorder? i dont know? */ - camel_folder_summary_info_free(((CamelFolder *)istore->selected)->summary, info); - info = camel_folder_summary_uid(((CamelFolder *)istore->selected)->summary, finfo->uid); - } - } - - if (info) { - if (finfo->got & (FETCH_FLAGS)) { - printf("updating flags for uid '%s'\n", finfo->uid); - info->flags = finfo->flags; - camel_folder_change_info_change_uid(istore->selected->changes, finfo->uid); - } - if (finfo->got & FETCH_MINFO) { - printf("got envelope unexpectedly?\n"); - } - /* other things go here, like body fetches */ - } else { - pending = g_hash_table_lookup(istore->pending_fetch_table, finfo->uid); - - /* we need to create a new info, we only care about flags and minfo */ - - if (pending) - info = pending->info; - else { - info = camel_folder_summary_info_new(((CamelFolder *)istore->selected)->summary); - camel_message_info_set_uid(info, g_strdup(finfo->uid)); - } - - if (finfo->got & FETCH_FLAGS) - info->flags = finfo->flags; - - if (finfo->got & FETCH_MINFO) { - /* if we only use ENVELOPE? */ - camel_message_info_set_subject(info, g_strdup(camel_message_info_subject(finfo->minfo))); - camel_message_info_set_from(info, g_strdup(camel_message_info_from(finfo->minfo))); - camel_message_info_set_to(info, g_strdup(camel_message_info_to(finfo->minfo))); - camel_message_info_set_cc(info, g_strdup(camel_message_info_cc(finfo->minfo))); - info->date_sent = finfo->minfo->date_sent; - camel_folder_summary_add(((CamelFolder *)istore->selected)->summary, info); - camel_folder_change_info_add_uid(istore->selected->changes, finfo->uid); - if (pending) { - e_dlist_remove((EDListNode *)pending); - g_hash_table_remove(istore->pending_fetch_table, finfo->uid); - /*e_memchunk_free(istore->pending_fetch_chunks, pending);*/ - } - } else if (finfo->got & FETCH_HEADER) { - /* if we only use HEADER? */ - CamelMimeParser *mp; - - if (pending == NULL) - camel_folder_summary_info_free(((CamelFolder *)istore->selected)->summary, info); - mp = camel_mime_parser_new(); - camel_mime_parser_init_with_stream(mp, finfo->header); - info = camel_folder_summary_info_new_from_parser(((CamelFolder *)istore->selected)->summary, mp); - camel_object_unref(mp); - camel_message_info_set_uid(info, g_strdup(finfo->uid)); - - camel_folder_summary_add(((CamelFolder *)istore->selected)->summary, info); - camel_folder_change_info_add_uid(istore->selected->changes, finfo->uid); - if (pending) { - /* FIXME: use a dlist */ - e_dlist_remove((EDListNode *)pending); - g_hash_table_remove(istore->pending_fetch_table, camel_message_info_uid(pending->info)); - camel_folder_summary_info_free(((CamelFolder *)istore->selected)->summary, pending->info); - /*e_memchunk_free(istore->pending_fetch_chunks, pending);*/ - } - } else if (finfo->got & FETCH_FLAGS) { - if (pending == NULL) { - pending = e_memchunk_alloc(istore->pending_fetch_chunks); - pending->info = info; - g_hash_table_insert(istore->pending_fetch_table, (char *)camel_message_info_uid(info), pending); - e_dlist_addtail(&istore->pending_fetch_list, (EDListNode *)pending); - } - } else { - if (pending == NULL) - camel_folder_summary_info_free(((CamelFolder *)istore->selected)->summary, info); - printf("got unexpected fetch response?\n"); - imap_dump_fetch(finfo); - } - } - } - } else { - printf("unexpected fetch response, no folder selected?\n"); - } - /*imap_dump_fetch(finfo);*/ - imap_free_fetch(finfo); - - return camel_imapp_engine_skip(ie); -} -#endif - -/* ********************************************************************** */ - -/* should be moved to imapp-utils? - stuff in imapp-utils should be moved to imapp-parse? */ - -/* ********************************************************************** */ - -#if 0 -void -camel_imapp_store_folder_selected(CamelIMAPPStore *store, CamelIMAPPFolder *folder, CamelIMAPPSelectResponse *select) -{ - CamelIMAPPCommand * volatile ic = NULL; - CamelIMAPPStore *istore = (CamelIMAPPStore *)store; - int i; - struct _uidset_state ss; - GPtrArray *fetch; - CamelMessageInfo *info; - struct _pending_fetch *fw, *fn; - - printf("imap folder selected\n"); - - if (select->uidvalidity == folder->uidvalidity - && select->exists == folder->exists - && select->recent == folder->recent - && select->unseen == folder->unseen) { - /* no work to do? */ - return; - } - - istore->pending_fetch_table = g_hash_table_new(g_str_hash, g_str_equal); - istore->pending_fetch_chunks = e_memchunk_new(256, sizeof(struct _pending_fetch)); - - /* perform an update - flags first (and see what we have) */ - CAMEL_TRY { - ic = camel_imapp_engine_command_new(istore->engine, "FETCH", NULL, "FETCH 1:%d (UID FLAGS)", select->exists); - camel_imapp_engine_command_queue(istore->engine, ic); - while (camel_imapp_engine_iterate(istore->engine, ic) > 0) - ; - - if (ic->status->result != IMAP_OK) - camel_exception_throw(1, "fetch failed: %s", ic->status->text); - - /* pending_fetch_list now contains any new messages */ - /* FIXME: how do we work out no-longer present messages? */ - printf("now fetching info for messages?\n"); - uidset_init(&ss, store->engine); - ic = camel_imapp_engine_command_new(istore->engine, "FETCH", NULL, "UID FETCH "); - fw = (struct _pending_fetch *)istore->pending_fetch_list.head; - fn = fw->next; - while (fn) { - info = fw->info; - /* if the uid set fills, then flush the command out */ - if (uidset_add(&ss, ic, camel_message_info_uid(info)) - || (fn->next == NULL && uidset_done(&ss, ic))) { - camel_imapp_engine_command_add(istore->engine, ic, " (FLAGS RFC822.HEADER)"); - camel_imapp_engine_command_queue(istore->engine, ic); - while (camel_imapp_engine_iterate(istore->engine, ic) > 0) - ; - if (ic->status->result != IMAP_OK) - camel_exception_throw(1, "fetch failed: %s", ic->status->text); - /* if not end ... */ - camel_imapp_engine_command_free(istore->engine, ic); - ic = camel_imapp_engine_command_new(istore->engine, "FETCH", NULL, "UID FETCH "); - } - fw = fn; - fn = fn->next; - } - - printf("The pending list should now be empty: %s\n", e_dlist_empty(&istore->pending_fetch_list)?"TRUE":"FALSE"); - for (i=0;i<10;i++) { - info = camel_folder_summary_index(((CamelFolder *)istore->selected)->summary, i); - if (info) { - printf("message info [%d] =\n", i); - camel_message_info_dump(info); - camel_folder_summary_info_free(((CamelFolder *)istore->selected)->summary, info); - } - } - } CAMEL_CATCH (e) { - /* FIXME: cleanup */ - camel_exception_throw_ex(e); - } CAMEL_DONE; - - g_hash_table_destroy(istore->pending_fetch_table); - istore->pending_fetch_table = NULL; - e_memchunk_destroy(istore->pending_fetch_chunks); - - camel_imapp_engine_command_free(istore->engine, ic); -} -#endif - -#if 0 -/*char *uids[] = {"1", "2", "4", "5", "6", "7", "9", "11", "12", 0};*/ -/*char *uids[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", 0};*/ -char *uids[] = {"1", "3", "5", "7", "9", "11", "12", "13", "14", "15", "20", "21", "24", "25", "26", 0}; - -void -uidset_test(CamelIMAPPEngine *ie) -{ - struct _uidset_state ss; - CamelIMAPPCommand *ic; - int i; - - /*ic = camel_imapp_engine_command_new(ie, 0, "FETCH", NULL, "FETCH ");*/ - uidset_init(&ss, 0, 0); - for (i=0;uids[i];i++) { - if (uidset_add(&ss, uids[i])) { - printf("\n[%d] flushing uids\n", i); - } - } - - if (uidset_done(&ss)) { - printf("\nflushing uids\n"); - } -} -#endif diff --git a/camel/providers/imapp/camel-imapp-store.h b/camel/providers/imapp/camel-imapp-store.h deleted file mode 100644 index 97b7afd1d1..0000000000 --- a/camel/providers/imapp/camel-imapp-store.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-store.h : class for an imap store */ - -/* - * Authors: Michael Zucchi - * - * Copyright (C) 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAPP_STORE_H -#define CAMEL_IMAPP_STORE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include -#include "camel-imapp-driver.h" -#include "e-util/e-memory.h" - -#define CAMEL_IMAPP_STORE_TYPE (camel_imapp_store_get_type ()) -#define CAMEL_IMAPP_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAPP_STORE_TYPE, CamelIMAPPStore)) -#define CAMEL_IMAPP_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAPP_STORE_TYPE, CamelIMAPPStoreClass)) -#define CAMEL_IS_IMAP_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAPP_STORE_TYPE)) - -struct _pending_fetch { - struct _pending_fetch *next; - struct _pending_fetch *prev; - - CamelMessageInfo *info; -}; - -typedef struct { - CamelStore parent_object; - - struct _CamelIMAPPStoreSummary *summary; /* in-memory list of folders */ - struct _CamelIMAPPDriver *driver; /* IMAP processing engine */ - struct _CamelDataCache *cache; - - /* if we had a login error, what to show to user */ - char *login_error; - - GPtrArray *pending_list; -} CamelIMAPPStore; - -typedef struct { - CamelStoreClass parent_class; - -} CamelIMAPPStoreClass; - -/* Standard Camel function */ -CamelType camel_imapp_store_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_IMAPP_STORE_H */ - - diff --git a/camel/providers/imapp/camel-imapp-stream.c b/camel/providers/imapp/camel-imapp-stream.c deleted file mode 100644 index 20876beae2..0000000000 --- a/camel/providers/imapp/camel-imapp-stream.c +++ /dev/null @@ -1,761 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Author: - * Michael Zucchi - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include - -#include - -#include "camel-imapp-stream.h" -#include "camel-imapp-exception.h" - -#define t(x) -#define io(x) x - -static void setup_table(void); - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelStream */ -#define CS_CLASS(so) CAMEL_IMAPP_STREAM_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -#define CAMEL_IMAPP_STREAM_SIZE (4096) -#define CAMEL_IMAPP_STREAM_TOKEN (4096) /* maximum token size */ - -static int -stream_fill(CamelIMAPPStream *is) -{ - int left = 0; - - if (is->source) { - left = is->end - is->ptr; - memcpy(is->buf, is->ptr, left); - is->end = is->buf + left; - is->ptr = is->buf; - left = camel_stream_read(is->source, is->end, CAMEL_IMAPP_STREAM_SIZE - (is->end - is->buf)); - if (left > 0) { - is->end += left; - io(printf("camel_imapp_read: buffer is '%.*s'\n", is->end - is->ptr, is->ptr)); - return is->end - is->ptr; - } else { - io(printf("camel_imapp_read: -1\n")); - return -1; - } - } - - printf("camel_imapp_read: -1\n"); - - return -1; -} - -static ssize_t -stream_read(CamelStream *stream, char *buffer, size_t n) -{ - CamelIMAPPStream *is = (CamelIMAPPStream *)stream; - ssize_t max; - - if (is->literal == 0 || n == 0) - return 0; - - max = is->end - is->ptr; - if (max > 0) { - max = MIN(max, is->literal); - max = MIN(max, n); - memcpy(buffer, is->ptr, max); - is->ptr += max; - } else { - max = MIN(is->literal, n); - max = camel_stream_read(is->source, buffer, max); - if (max <= 0) - return max; - } - - is->literal -= max; - - return max; -} - -static ssize_t -stream_write(CamelStream *stream, const char *buffer, size_t n) -{ - CamelIMAPPStream *is = (CamelIMAPPStream *)stream; - - return camel_stream_write(is->source, buffer, n); -} - -static int -stream_close(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static int -stream_flush(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static gboolean -stream_eos(CamelStream *stream) -{ - CamelIMAPPStream *is = (CamelIMAPPStream *)stream; - - return is->literal == 0; -} - -static int -stream_reset(CamelStream *stream) -{ - /* nop? reset literal mode? */ - return 0; -} - -static void -camel_imapp_stream_class_init (CamelStreamClass *camel_imapp_stream_class) -{ - CamelStreamClass *camel_stream_class = (CamelStreamClass *)camel_imapp_stream_class; - - parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE ); - - /* virtual method definition */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->close = stream_close; - camel_stream_class->flush = stream_flush; - camel_stream_class->eos = stream_eos; - camel_stream_class->reset = stream_reset; -} - -static void -camel_imapp_stream_init(CamelIMAPPStream *is, CamelIMAPPStreamClass *isclass) -{ - /* +1 is room for appending a 0 if we need to for a token */ - is->ptr = is->end = is->buf = g_malloc(CAMEL_IMAPP_STREAM_SIZE+1); - is->tokenptr = is->tokenbuf = g_malloc(CAMEL_IMAPP_STREAM_SIZE+1); - is->tokenend = is->tokenbuf + CAMEL_IMAPP_STREAM_SIZE; -} - -static void -camel_imapp_stream_finalise(CamelIMAPPStream *is) -{ - g_free(is->buf); - if (is->source) - camel_object_unref((CamelObject *)is->source); -} - -CamelType -camel_imapp_stream_get_type (void) -{ - static CamelType camel_imapp_stream_type = CAMEL_INVALID_TYPE; - - if (camel_imapp_stream_type == CAMEL_INVALID_TYPE) { - setup_table(); - camel_imapp_stream_type = camel_type_register( camel_stream_get_type(), - "CamelIMAPPStream", - sizeof( CamelIMAPPStream ), - sizeof( CamelIMAPPStreamClass ), - (CamelObjectClassInitFunc) camel_imapp_stream_class_init, - NULL, - (CamelObjectInitFunc) camel_imapp_stream_init, - (CamelObjectFinalizeFunc) camel_imapp_stream_finalise ); - } - - return camel_imapp_stream_type; -} - -/** - * camel_imapp_stream_new: - * - * Returns a NULL stream. A null stream is always at eof, and - * always returns success for all reads and writes. - * - * Return value: the stream - **/ -CamelStream * -camel_imapp_stream_new(CamelStream *source) -{ - CamelIMAPPStream *is; - - is = (CamelIMAPPStream *)camel_object_new(camel_imapp_stream_get_type ()); - camel_object_ref((CamelObject *)source); - is->source = source; - - return (CamelStream *)is; -} - - -/* - From rfc2060 - -ATOM_CHAR ::= - -atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / - quoted_specials - -CHAR ::= - -CTL ::= - -SPACE ::= - -list_wildcards ::= "%" / "*" - -quoted_specials ::= <"> / "\" -*/ - -static unsigned char imap_specials[256] = { -/* 00 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 10 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 20 */0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, -/* 30 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* 40 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* 50 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, -/* 60 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* 70 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 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, 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, 0, 0, 0, -}; - -#define imap_is_atom(c) ((imap_specials[(c)&0xff] & 0x01) != 0) -#define imap_is_simple(c) ((imap_specials[(c)&0xff] & 0x02) != 0) -#define imap_not_id(c) ((imap_specials[(c)&0xff] & 0x04) != 0) - -/* could be pregenerated, but this is cheap */ -static struct { - unsigned char *chars; - unsigned char mask; -} is_masks[] = { - { "\n*()[]+", 2 }, - { " \r\n()[]+", 4 }, -}; - -static void setup_table(void) -{ - int i; - unsigned char *p, c; - - for (i=0;i<(int)(sizeof(is_masks)/sizeof(is_masks[0]));i++) { - p = is_masks[i].chars; - while ((c = *p++)) - imap_specials[c] |= is_masks[i].mask; - } -} - -#if 0 - -static int -skip_ws(CamelIMAPPStream *is, unsigned char *pp, unsigned char *pe) -{ - register unsigned char c, *p; - unsigned char *e; - - p = is->ptr; - e = is->end; - - do { - while (p >= e ) { - is->ptr = p; - if (stream_fill(is) == IMAP_TOK_ERROR) - return IMAP_TOK_ERROR; - p = is->ptr; - e = is->end; - } - c = *p++; - } while (c == ' ' || c == '\r'); - - is->ptr = p; - is->end = e; - - return c; -} -#endif - -/* FIXME: these should probably handle it themselves, - and get rid of the token interface? */ -int -camel_imapp_stream_atom(CamelIMAPPStream *is, unsigned char **data, unsigned int *lenp) -{ - unsigned char *p, c; - - /* this is only 'approximate' atom */ - switch(camel_imapp_stream_token(is, data, lenp)) { - case IMAP_TOK_TOKEN: - p = *data; - while ((c = *p)) - *p++ = toupper(c); - case IMAP_TOK_INT: - return 0; - case IMAP_TOK_ERROR: - return IMAP_TOK_ERROR; - default: - camel_exception_throw(1, "expecting atom"); - printf("expecting atom!\n"); - return IMAP_TOK_PROTOCOL; - } -} - -/* gets an atom, a quoted_string, or a literal */ -int -camel_imapp_stream_astring(CamelIMAPPStream *is, unsigned char **data) -{ - unsigned char *p, *start; - unsigned int len, inlen; - - switch(camel_imapp_stream_token(is, data, &len)) { - case IMAP_TOK_TOKEN: - case IMAP_TOK_INT: - case IMAP_TOK_STRING: - return 0; - case IMAP_TOK_LITERAL: - /* FIXME: just grow buffer */ - if (len >= CAMEL_IMAPP_STREAM_TOKEN) { - camel_exception_throw(1, "astring: literal too long"); - printf("astring too long\n"); - return IMAP_TOK_PROTOCOL; - } - p = is->tokenptr; - camel_imapp_stream_set_literal(is, len); - do { - len = camel_imapp_stream_getl(is, &start, &inlen); - if (len < 0) - return len; - memcpy(p, start, inlen); - p += inlen; - } while (len > 0); - *data = is->tokenptr; - return 0; - case IMAP_TOK_ERROR: - /* wont get unless no exception hanlder*/ - return IMAP_TOK_ERROR; - default: - camel_exception_throw(1, "expecting astring"); - printf("expecting astring!\n"); - return IMAP_TOK_PROTOCOL; - } -} - -/* check for NIL or (small) quoted_string or literal */ -int -camel_imapp_stream_nstring(CamelIMAPPStream *is, unsigned char **data) -{ - unsigned char *p, *start; - unsigned int len, inlen; - - switch(camel_imapp_stream_token(is, data, &len)) { - case IMAP_TOK_STRING: - return 0; - case IMAP_TOK_LITERAL: - /* FIXME: just grow buffer */ - if (len >= CAMEL_IMAPP_STREAM_TOKEN) { - camel_exception_throw(1, "nstring: literal too long"); - return IMAP_TOK_PROTOCOL; - } - p = is->tokenptr; - camel_imapp_stream_set_literal(is, len); - do { - len = camel_imapp_stream_getl(is, &start, &inlen); - if (len < 0) - return len; - memcpy(p, start, inlen); - p += inlen; - } while (len > 0); - *data = is->tokenptr; - return 0; - case IMAP_TOK_TOKEN: - p = *data; - if (toupper(p[0]) == 'N' && toupper(p[1]) == 'I' && toupper(p[2]) == 'L' && p[3] == 0) { - *data = NULL; - return 0; - } - default: - camel_exception_throw(1, "expecting nstring"); - return IMAP_TOK_PROTOCOL; - case IMAP_TOK_ERROR: - /* we'll never get this unless there are no exception handlers anyway */ - return IMAP_TOK_ERROR; - - } -} - -/* parse an nstring as a stream */ -int -camel_imapp_stream_nstring_stream(CamelIMAPPStream *is, CamelStream **stream) -/* throws IO,PARSE exception */ -{ - unsigned char *token; - unsigned int len; - int ret = 0; - CamelStream * volatile mem = NULL; - - *stream = NULL; - - CAMEL_TRY { - switch(camel_imapp_stream_token(is, &token, &len)) { - case IMAP_TOK_STRING: - mem = camel_stream_mem_new_with_buffer(token, len); - *stream = mem; - break; - case IMAP_TOK_LITERAL: - /* if len is big, we could automatically use a file backing */ - camel_imapp_stream_set_literal(is, len); - mem = camel_stream_mem_new(); - if (camel_stream_write_to_stream((CamelStream *)is, mem) == -1) - camel_exception_throw(1, "nstring: io error: %s", strerror(errno)); - camel_stream_reset(mem); - *stream = mem; - break; - case IMAP_TOK_TOKEN: - if (toupper(token[0]) == 'N' && toupper(token[1]) == 'I' && toupper(token[2]) == 'L' && token[3] == 0) { - *stream = NULL; - break; - } - default: - ret = -1; - camel_exception_throw(1, "nstring: token not string"); - } - } CAMEL_CATCH(ex) { - if (mem) - camel_object_unref((CamelObject *)mem); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - /* never reaches here anyway */ - return ret; -} - -guint32 -camel_imapp_stream_number(CamelIMAPPStream *is) -{ - unsigned char *token; - unsigned int len; - - if (camel_imapp_stream_token(is, &token, &len) != IMAP_TOK_INT) { - camel_exception_throw(1, "expecting number"); - return 0; - } - - return strtoul(token, 0, 10); -} - -int -camel_imapp_stream_text(CamelIMAPPStream *is, unsigned char **text) -{ - GByteArray *build = g_byte_array_new(); - unsigned char *token; - unsigned int len; - int tok; - - CAMEL_TRY { - while (is->unget > 0) { - switch (is->unget_tok) { - case IMAP_TOK_TOKEN: - case IMAP_TOK_STRING: - case IMAP_TOK_INT: - g_byte_array_append(build, is->unget_token, is->unget_len); - g_byte_array_append(build, " ", 1); - default: /* invalid, but we'll ignore */ - break; - } - is->unget--; - } - - do { - tok = camel_imapp_stream_gets(is, &token, &len); - if (tok < 0) - camel_exception_throw(1, "io error: %s", strerror(errno)); - if (len) - g_byte_array_append(build, token, len); - } while (tok > 0); - } CAMEL_CATCH(ex) { - *text = NULL; - g_byte_array_free(build, TRUE); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - g_byte_array_append(build, "", 1); - *text = build->data; - g_byte_array_free(build, FALSE); - - return 0; -} - -/* Get one token from the imap stream */ -camel_imapp_token_t -/* throws IO,PARSE exception */ -camel_imapp_stream_token(CamelIMAPPStream *is, unsigned char **data, unsigned int *len) -{ - register unsigned char c, *p, *o, *oe; - unsigned char *e; - unsigned int literal; - int digits; - - if (is->unget > 0) { - is->unget--; - *data = is->unget_token; - *len = is->unget_len; - /*printf("token UNGET '%c' %s\n", is->unget_tok, is->unget_token);*/ - return is->unget_tok; - } - - if (is->literal > 0) - g_warning("stream_token called with literal %d", is->literal); - - p = is->ptr; - e = is->end; - - /* skip whitespace/prefill buffer */ - do { - while (p >= e ) { - is->ptr = p; - if (stream_fill(is) == IMAP_TOK_ERROR) - goto io_error; - p = is->ptr; - e = is->end; - } - c = *p++; - } while (c == ' ' || c == '\r'); - - /*strchr("\n*()[]+", c)*/ - if (imap_is_simple(c)) { - is->ptr = p; - t(printf("token '%c'\n", c)); - return c; - } else if (c == '{') { - literal = 0; - *data = p; - while (1) { - while (p < e) { - c = *p++; - if (isdigit(c) && literal < (UINT_MAX/10)) { - literal = literal * 10 + (c - '0'); - } else if (c == '}') { - while (1) { - while (p < e) { - c = *p++; - if (c == '\n') { - *len = literal; - is->ptr = p; - is->literal = literal; - t(printf("token LITERAL %d\n", literal)); - return IMAP_TOK_LITERAL; - } - } - is->ptr = p; - if (stream_fill(is) == IMAP_TOK_ERROR) - goto io_error; - p = is->ptr; - e = is->end; - } - } else { - if (isdigit(c)) - printf("Protocol error: literal too big\n"); - else - printf("Protocol error: literal contains invalid char %02x '%c'\n", c, isprint(c)?c:c); - goto protocol_error; - } - } - is->ptr = p; - if (stream_fill(is) == IMAP_TOK_ERROR) - goto io_error; - p = is->ptr; - e = is->end; - } - } else if (c == '"') { - o = is->tokenptr; - oe = is->tokenptr + CAMEL_IMAPP_STREAM_TOKEN - 1; - while (1) { - while (p < e) { - c = *p++; - if (c == '\\') { - while (p >= e) { - is->ptr = p; - if (stream_fill(is) == IMAP_TOK_ERROR) - goto io_error; - p = is->ptr; - e = is->end; - } - c = *p++; - } else if (c == '\"') { - is->ptr = p; - *o = 0; - *data = is->tokenbuf; - *len = o - is->tokenbuf; - t(printf("token STRING '%s'\n", is->tokenbuf)); - return IMAP_TOK_STRING; - } - - if (c == '\n' || c == '\r' || o>=oe) { - if (o >= oe) - printf("Protocol error: string too long\n"); - else - printf("Protocol error: truncated string\n"); - goto protocol_error; - } else { - *o++ = c; - } - } - is->ptr = p; - if (stream_fill(is) == IMAP_TOK_ERROR) - goto io_error; - p = is->ptr; - e = is->end; - } - } else { - o = is->tokenptr; - oe = is->tokenptr + CAMEL_IMAPP_STREAM_TOKEN - 1; - digits = isdigit(c); - *o++ = c; - while (1) { - while (p < e) { - c = *p++; - /*if (strchr(" \r\n*()[]+", c) != NULL) {*/ - if (imap_not_id(c)) { - if (c == ' ' || c == '\r') - is->ptr = p; - else - is->ptr = p-1; - *o = 0; - *data = is->tokenbuf; - *len = o - is->tokenbuf; - t(printf("token TOKEN '%s'\n", is->tokenbuf)); - return digits?IMAP_TOK_INT:IMAP_TOK_TOKEN; - } else if (o < oe) { - digits &= isdigit(c); - *o++ = c; - } else { - printf("Protocol error: token too long\n"); - goto protocol_error; - } - } - is->ptr = p; - if (stream_fill(is) == IMAP_TOK_ERROR) - goto io_error; - p = is->ptr; - e = is->end; - } - } - - /* Had an i/o erorr */ -io_error: - printf("Got io error\n"); - camel_exception_throw(1, "io error"); - return IMAP_TOK_ERROR; - - /* Protocol error, skip until next lf? */ -protocol_error: - printf("Got protocol error\n"); - - if (c == '\n') - is->ptr = p-1; - else - is->ptr = p; - - camel_exception_throw(1, "protocol error"); - return IMAP_TOK_PROTOCOL; -} - -void -camel_imapp_stream_ungettoken(CamelIMAPPStream *is, camel_imapp_token_t tok, unsigned char *token, unsigned int len) -{ - /*printf("ungettoken: '%c' '%s'\n", tok, token);*/ - is->unget_tok = tok; - is->unget_token = token; - is->unget_len = len; - is->unget++; -} - -/* returns -1 on error, 0 if last lot of data, >0 if more remaining */ -int camel_imapp_stream_gets(CamelIMAPPStream *is, unsigned char **start, unsigned int *len) -{ - int max; - unsigned char *end; - - *len = 0; - - max = is->end - is->ptr; - if (max == 0) { - max = stream_fill(is); - if (max <= 0) - return max; - } - - *start = is->ptr; - end = memchr(is->ptr, '\n', max); - if (end) - max = (end - is->ptr) + 1; - *start = is->ptr; - *len = max; - is->ptr += max; - - return end == NULL?1:0; -} - -void camel_imapp_stream_set_literal(CamelIMAPPStream *is, unsigned int literal) -{ - is->literal = literal; -} - -/* returns -1 on erorr, 0 if last data, >0 if more data left */ -int camel_imapp_stream_getl(CamelIMAPPStream *is, unsigned char **start, unsigned int *len) -{ - int max; - - *len = 0; - - if (is->literal > 0) { - max = is->end - is->ptr; - if (max == 0) { - max = stream_fill(is); - if (max <= 0) - return max; - } - - max = MIN(max, is->literal); - *start = is->ptr; - *len = max; - is->ptr += max; - is->literal -= max; - } - - if (is->literal > 0) - return 1; - - return 0; -} diff --git a/camel/providers/imapp/camel-imapp-stream.h b/camel/providers/imapp/camel-imapp-stream.h deleted file mode 100644 index 802c018672..0000000000 --- a/camel/providers/imapp/camel-imapp-stream.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_IMAPP_STREAM_H -#define _CAMEL_IMAPP_STREAM_H - -#include - -#define CAMEL_IMAPP_STREAM(obj) CAMEL_CHECK_CAST (obj, camel_imapp_stream_get_type (), CamelIMAPPStream) -#define CAMEL_IMAPP_STREAM_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imapp_stream_get_type (), CamelIMAPPStreamClass) -#define CAMEL_IS_IMAP_STREAM(obj) CAMEL_CHECK_TYPE (obj, camel_imapp_stream_get_type ()) - -typedef struct _CamelIMAPPStreamClass CamelIMAPPStreamClass; -typedef struct _CamelIMAPPStream CamelIMAPPStream; - -typedef enum { - IMAP_TOK_PROTOCOL = -2, - IMAP_TOK_ERROR = -1, - IMAP_TOK_TOKEN = 256, - IMAP_TOK_STRING, - IMAP_TOK_INT, - IMAP_TOK_LITERAL, -} camel_imapp_token_t; - -struct _CamelIMAPPStream { - CamelStream parent; - - CamelStream *source; - - /*int state;*/ - unsigned char *buf, *ptr, *end; - unsigned int literal; - - unsigned int unget; - camel_imapp_token_t unget_tok; - unsigned char *unget_token; - unsigned int unget_len; - - unsigned char *tokenbuf, *tokenptr, *tokenend; -}; - -struct _CamelIMAPPStreamClass { - CamelStreamClass parent_class; -}; - -CamelType camel_imapp_stream_get_type (void); - -CamelStream *camel_imapp_stream_new (CamelStream *source); - -camel_imapp_token_t camel_imapp_stream_token (CamelIMAPPStream *is, unsigned char **start, unsigned int *len); /* throws IO,PARSE exception */ -void camel_imapp_stream_ungettoken (CamelIMAPPStream *is, camel_imapp_token_t tok, unsigned char *token, unsigned int len); - -void camel_imapp_stream_set_literal (CamelIMAPPStream *is, unsigned int literal); -int camel_imapp_stream_gets (CamelIMAPPStream *is, unsigned char **start, unsigned int *len); -int camel_imapp_stream_getl (CamelIMAPPStream *is, unsigned char **start, unsigned int *len); - -/* all throw IO,PARSE exceptions */ - -/* gets an atom, upper-cases */ -int camel_imapp_stream_atom (CamelIMAPPStream *is, unsigned char **start, unsigned int *len); -/* gets an atom or string */ -int camel_imapp_stream_astring (CamelIMAPPStream *is, unsigned char **start); -/* gets a NIL or a string, start==NULL if NIL */ -int camel_imapp_stream_nstring (CamelIMAPPStream *is, unsigned char **start); -/* gets a NIL or string into a stream, stream==NULL if NIL */ -int camel_imapp_stream_nstring_stream(CamelIMAPPStream *is, CamelStream **stream); -/* gets 'text' */ -int camel_imapp_stream_text (CamelIMAPPStream *is, unsigned char **text); - -/* gets a 'number' */ -guint32 camel_imapp_stream_number(CamelIMAPPStream *is); - -#endif /* ! _CAMEL_IMAPP_STREAM_H */ diff --git a/camel/providers/imapp/camel-imapp-summary.c b/camel/providers/imapp/camel-imapp-summary.c deleted file mode 100644 index a0df21bcb0..0000000000 --- a/camel/providers/imapp/camel-imapp-summary.c +++ /dev/null @@ -1,166 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright(C) 2000 Ximian Inc. - * - * Authors: - * Michael Zucchi - * Dan Winship - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include "camel-imapp-summary.h" -#include - -#define CAMEL_IMAPP_SUMMARY_VERSION (0x1000) - -static int summary_header_load(CamelFolderSummary *, FILE *); -static int summary_header_save(CamelFolderSummary *, FILE *); - -static CamelMessageInfo *message_info_load(CamelFolderSummary *s, FILE *in); -static int message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *info); - -static void camel_imapp_summary_class_init(CamelIMAPPSummaryClass *klass); -static void camel_imapp_summary_init (CamelIMAPPSummary *obj); - -static CamelFolderSummaryClass *camel_imapp_summary_parent; - -CamelType -camel_imapp_summary_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register( - camel_folder_summary_get_type(), "CamelIMAPPSummary", - sizeof(CamelIMAPPSummary), - sizeof(CamelIMAPPSummaryClass), - (CamelObjectClassInitFunc) camel_imapp_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_imapp_summary_init, - NULL); - } - - return type; -} - -static void -camel_imapp_summary_class_init(CamelIMAPPSummaryClass *klass) -{ - CamelFolderSummaryClass *cfs_class =(CamelFolderSummaryClass *) klass; - - camel_imapp_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type())); - - cfs_class->summary_header_load = summary_header_load; - cfs_class->summary_header_save = summary_header_save; - cfs_class->message_info_load = message_info_load; - cfs_class->message_info_save = message_info_save; -} - -static void -camel_imapp_summary_init(CamelIMAPPSummary *obj) -{ - CamelFolderSummary *s =(CamelFolderSummary *)obj; - - /* subclasses need to set the right instance data sizes */ - s->message_info_size = sizeof(CamelIMAPPMessageInfo); - s->content_info_size = sizeof(CamelMessageContentInfo); - - /* and a unique file version */ - s->version += CAMEL_IMAPP_SUMMARY_VERSION; -} - -/** - * camel_imapp_summary_new: - * @filename: the file to store the summary in. - * - * This will create a new CamelIMAPPSummary object and read in the - * summary data from disk, if it exists. - * - * Return value: A new CamelIMAPPSummary object. - **/ -CamelFolderSummary * -camel_imapp_summary_new(void) -{ - CamelFolderSummary *summary = CAMEL_FOLDER_SUMMARY(camel_object_new(camel_imapp_summary_get_type())); - - return summary; -} - - -static int -summary_header_load(CamelFolderSummary *s, FILE *in) -{ - CamelIMAPPSummary *ims = CAMEL_IMAPP_SUMMARY(s); - - if (camel_imapp_summary_parent->summary_header_load(s, in) == -1) - return -1; - - return camel_file_util_decode_uint32(in, &ims->uidvalidity); -} - -static int -summary_header_save(CamelFolderSummary *s, FILE *out) -{ - CamelIMAPPSummary *ims = CAMEL_IMAPP_SUMMARY(s); - - if (camel_imapp_summary_parent->summary_header_save(s, out) == -1) - return -1; - - return camel_file_util_encode_uint32(out, ims->uidvalidity); -} - - -static CamelMessageInfo * -message_info_load(CamelFolderSummary *s, FILE *in) -{ - CamelMessageInfo *info; - CamelIMAPPMessageInfo *iinfo; - - info = camel_imapp_summary_parent->message_info_load(s, in); - if (info) { - iinfo =(CamelIMAPPMessageInfo *)info; - - if (camel_file_util_decode_uint32(in, &iinfo->server_flags) == -1) - goto error; - } - - return info; -error: - camel_folder_summary_info_free(s, info); - return NULL; -} - -static int -message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *info) -{ - CamelIMAPPMessageInfo *iinfo =(CamelIMAPPMessageInfo *)info; - - if (camel_imapp_summary_parent->message_info_save(s, out, info) == -1) - return -1; - - return camel_file_util_encode_uint32(out, iinfo->server_flags); -} diff --git a/camel/providers/imapp/camel-imapp-summary.h b/camel/providers/imapp/camel-imapp-summary.h deleted file mode 100644 index e9783625f4..0000000000 --- a/camel/providers/imapp/camel-imapp-summary.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: - * Michael Zucchi - * Dan Winship - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_IMAPP_SUMMARY_H -#define _CAMEL_IMAPP_SUMMARY_H - -#include -#include - -#define CAMEL_IMAPP_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_imapp_summary_get_type (), CamelIMAPPSummary) -#define CAMEL_IMAPP_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imapp_summary_get_type (), CamelIMAPPSummaryClass) -#define CAMEL_IS_IMAPP_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_imapp_summary_get_type ()) - -#define CAMEL_IMAPP_SERVER_FLAGS (CAMEL_MESSAGE_ANSWERED | \ - CAMEL_MESSAGE_DELETED | \ - CAMEL_MESSAGE_DRAFT | \ - CAMEL_MESSAGE_FLAGGED | \ - CAMEL_MESSAGE_SEEN) - -#define CAMEL_IMAPP_MESSAGE_RECENT (1 << 8) - -typedef struct _CamelIMAPPSummaryClass CamelIMAPPSummaryClass; -typedef struct _CamelIMAPPSummary CamelIMAPPSummary; - -typedef struct _CamelIMAPPMessageInfo { - CamelMessageInfo info; - - guint32 server_flags; -} CamelIMAPPMessageInfo; - -struct _CamelIMAPPSummary { - CamelFolderSummary parent; - - guint32 uidvalidity; -}; - -struct _CamelIMAPPSummaryClass { - CamelFolderSummaryClass parent_class; - -}; - -CamelType camel_imapp_summary_get_type (void); -CamelFolderSummary *camel_imapp_summary_new (void); - -#endif /* ! _CAMEL_IMAPP_SUMMARY_H */ - diff --git a/camel/providers/imapp/camel-imapp-utils.c b/camel/providers/imapp/camel-imapp-utils.c deleted file mode 100644 index e20499689d..0000000000 --- a/camel/providers/imapp/camel-imapp-utils.c +++ /dev/null @@ -1,1339 +0,0 @@ - -#include -#include -#include - -#include -#include -#include - -#include "camel-imapp-folder.h" -#include "camel-imapp-stream.h" -#include "camel-imapp-utils.h" -#include "camel-imapp-exception.h" -#include "camel-imapp-engine.h" -#include "e-util/e-memory.h" - -/* high-level parser state */ -#define p(x) -/* debug */ -#define d(x) - -/* ANSI-C code produced by gperf version 2.7 */ -/* Command-line: gperf -H imap_hash -N imap_tokenise -L ANSI-C -o -t -k1,$ imap-tokens.txt */ -struct _imap_keyword { char *name; enum _imap_id id; }; -/* - gperf input file - best hash generated using: gperf -o -s-2 -k1,'$' -t -H imap_hash -N imap_tokenise -L ANSI-C -*/ - -#define TOTAL_KEYWORDS 23 -#define MIN_WORD_LENGTH 2 -#define MAX_WORD_LENGTH 14 -#define MIN_HASH_VALUE 2 -#define MAX_HASH_VALUE 38 -/* maximum key range = 37, duplicates = 0 */ - -#ifdef __GNUC__ -__inline -#endif -static unsigned int -imap_hash (register const char *str, register unsigned int len) -{ - static unsigned char asso_values[] = - { - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 10, 15, 39, 20, 0, - 0, 39, 0, 10, 39, 0, 39, 39, 10, 0, - 0, 39, 0, 10, 5, 10, 39, 39, 39, 0, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39 - }; - return len + asso_values[(unsigned char)str[len - 1]] + asso_values[(unsigned char)str[0]]; -} - -#ifdef __GNUC__ -__inline -#endif -enum _imap_id -imap_tokenise (register const char *str, register unsigned int len) -{ - static struct _imap_keyword wordlist[] = - { - {""}, {""}, - {"OK", IMAP_OK}, - {""}, {""}, - {"PARSE", IMAP_PARSE}, - {""}, - {"PREAUTH", IMAP_PREAUTH}, - {"ENVELOPE", IMAP_ENVELOPE}, - {"READ-ONLY", IMAP_READ_ONLY}, - {"READ-WRITE", IMAP_READ_WRITE}, - {"RFC822.SIZE", IMAP_RFC822_SIZE}, - {"NO", IMAP_NO}, - {"RFC822.HEADER", IMAP_RFC822_HEADER}, - {"TRYCREATE", IMAP_TRYCREATE}, - {"FLAGS", IMAP_FLAGS}, - {"RFC822.TEXT", IMAP_RFC822_TEXT}, - {"NEWNAME", IMAP_NEWNAME}, - {"BYE", IMAP_BYE}, - {"BODY", IMAP_BODY}, - {"ALERT", IMAP_ALERT}, - {"UIDVALIDITY", IMAP_UIDVALIDITY}, - {"INTERNALDATE", IMAP_INTERNALDATE}, - {""}, - {"PERMANENTFLAGS", IMAP_PERMANENTFLAGS}, - {""}, - {"UNSEEN", IMAP_UNSEEN}, - {""}, - {"BODYSTRUCTURE", IMAP_BODYSTRUCTURE}, - {""}, {""}, {""}, {""}, - {"UID", IMAP_UID}, - {""}, {""}, {""}, {""}, - {"BAD", IMAP_BAD} - }; - - if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) - { - register int key = imap_hash (str, len); - - if (key <= MAX_HASH_VALUE && key >= 0) - { - register const char *s = wordlist[key].name; - - if (*str == *s && !strcmp (str + 1, s + 1)) - return wordlist[key].id; - } - } - return 0; -} - -/* flag table */ -static struct { - char *name; - guint32 flag; -} flag_table[] = { - { "\\ANSWERED", CAMEL_MESSAGE_ANSWERED }, - { "\\DELETED", CAMEL_MESSAGE_DELETED }, - { "\\DRAFT", CAMEL_MESSAGE_DRAFT }, - { "\\FLAGGED", CAMEL_MESSAGE_FLAGGED }, - { "\\SEEN", CAMEL_MESSAGE_SEEN }, - { "\\RECENT", CAMEL_IMAPP_MESSAGE_RECENT }, - { "\\*", CAMEL_MESSAGE_USER }, -}; - -/* utility functions - shoudl this be part of imapp-driver? */ -/* mabye this should be a stream op? */ -void -imap_parse_flags(CamelIMAPPStream *stream, guint32 *flagsp) -/* throws IO,PARSE exception */ -{ - int tok, len, i; - unsigned char *token, *p, c; - guint32 flags = 0; - - *flagsp = flags; - - tok = camel_imapp_stream_token(stream, &token, &len); - if (tok == '(') { - do { - tok = camel_imapp_stream_token(stream, &token, &len); - if (tok == IMAP_TOK_TOKEN) { - p = token; - while ((c=*p)) - *p++ = toupper(c); - for (i=0;i<(int)(sizeof(flag_table)/sizeof(flag_table[0]));i++) - if (!strcmp(token, flag_table[i].name)) - flags |= flag_table[i].flag; - } else if (tok != ')') { - camel_exception_throw(1, "expecting flag"); - } - } while (tok != ')'); - } else { - camel_exception_throw(1, "expecting flag list"); - } - - *flagsp = flags; -} - -void -imap_write_flags(CamelStream *stream, guint32 flags) -/* throws IO exception */ -{ - int i; - - /* all this ugly exception throwing goes away once camel streams throw their own? */ - if (camel_stream_write(stream, "(", 1) == -1) - camel_exception_throw(1, "io error: %s", strerror(errno)); - - for (i=0;flags!=0 && i<(int)(sizeof(flag_table)/sizeof(flag_table[0]));i++) { - if (flag_table[i].flag & flags) { - if (camel_stream_write(stream, flag_table[i].name, strlen(flag_table[i].name)) == -1) - camel_exception_throw(1, "io error: %s", strerror(errno)); - flags &= ~flag_table[i].flag; - if (flags != 0) - if (camel_stream_write(stream, " ", 1) == -1) - camel_exception_throw(1, "io error: %s", strerror(errno)); - } - } - - if (camel_stream_write(stream, ")", 1) == -1) - camel_exception_throw(1, "io error: %s", strerror(errno)); -} - -/* -body ::= "(" body_type_1part / body_type_mpart ")" - -body_extension ::= nstring / number / "(" 1#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 [SPACE body_fld_dsp - [SPACE body_fld_lang - [SPACE 1#body_extension]]] - ;; MUST NOT be returned on non-extensible - ;; "BODY" fetch - -body_ext_mpart ::= body_fld_param - [SPACE body_fld_dsp SPACE body_fld_lang - [SPACE 1#body_extension]] - ;; MUST NOT be returned on non-extensible - ;; "BODY" fetch - -body_fields ::= body_fld_param SPACE body_fld_id SPACE - body_fld_desc SPACE body_fld_enc SPACE - body_fld_octets - -body_fld_desc ::= nstring - -body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil - -body_fld_enc ::= (<"> ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ - "QUOTED-PRINTABLE") <">) / string - -body_fld_id ::= nstring - -body_fld_lang ::= nstring / "(" 1#string ")" - -body_fld_lines ::= number - -body_fld_md5 ::= nstring - -body_fld_octets ::= number - -body_fld_param ::= "(" 1#(string SPACE string) ")" / nil - -body_type_1part ::= (body_type_basic / body_type_msg / body_type_text) - [SPACE body_ext_1part] - -body_type_basic ::= media_basic SPACE body_fields - ;; MESSAGE subtype MUST NOT be "RFC822" - -body_type_mpart ::= 1*body SPACE media_subtype - [SPACE body_ext_mpart] - -body_type_msg ::= media_message SPACE body_fields SPACE envelope - SPACE body SPACE body_fld_lines - -body_type_text ::= media_text SPACE body_fields SPACE body_fld_lines - -envelope ::= "(" env_date SPACE env_subject SPACE env_from - SPACE env_sender SPACE env_reply_to SPACE env_to - SPACE env_cc SPACE env_bcc SPACE env_in_reply_to - SPACE 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 - -media_basic ::= (<"> ("APPLICATION" / "AUDIO" / "IMAGE" / - "MESSAGE" / "VIDEO") <">) / string) - SPACE media_subtype - ;; Defined in [MIME-IMT] - -media_message ::= <"> "MESSAGE" <"> SPACE <"> "RFC822" <"> - ;; Defined in [MIME-IMT] - -media_subtype ::= string - ;; Defined in [MIME-IMT] - -media_text ::= <"> "TEXT" <"> SPACE media_subtype - ;; Defined in [MIME-IMT] - - - - ( "type" "subtype" body_fields [envelope body body_fld_lines] - [body_fld_lines] - - - - (("TEXT" "PLAIN" ("CHARSET" - "US-ASCII") NIL NIL "7BIT" 1152 23)("TEXT" "PLAIN" - ("CHARSET" "US-ASCII" "NAME" "cc.diff") - "<960723163407.20117h@cac.washington.edu>" - "Compiler diff" "BASE64" 4554 73) "MIXED")) - -*/ - -/* -struct _body_fields { - CamelContentType *ct; - char *msgid, *desc; - CamelTransferEncoding encoding; - guint32 size; - };*/ - -void -imap_free_body(struct _CamelMessageContentInfo *cinfo) -{ - struct _CamelMessageContentInfo *list, *next; - - list = cinfo->childs; - while (list) { - next = list->next; - imap_free_body(list); - list = next; - } - - if (cinfo->type) - camel_content_type_unref(cinfo->type); - g_free(cinfo->id); - g_free(cinfo->description); - g_free(cinfo->encoding); - g_free(cinfo); -} - -void -imap_parse_param_list(CamelIMAPPStream *is, struct _camel_header_param **plist) -{ - int tok, len; - unsigned char *token, *param; - - p(printf("body_fld_param\n")); - - /* body_fld_param ::= "(" 1#(string SPACE string) ")" / nil */ - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == '(') { - while (1) { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == ')') - break; - camel_imapp_stream_ungettoken(is, tok, token, len); - - camel_imapp_stream_astring(is, &token); - param = alloca(strlen(token)+1); - strcpy(param, token); - camel_imapp_stream_astring(is, &token); - camel_header_set_param(plist, param, token); - } - } /* else check nil? no need */ -} - -struct _CamelContentDisposition * -imap_parse_ext_optional(CamelIMAPPStream *is) -{ - int tok, len; - unsigned char *token; - struct _CamelContentDisposition * volatile dinfo = NULL; - - /* this parses both extension types, from the body_fld_dsp onwards */ - /* although the grammars are different, they can be parsed the same way */ - - /* body_ext_1part ::= body_fld_md5 [SPACE body_fld_dsp - [SPACE body_fld_lang - [SPACE 1#body_extension]]] - ;; MUST NOT be returned on non-extensible - ;; "BODY" fetch */ - - /* body_ext_mpart ::= body_fld_param - [SPACE body_fld_dsp SPACE body_fld_lang - [SPACE 1#body_extension]] - ;; MUST NOT be returned on non-extensible - ;; "BODY" fetch */ - - CAMEL_TRY { - /* body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil */ - - tok = camel_imapp_stream_token(is, &token, &len); - switch (tok) { - case '(': - dinfo = g_malloc0(sizeof(*dinfo)); - dinfo->refcount = 1; - /* should be string */ - camel_imapp_stream_astring(is, &token); - - dinfo->disposition = g_strdup(token); - imap_parse_param_list(is, &dinfo->params); - case IMAP_TOK_TOKEN: - d(printf("body_fld_dsp: NIL\n")); - break; - default: - camel_exception_throw(1, "body_fld_disp: expecting nil or list"); - } - - p(printf("body_fld_lang\n")); - - /* body_fld_lang ::= nstring / "(" 1#string ")" */ - - /* we just drop the lang string/list, save it somewhere? */ - - tok = camel_imapp_stream_token(is, &token, &len); - switch (tok) { - case '(': - while (1) { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == ')') { - break; - } else if (tok != IMAP_TOK_STRING) { - camel_exception_throw(1, "expecting string"); - } - } - break; - case IMAP_TOK_TOKEN: - d(printf("body_fld_lang = nil\n")); - /* treat as 'nil' */ - break; - case IMAP_TOK_STRING: - /* we have a string */ - break; - case IMAP_TOK_LITERAL: - /* we have a literal string */ - camel_imapp_stream_set_literal(is, len); - while ((tok = camel_imapp_stream_getl(is, &token, &len)) > 0) { - d(printf("Skip literal data '%.*s'\n", (int)len, token)); - } - break; - - } - } CAMEL_CATCH(ex) { - if (dinfo) - camel_content_disposition_unref(dinfo); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return dinfo; -} - -struct _CamelMessageContentInfo * -imap_parse_body_fields(CamelIMAPPStream *is) -{ - unsigned char *token, *type; - struct _CamelMessageContentInfo *cinfo; - - /* body_fields ::= body_fld_param SPACE body_fld_id SPACE - body_fld_desc SPACE body_fld_enc SPACE - body_fld_octets */ - - p(printf("body_fields\n")); - - cinfo = g_malloc0(sizeof(*cinfo)); - - CAMEL_TRY { - /* this should be string not astring */ - camel_imapp_stream_astring(is, &token); - type = alloca(strlen(token)+1); - strcpy(type, token); - camel_imapp_stream_astring(is, &token); - cinfo->type = camel_content_type_new(type, token); - imap_parse_param_list(is, &cinfo->type->params); - - /* body_fld_id ::= nstring */ - camel_imapp_stream_nstring(is, &token); - cinfo->id = g_strdup(token); - - /* body_fld_desc ::= nstring */ - camel_imapp_stream_nstring(is, &token); - cinfo->description = g_strdup(token); - - /* body_fld_enc ::= (<"> ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ - "QUOTED-PRINTABLE") <">) / string */ - camel_imapp_stream_astring(is, &token); - cinfo->encoding = g_strdup(token); - - /* body_fld_octets ::= number */ - cinfo->size = camel_imapp_stream_number(is); - } CAMEL_CATCH(ex) { - imap_free_body(cinfo); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return cinfo; -} - -struct _camel_header_address * -imap_parse_address_list(CamelIMAPPStream *is) -/* throws PARSE,IO exception */ -{ - int tok, len; - unsigned char *token, *host, *mbox; - struct _camel_header_address *list = NULL; - - /* "(" 1*address ")" / nil */ - - CAMEL_TRY { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == '(') { - while (1) { - struct _camel_header_address *addr, *group = NULL; - - /* address ::= "(" addr_name SPACE addr_adl SPACE addr_mailbox - SPACE addr_host ")" */ - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == ')') - break; - if (tok != '(') - camel_exception_throw(1, "missing '(' for address"); - - addr = camel_header_address_new(); - addr->type = HEADER_ADDRESS_NAME; - tok = camel_imapp_stream_nstring(is, &token); - addr->name = g_strdup(token); - /* we ignore the route, nobody uses it in the real world */ - tok = camel_imapp_stream_nstring(is, &token); - - /* [RFC-822] group syntax is indicated by a special - form of address structure in which the host name - field is NIL. If the mailbox name field is also - NIL, this is an end of group marker (semi-colon in - RFC 822 syntax). If the mailbox name field is - non-NIL, this is a start of group marker, and the - mailbox name field holds the group name phrase. */ - - tok = camel_imapp_stream_nstring(is, &mbox); - mbox = g_strdup(mbox); - tok = camel_imapp_stream_nstring(is, &host); - if (host == NULL) { - if (mbox == NULL) { - group = NULL; - } else { - d(printf("adding group '%s'\n", mbox)); - g_free(addr->name); - addr->name = mbox; - addr->type = HEADER_ADDRESS_GROUP; - camel_header_address_list_append(&list, addr); - group = addr; - } - } else { - addr->v.addr = g_strdup_printf("%s%s%s", mbox?(char *)mbox:"", host?"@":"", host?(char *)host:""); - g_free(mbox); - d(printf("adding address '%s'\n", addr->v.addr)); - if (group != NULL) - camel_header_address_add_member(group, addr); - else - camel_header_address_list_append(&list, addr); - } - do { - tok = camel_imapp_stream_token(is, &token, &len); - } while (tok != ')'); - } - } else { - d(printf("empty, nil '%s'\n", token)); - } - } CAMEL_CATCH(ex) { - camel_header_address_list_clear(&list); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return list; -} - -struct _CamelMessageInfo * -imap_parse_envelope(CamelIMAPPStream *is) -{ - int tok, len; - unsigned char *token; - struct _camel_header_address *addr, *addr_from; - char *addrstr; - struct _CamelMessageInfo *minfo; - - /* envelope ::= "(" env_date SPACE env_subject SPACE env_from - SPACE env_sender SPACE env_reply_to SPACE env_to - SPACE env_cc SPACE env_bcc SPACE env_in_reply_to - SPACE env_message_id ")" */ - - p(printf("envelope\n")); - - minfo = camel_message_info_new(); - - CAMEL_TRY { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != '(') - camel_exception_throw(1, "envelope: expecting '('"); - - /* env_date ::= nstring */ - camel_imapp_stream_nstring(is, &token); - minfo->date_sent = camel_header_decode_date(token, NULL); - - /* env_subject ::= nstring */ - tok = camel_imapp_stream_nstring(is, &token); - /* DUH: this free's it!: camel_message_info_set_subject(minfo, token); */ - e_poolv_set(minfo->strings, CAMEL_MESSAGE_INFO_SUBJECT, token, FALSE); - - /* we merge from/sender into from, append should probably merge more smartly? */ - - /* env_from ::= "(" 1*address ")" / nil */ - addr_from = imap_parse_address_list(is); - - /* env_sender ::= "(" 1*address ")" / nil */ - addr = imap_parse_address_list(is); - if (addr_from) { - camel_header_address_list_clear(&addr); -#if 0 - if (addr) - camel_header_address_list_append_list(&addr_from, &addr); -#endif - } else { - if (addr) - addr_from = addr; - } - - if (addr_from) { - addrstr = camel_header_address_list_format(addr_from); - camel_message_info_set_from(minfo, addrstr); - camel_header_address_list_clear(&addr_from); - } - - /* we dont keep reply_to */ - - /* env_reply_to ::= "(" 1*address ")" / nil */ - addr = imap_parse_address_list(is); - camel_header_address_list_clear(&addr); - - /* env_to ::= "(" 1*address ")" / nil */ - addr = imap_parse_address_list(is); - if (addr) { - addrstr = camel_header_address_list_format(addr); - camel_message_info_set_to(minfo, addrstr); - camel_header_address_list_clear(&addr); - } - - /* env_cc ::= "(" 1*address ")" / nil */ - addr = imap_parse_address_list(is); - if (addr) { - addrstr = camel_header_address_list_format(addr); - camel_message_info_set_cc(minfo, addrstr); - camel_header_address_list_clear(&addr); - } - - /* we dont keep bcc either */ - - /* env_bcc ::= "(" 1*address ")" / nil */ - addr = imap_parse_address_list(is); - camel_header_address_list_clear(&addr); - - /* FIXME: need to put in-reply-to into references hash list */ - - /* env_in_reply_to ::= nstring */ - tok = camel_imapp_stream_nstring(is, &token); - - /* FIXME: need to put message-id into message-id hash */ - - /* env_message_id ::= nstring */ - tok = camel_imapp_stream_nstring(is, &token); - - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != ')') - camel_exception_throw(1, "expecting ')'"); - } CAMEL_CATCH(ex) { - camel_message_info_free(minfo); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return minfo; -} - -struct _CamelMessageContentInfo * -imap_parse_body(CamelIMAPPStream *is) -{ - int tok, len; - unsigned char *token; - struct _CamelMessageContentInfo * volatile cinfo = NULL; - struct _CamelMessageContentInfo *subinfo, *last; - struct _CamelContentDisposition * volatile dinfo = NULL; - struct _CamelMessageInfo * volatile minfo = NULL; - - /* body ::= "(" body_type_1part / body_type_mpart ")" */ - - p(printf("body\n")); - - CAMEL_TRY { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != '(') - camel_exception_throw(1, "body: expecting '('"); - - /* 1*body (optional for multiparts) */ - tok = camel_imapp_stream_token(is, &token, &len); - camel_imapp_stream_ungettoken(is, tok, token, len); - if (tok == '(') { - /* body_type_mpart ::= 1*body SPACE media_subtype - [SPACE body_ext_mpart] */ - - cinfo = g_malloc0(sizeof(*cinfo)); - last = (struct _CamelMessageContentInfo *)&cinfo->childs; - do { - subinfo = imap_parse_body(is); - last->next = subinfo; - last = subinfo; - subinfo->parent = cinfo; - tok = camel_imapp_stream_token(is, &token, &len); - camel_imapp_stream_ungettoken(is, tok, token, len); - } while (tok == '('); - - d(printf("media_subtype\n")); - - camel_imapp_stream_astring(is, &token); - cinfo->type = camel_content_type_new("multipart", token); - - /* body_ext_mpart ::= body_fld_param - [SPACE body_fld_dsp SPACE body_fld_lang - [SPACE 1#body_extension]] - ;; MUST NOT be returned on non-extensible - ;; "BODY" fetch */ - - d(printf("body_ext_mpart\n")); - - tok = camel_imapp_stream_token(is, &token, &len); - camel_imapp_stream_ungettoken(is, tok, token, len); - if (tok == '(') { - imap_parse_param_list(is, &cinfo->type->params); - - /* body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil */ - - tok = camel_imapp_stream_token(is, &token, &len); - camel_imapp_stream_ungettoken(is, tok, token, len); - if (tok == '(' || tok == IMAP_TOK_TOKEN) { - dinfo = imap_parse_ext_optional(is); - /* other extension fields?, soaked up below */ - } else { - camel_imapp_stream_ungettoken(is, tok, token, len); - } - } - } else { - /* body_type_1part ::= (body_type_basic / body_type_msg / body_type_text) - [SPACE body_ext_1part] - - body_type_basic ::= media_basic SPACE body_fields - body_type_text ::= media_text SPACE body_fields SPACE body_fld_lines - body_type_msg ::= media_message SPACE body_fields SPACE envelope - SPACE body SPACE body_fld_lines */ - - d(printf("Single part body\n")); - - cinfo = imap_parse_body_fields(is); - - d(printf("envelope?\n")); - - /* do we have an envelope following */ - tok = camel_imapp_stream_token(is, &token, &len); - camel_imapp_stream_ungettoken(is, tok, token, len); - if (tok == '(') { - /* what do we do with the envelope?? */ - minfo = imap_parse_envelope(is); - /* what do we do with the message content info?? */ - minfo->content = imap_parse_body(is); - camel_message_info_free(minfo); - minfo = NULL; - d(printf("Scanned envelope - what do i do with it?\n")); - } - - d(printf("fld_lines?\n")); - - /* do we have fld_lines following? */ - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == IMAP_TOK_INT) { - d(printf("field lines: %s\n", token)); - tok = camel_imapp_stream_token(is, &token, &len); - } - camel_imapp_stream_ungettoken(is, tok, token, len); - - /* body_ext_1part ::= body_fld_md5 [SPACE body_fld_dsp - [SPACE body_fld_lang - [SPACE 1#body_extension]]] - ;; MUST NOT be returned on non-extensible - ;; "BODY" fetch */ - - d(printf("extension data?\n")); - - if (tok != ')') { - camel_imapp_stream_nstring(is, &token); - - d(printf("md5: %s\n", token?(char *)token:"NIL")); - - /* body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil */ - - tok = camel_imapp_stream_token(is, &token, &len); - camel_imapp_stream_ungettoken(is, tok, token, len); - if (tok == '(' || tok == IMAP_TOK_TOKEN) { - dinfo = imap_parse_ext_optional(is); - /* then other extension fields, soaked up below */ - } - } - } - - /* soak up any other extension fields that may be present */ - /* there should only be simple tokens, no lists */ - do { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != ')') - d(printf("Dropping extension data '%s'\n", token)); - } while (tok != ')'); - } CAMEL_CATCH(ex) { - if (cinfo) - imap_free_body(cinfo); - if (dinfo) - camel_content_disposition_unref(dinfo); - if (minfo) - camel_message_info_free(minfo); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - /* FIXME: do something with the disposition, currently we have no way to pass it out? */ - if (dinfo) - camel_content_disposition_unref(dinfo); - - return cinfo; -} - -char * -imap_parse_section(CamelIMAPPStream *is) -{ - int tok, len; - unsigned char *token; - char * volatile section = NULL; - - /* currently we only return the part within the [section] specifier - any header fields are parsed, but dropped */ - - /* - section ::= "[" [section_text / - (nz_number *["." nz_number] ["." (section_text / "MIME")])] "]" - - section_text ::= "HEADER" / "HEADER.FIELDS" [".NOT"] - SPACE header_list / "TEXT" - */ - - CAMEL_TRY { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != '[') - camel_exception_throw(1, "section: expecting '['"); - - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == IMAP_TOK_INT || tok == IMAP_TOK_TOKEN) - section = g_strdup(token); - else if (tok == ']') { - section = g_strdup(""); - camel_imapp_stream_ungettoken(is, tok, token, len); - } else - camel_exception_throw(1, "section: expecting token"); - - /* header_list ::= "(" 1#header_fld_name ")" - header_fld_name ::= astring */ - - /* we dont need the header specifiers */ - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == '(') { - do { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == IMAP_TOK_STRING || tok == IMAP_TOK_TOKEN || tok == IMAP_TOK_INT) { - /* ?do something? */ - } else if (tok != ')') - camel_exception_throw(1, "section: header fields: expecting string"); - } while (tok != ')'); - tok = camel_imapp_stream_token(is, &token, &len); - } - - if (tok != ']') - camel_exception_throw(1, "section: expecting ']'"); - } CAMEL_CATCH(ex) { - g_free(section); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return section; -} - -void -imap_free_fetch(struct _fetch_info *finfo) -{ - if (finfo == NULL) - return; - - if (finfo->body) - camel_object_unref((CamelObject *)finfo->body); - if (finfo->text) - camel_object_unref((CamelObject *)finfo->text); - if (finfo->header) - camel_object_unref((CamelObject *)finfo->header); - if (finfo->minfo) - camel_message_info_free(finfo->minfo); - if (finfo->cinfo) - imap_free_body(finfo->cinfo); - g_free(finfo->date); - g_free(finfo->section); - g_free(finfo->uid); - g_free(finfo); -} - -extern void camel_content_info_dump(CamelMessageContentInfo *ci, int depth); -extern void camel_message_info_dump(CamelMessageInfo *mi); - -#include - -/* debug, dump one out */ -void -imap_dump_fetch(struct _fetch_info *finfo) -{ - CamelStream *sout; - int fd; - - printf("Fetch info:\n"); - if (finfo == NULL) { - printf("Empty\n"); - return; - } - - fd = dup(1); - sout = camel_stream_fs_new_with_fd(fd); - if (finfo->body) { - camel_stream_printf(sout, "Body content:\n"); - camel_stream_write_to_stream(finfo->body, sout); - } - if (finfo->text) { - camel_stream_printf(sout, "Text content:\n"); - camel_stream_write_to_stream(finfo->text, sout); - } - if (finfo->header) { - camel_stream_printf(sout, "Header content:\n"); - camel_stream_write_to_stream(finfo->header, sout); - } - if (finfo->minfo) { - camel_stream_printf(sout, "Message Info:\n"); - camel_message_info_dump(finfo->minfo); - } - if (finfo->cinfo) { - camel_stream_printf(sout, "Content Info:\n"); - camel_content_info_dump(finfo->cinfo, 0); - } - if (finfo->got & FETCH_SIZE) - camel_stream_printf(sout, "Size: %d\n", (int)finfo->size); - if (finfo->got & FETCH_BODY) - camel_stream_printf(sout, "Offset: %d\n", (int)finfo->offset); - if (finfo->got & FETCH_FLAGS) - camel_stream_printf(sout, "Flags: %08x\n", (int)finfo->flags); - if (finfo->date) - camel_stream_printf(sout, "Date: '%s'\n", finfo->date); - if (finfo->section) - camel_stream_printf(sout, "Section: '%s'\n", finfo->section); - if (finfo->date) - camel_stream_printf(sout, "UID: '%s'\n", finfo->uid); - camel_object_unref((CamelObject *)sout); -} - -struct _fetch_info * -imap_parse_fetch(CamelIMAPPStream *is) -{ - int tok, len; - unsigned char *token, *p, c; - struct _fetch_info *finfo; - - finfo = g_malloc0(sizeof(*finfo)); - - CAMEL_TRY { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != '(') - camel_exception_throw(1, "fetch: expecting '('"); - - while ( (tok = camel_imapp_stream_token(is, &token, &len)) == IMAP_TOK_TOKEN ) { - - p = token; - while ((c=*p)) - *p++ = toupper(c); - - switch(imap_tokenise(token, len)) { - case IMAP_ENVELOPE: - finfo->minfo = imap_parse_envelope(is); - finfo->got |= FETCH_MINFO; - break; - case IMAP_FLAGS: - imap_parse_flags(is, &finfo->flags); - finfo->got |= FETCH_FLAGS; - break; - case IMAP_INTERNALDATE: - camel_imapp_stream_nstring(is, &token); - /* TODO: convert to camel format? */ - finfo->date = g_strdup(token); - finfo->got |= FETCH_DATE; - break; - case IMAP_RFC822_HEADER: - camel_imapp_stream_nstring_stream(is, &finfo->header); - finfo->got |= FETCH_HEADER; - break; - case IMAP_RFC822_TEXT: - camel_imapp_stream_nstring_stream(is, &finfo->text); - finfo->got |= FETCH_TEXT; - break; - case IMAP_RFC822_SIZE: - finfo->size = camel_imapp_stream_number(is); - finfo->got |= FETCH_SIZE; - break; - case IMAP_BODYSTRUCTURE: - finfo->cinfo = imap_parse_body(is); - finfo->got |= FETCH_CINFO; - break; - case IMAP_BODY: - tok = camel_imapp_stream_token(is, &token, &len); - camel_imapp_stream_ungettoken(is, tok, token, len); - if (tok == '(') { - finfo->cinfo = imap_parse_body(is); - finfo->got |= FETCH_CINFO; - } else if (tok == '[') { - finfo->section = imap_parse_section(is); - finfo->got |= FETCH_SECTION; - tok = camel_imapp_stream_token(is, &token, &len); - if (token[0] == '<') { - finfo->offset = strtoul(token+1, NULL, 10); - } else { - camel_imapp_stream_ungettoken(is, tok, token, len); - } - camel_imapp_stream_nstring_stream(is, &finfo->body); - finfo->got |= FETCH_BODY; - } else { - camel_exception_throw(1, "unknown body response"); - } - break; - case IMAP_UID: - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != IMAP_TOK_INT) - camel_exception_throw(1, "uid not integer"); - finfo->uid = g_strdup(token); - finfo->got |= FETCH_UID; - break; - default: - camel_exception_throw(1, "unknown body response"); - } - } - - if (tok != ')') - camel_exception_throw(1, "missing closing ')' on fetch response"); - } CAMEL_CATCH(ex) { - imap_free_fetch(finfo); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return finfo; -} - -/* rfc 2060 section 7.1 Status Responses */ -/* shoudl this start after [ or before the [? token_unget anyone? */ -struct _status_info * -imap_parse_status(CamelIMAPPStream *is) -{ - int tok, len; - unsigned char *token; - struct _status_info *sinfo; - - sinfo = g_malloc0(sizeof(*sinfo)); - - CAMEL_TRY { - camel_imapp_stream_atom(is, &token, &len); - - /* - resp_cond_auth ::= ("OK" / "PREAUTH") SPACE resp_text - ;; Authentication condition - - resp_cond_bye ::= "BYE" SPACE resp_text - - resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text - ;; Status condition - */ - - sinfo->result = imap_tokenise(token, len); - switch (sinfo->result) { - case IMAP_OK: - case IMAP_NO: - case IMAP_BAD: - case IMAP_PREAUTH: - case IMAP_BYE: - break; - default: - camel_exception_throw(1, "expecting OK/NO/BAD"); - } - - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == '[') { - camel_imapp_stream_atom(is, &token, &len); - sinfo->condition = imap_tokenise(token, len); - - /* parse any details */ - switch (sinfo->condition) { - case IMAP_READ_ONLY: - case IMAP_READ_WRITE: - case IMAP_ALERT: - case IMAP_PARSE: - case IMAP_TRYCREATE: - break; - case IMAP_NEWNAME: - /* the rfc doesn't specify the bnf for this */ - camel_imapp_stream_astring(is, &token); - sinfo->u.newname.oldname = g_strdup(token); - camel_imapp_stream_astring(is, &token); - sinfo->u.newname.newname = g_strdup(token); - break; - case IMAP_PERMANENTFLAGS: - imap_parse_flags(is, &sinfo->u.permanentflags); - break; - case IMAP_UIDVALIDITY: - sinfo->u.uidvalidity = camel_imapp_stream_number(is); - break; - case IMAP_UNSEEN: - sinfo->u.unseen = camel_imapp_stream_number(is); - break; - default: - sinfo->condition = IMAP_UNKNOWN; - printf("Got unknown response code: %s: ignored\n", token); - } - - /* ignore anything we dont know about */ - do { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == '\n') - camel_exception_throw(1, "server response truncated"); - } while (tok != ']'); - } else { - camel_imapp_stream_ungettoken(is, tok, token, len); - } - - /* and take the human readable response */ - camel_imapp_stream_text(is, (unsigned char **)&sinfo->text); - } CAMEL_CATCH(ex) { - imap_free_status(sinfo); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return sinfo; -} - -void -imap_free_status(struct _status_info *sinfo) -{ - if (sinfo == NULL) - return; - - switch (sinfo->condition) { - case IMAP_NEWNAME: - g_free(sinfo->u.newname.oldname); - g_free(sinfo->u.newname.newname); - default: - break; - } - - g_free(sinfo->text); - g_free(sinfo); -} - -/* FIXME: use tokeniser? */ -/* FIXME: real flags */ -static struct { - char *name; - guint32 flag; -} list_flag_table[] = { - { "\\NOINFERIORS", CAMEL_FOLDER_NOINFERIORS }, - { "\\NOSELECT", CAMEL_FOLDER_NOSELECT }, - { "\\MARKED", 1<<8 }, - { "\\UNMARKED", 1<<9 }, -}; - -struct _list_info * -imap_parse_list(CamelIMAPPStream *is) -/* throws io, parse */ -{ - int tok, len, i; - unsigned char *token, *p, c; - struct _list_info * volatile linfo; - - linfo = g_malloc0(sizeof(*linfo)); - - CAMEL_TRY { - /* mailbox_list ::= "(" #("\Marked" / "\Noinferiors" / - "\Noselect" / "\Unmarked" / flag_extension) ")" - SPACE (<"> QUOTED_CHAR <"> / nil) SPACE mailbox */ - - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != '(') - camel_exception_throw(1, "list: expecting '('"); - - while ( (tok = camel_imapp_stream_token(is, &token, &len)) != ')' ) { - if (tok == IMAP_TOK_STRING || tok == IMAP_TOK_TOKEN) { - p = token; - while ((c=*p)) - *p++ = toupper(c); - for (i=0;i<(int)(sizeof(list_flag_table)/sizeof(list_flag_table[0]));i++) - if (!strcmp(token, list_flag_table[i].name)) - linfo->flags |= list_flag_table[i].flag; - } else { - camel_exception_throw(1, "list: expecting flag or ')'"); - } - } - - camel_imapp_stream_nstring(is, &token); - linfo->separator = token?*token:0; - camel_imapp_stream_astring(is, &token); - linfo->name = g_strdup(token); - } CAMEL_CATCH(ex) { - imap_free_list(linfo); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return linfo; -} - -char * -imapp_list_get_path(struct _list_info *li) -{ - char *path, *p; - int c; - const char *f; - - if (li->separator != 0 && li->separator != '/') { - p = path = alloca(strlen(li->name)*3+1); - f = li->name; - while ( (c = *f++ & 0xff) ) { - if (c == li->separator) - *p++ = '/'; - else if (c == '/' || c == '%') - p += sprintf(p, "%%%02X", c); - else - *p++ = c; - } - *p = 0; - } else - path = li->name; - - return camel_utf7_utf8(path); -} - -void -imap_free_list(struct _list_info *linfo) -{ - if (linfo) { - g_free(linfo->name); - g_free(linfo); - } -} - - -/* ********************************************************************** */ -/* utility functions */ - -/* should the rest of imapp-utils go into imapp-parse? */ - -/* this creates a uid (or sequence number) set directly into the command, - optionally breaking it into smaller chunks */ - -void -imapp_uidset_init(struct _uidset_state *ss, CamelIMAPPEngine *ie) -{ - ss->ie = ie; - ss->len = 0; - ss->start = 0; - ss->last = 0; -} - -int -imapp_uidset_done(struct _uidset_state *ss, CamelIMAPPCommand *ic) -{ - int ret = 0; - - if (ss->last != 0 && ss->last != ss->start) { - camel_imapp_engine_command_add(ss->ie, ic, ":%d", ss->last); - printf(":%d", ss->last); - } - - ret = ss->last != 0; - - ss->start = 0; - ss->last = 0; - ss->len = 0; - - return ret; -} - -int -imapp_uidset_add(struct _uidset_state *ss, CamelIMAPPCommand *ic, const char *uid) -{ - guint32 uidn; - - uidn = strtoul(uid, NULL, 10); - if (uidn == 0) - return -1; - - if (ss->last == 0) { - camel_imapp_engine_command_add(ss->ie, ic, "%d", uidn); - printf("%d", uidn); - ss->len ++; - ss->start = uidn; - } else { - if (ss->last != uidn-1) { - if (ss->last == ss->start) { - camel_imapp_engine_command_add(ss->ie, ic, ",%d", uidn); - printf(",%d", uidn); - ss->len ++; - } else { - camel_imapp_engine_command_add(ss->ie, ic, ":%d,%d", ss->last, uidn); - printf(":%d,%d", ss->last, uidn); - ss->len+=2; - } - ss->start = uidn; - } - } - - ss->last = uidn; - - if (ss->len > 10) { - imapp_uidset_done(ss, ic); - return 1; - } - - return 0; -} diff --git a/camel/providers/imapp/camel-imapp-utils.h b/camel/providers/imapp/camel-imapp-utils.h deleted file mode 100644 index e0974bdc96..0000000000 --- a/camel/providers/imapp/camel-imapp-utils.h +++ /dev/null @@ -1,145 +0,0 @@ - -#ifndef _CAMEL_IMAPP_UTILS_H -#define _CAMEL_IMAPP_UTILS_H - -#include - -/* FIXME: the enum should be split up into logical groups, so that testing - can be done more accurately? */ - -/* list of strings we know about that can be *quickly* tokenised */ -enum _imap_id { - IMAP_UNKNOWN = 0, - IMAP_ALERT, - IMAP_BYE, - IMAP_BAD, - IMAP_NO, - IMAP_OK, - IMAP_PREAUTH, - IMAP_NEWNAME, - IMAP_PARSE, - IMAP_PERMANENTFLAGS, - IMAP_READ_ONLY, - IMAP_READ_WRITE, - IMAP_TRYCREATE, - IMAP_UIDVALIDITY, - IMAP_UNSEEN, - IMAP_ENVELOPE, - IMAP_FLAGS, - IMAP_INTERNALDATE, - IMAP_RFC822_HEADER, - IMAP_RFC822_TEXT, - IMAP_RFC822_SIZE, - IMAP_BODYSTRUCTURE, - IMAP_BODY, - IMAP_UID, -}; - -/* str MUST be in upper case, tokenised using gperf function */ -enum _imap_id imap_tokenise(register const char *str, register unsigned int len); - -/* this flag should be part of imapfoldersummary */ -enum { - CAMEL_IMAPP_MESSAGE_RECENT = (1<<8), -}; - -/* ********************************************************************** */ -void imap_parse_flags(CamelIMAPPStream *stream, guint32 *flagsp) /* IO,PARSE */; -void imap_write_flags(CamelStream *stream, guint32 flags) /* IO */; - -/* ********************************************************************** */ -void imap_parse_param_list(CamelIMAPPStream *is, struct _camel_header_param **plist) /* IO,PARSE */; -struct _CamelContentDisposition *imap_parse_ext_optional(CamelIMAPPStream *is) /* IO,PARSE */; -struct _CamelMessageContentInfo *imap_parse_body_fields(CamelIMAPPStream *is) /* IO,PARSE */; -struct _camel_header_address *imap_parse_address_list(CamelIMAPPStream *is) /* IO,PARSE */; -struct _CamelMessageInfo *imap_parse_envelope(CamelIMAPPStream *is) /* IO, PARSE */; -struct _CamelMessageContentInfo *imap_parse_body(CamelIMAPPStream *is) /* IO,PARSE */; -char *imap_parse_section(CamelIMAPPStream *is) /* IO,PARSE */; -void imap_free_body(struct _CamelMessageContentInfo *cinfo); - -/* ********************************************************************** */ -/* all the possible stuff we might get from a fetch request */ -/* this assumes the caller/server doesn't send any one of these types twice */ -struct _fetch_info { - guint32 got; /* what we got, see below */ - CamelStream *body; /* BODY[.*](<.*>)? */ - CamelStream *text; /* RFC822.TEXT */ - CamelStream *header; /* RFC822.HEADER */ - CamelMessageInfo *minfo; /* ENVELOPE */ - CamelMessageContentInfo *cinfo; /* BODYSTRUCTURE,BODY */ - guint32 size; /* RFC822.SIZE */ - guint32 offset; /* start offset of a BODY[] request */ - guint32 flags; /* FLAGS */ - char *date; /* INTERNALDATE */ - char *section; /* section for a BODY[section] request */ - char *uid; /* UID */ -}; - -#define FETCH_BODY (1<<0) -#define FETCH_TEXT (1<<1) -#define FETCH_HEADER (1<<2) -#define FETCH_MINFO (1<<3) -#define FETCH_CINFO (1<<4) -#define FETCH_SIZE (1<<5) -#define FETCH_OFFSET (1<<6) -#define FETCH_FLAGS (1<<7) -#define FETCH_DATE (1<<8) -#define FETCH_SECTION (1<<9) -#define FETCH_UID (1<<10) - -struct _fetch_info *imap_parse_fetch(CamelIMAPPStream *is); -void imap_free_fetch(struct _fetch_info *finfo); -void imap_dump_fetch(struct _fetch_info *finfo); - -/* ********************************************************************** */ - -struct _status_info { - enum _imap_id result; /* ok/no/bad/preauth only */ - enum _imap_id condition; /* read-only/read-write/alert/parse/trycreate/newname/permanentflags/uidvalidity/unseen */ - - union { - struct { - char *oldname; - char *newname; - } newname; - guint32 permanentflags; - guint32 uidvalidity; - guint32 unseen; - } u; - - char *text; -}; - -struct _status_info *imap_parse_status(CamelIMAPPStream *is); -void imap_free_status(struct _status_info *sinfo); - -/* ********************************************************************** */ - -/* should this just return a FolderInfo? - should this just return the name & flags & separator by reference? */ -struct _list_info { - guint32 flags:24; - char separator; - char *name; -}; - -struct _list_info *imap_parse_list(CamelIMAPPStream *is); -char *imapp_list_get_path(struct _list_info *li); -void imap_free_list(struct _list_info *linfo); - -/* ********************************************************************** */ - -struct _uidset_state { - struct _CamelIMAPPEngine *ie; - int len; - guint32 start; - guint32 last; -}; - -struct _CamelIMAPPEngine; -struct _CamelIMAPPCommand; -void imapp_uidset_init(struct _uidset_state *ss, struct _CamelIMAPPEngine *ie); -int imapp_uidset_done(struct _uidset_state *ss, struct _CamelIMAPPCommand *ic); -int imapp_uidset_add(struct _uidset_state *ss, struct _CamelIMAPPCommand *ic, const char *uid); - -#endif diff --git a/camel/providers/imapp/libcamelimapp.urls b/camel/providers/imapp/libcamelimapp.urls deleted file mode 100644 index aad1347834..0000000000 --- a/camel/providers/imapp/libcamelimapp.urls +++ /dev/null @@ -1 +0,0 @@ -imapp diff --git a/camel/providers/local/.cvsignore b/camel/providers/local/.cvsignore deleted file mode 100644 index 3fa8afaa38..0000000000 --- a/camel/providers/local/.cvsignore +++ /dev/null @@ -1,11 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/local/Makefile.am b/camel/providers/local/Makefile.am deleted file mode 100644 index ad07472e85..0000000000 --- a/camel/providers/local/Makefile.am +++ /dev/null @@ -1,61 +0,0 @@ -## Process this file with automake to produce Makefile.in - -libcamellocalincludedir = $(privincludedir)/camel - -camel_provider_LTLIBRARIES = libcamellocal.la -camel_provider_DATA = libcamellocal.urls - -INCLUDES = -I.. \ - -I$(srcdir)/.. \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir) \ - $(CAMEL_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(GTK_INCLUDEDIR) \ - -DG_LOG_DOMAIN=\"camel-local-provider\" - -libcamellocal_la_SOURCES = \ - camel-local-folder.c \ - camel-local-store.c \ - camel-local-summary.c \ - camel-local-provider.c \ - camel-mh-folder.c \ - camel-mh-store.c \ - camel-mh-summary.c \ - camel-mbox-folder.c \ - camel-mbox-store.c \ - camel-mbox-summary.c \ - camel-maildir-folder.c \ - camel-maildir-store.c \ - camel-maildir-summary.c \ - camel-spool-folder.c \ - camel-spool-store.c \ - camel-spool-summary.c - -libcamellocalinclude_HEADERS = \ - camel-local-folder.h \ - camel-local-store.h \ - camel-local-summary.h \ - camel-mh-folder.h \ - camel-mh-store.h \ - camel-mh-summary.h \ - camel-mbox-folder.h \ - camel-mbox-store.h \ - camel-mbox-summary.h \ - camel-maildir-folder.h \ - camel-maildir-store.h \ - camel-maildir-summary.h \ - camel-spool-folder.h \ - camel-spool-store.h \ - camel-spool-summary.h - -noinst_HEADERS = \ - camel-local-private.h - -libcamellocal_la_LDFLAGS = -avoid-version -module - -libcamellocal_la_LIBADD = $(top_builddir)/e-util/libeutil.la - -EXTRA_DIST = libcamellocal.urls diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c deleted file mode 100644 index 5bf2142f35..0000000000 --- a/camel/providers/local/camel-local-folder.c +++ /dev/null @@ -1,646 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Michael Zucchi - * - * Copyright 1999-2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef _POSIX_PATH_MAX -#include -#endif - -#include "camel-local-folder.h" -#include "camel-local-store.h" -#include "camel-stream-fs.h" -#include "camel-local-summary.h" -#include "camel-data-wrapper.h" -#include "camel-mime-message.h" -#include "camel-stream-filter.h" -#include "camel-mime-filter-from.h" -#include "camel-exception.h" - -#include "camel-local-private.h" - -#include "camel-text-index.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#ifndef PATH_MAX -#define PATH_MAX _POSIX_PATH_MAX -#endif - -static CamelFolderClass *parent_class; -static GSList *local_folder_properties; - -/* Returns the class for a CamelLocalFolder */ -#define CLOCALF_CLASS(so) CAMEL_LOCAL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CLOCALS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static int local_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args); -static int local_setv(CamelObject *object, CamelException *ex, CamelArgV *args); - -static int local_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex); -static void local_unlock(CamelLocalFolder *lf); - -static char *local_get_full_path (const char *toplevel_dir, const char *full_name); -static char *local_get_meta_path (const char *toplevel_dir, const char *full_name, const char *ext); - -static void local_refresh_info(CamelFolder *folder, CamelException *ex); - -static void local_sync(CamelFolder *folder, gboolean expunge, CamelException *ex); -static void local_expunge(CamelFolder *folder, CamelException *ex); - -static GPtrArray *local_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex); -static GPtrArray *local_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex); -static void local_search_free(CamelFolder *folder, GPtrArray * result); - -static void local_delete(CamelFolder *folder); -static void local_rename(CamelFolder *folder, const char *newname); - -static void local_finalize(CamelObject * object); - -static void -camel_local_folder_class_init(CamelLocalFolderClass * camel_local_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_local_folder_class); - CamelObjectClass *oklass = (CamelObjectClass *)camel_local_folder_class; - - /* virtual method definition */ - - /* virtual method overload */ - oklass->getv = local_getv; - oklass->setv = local_setv; - - camel_folder_class->refresh_info = local_refresh_info; - camel_folder_class->sync = local_sync; - camel_folder_class->expunge = local_expunge; - - camel_folder_class->search_by_expression = local_search_by_expression; - camel_folder_class->search_by_uids = local_search_by_uids; - camel_folder_class->search_free = local_search_free; - - camel_folder_class->delete = local_delete; - camel_folder_class->rename = local_rename; - - camel_local_folder_class->get_full_path = local_get_full_path; - camel_local_folder_class->get_meta_path = local_get_meta_path; - - camel_local_folder_class->lock = local_lock; - camel_local_folder_class->unlock = local_unlock; -} - -static void -local_init(gpointer object, gpointer klass) -{ - CamelFolder *folder = object; - CamelLocalFolder *local_folder = object; - - folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | - CAMEL_FOLDER_HAS_SEARCH_CAPABILITY); - - folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | - CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_DRAFT | - CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN | - CAMEL_MESSAGE_ANSWERED_ALL | CAMEL_MESSAGE_USER; - - folder->summary = NULL; - local_folder->search = NULL; - - local_folder->priv = g_malloc0(sizeof(*local_folder->priv)); - local_folder->priv->search_lock = g_mutex_new(); -} - -static void -local_finalize(CamelObject * object) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(object); - CamelFolder *folder = (CamelFolder *)object; - - if (folder->summary) { - camel_local_summary_sync((CamelLocalSummary *)folder->summary, FALSE, local_folder->changes, NULL); - camel_object_unref((CamelObject *)folder->summary); - folder->summary = NULL; - } - - if (local_folder->search) { - camel_object_unref((CamelObject *)local_folder->search); - } - - if (local_folder->index) - camel_object_unref((CamelObject *)local_folder->index); - - while (local_folder->locked> 0) - camel_local_folder_unlock(local_folder); - - g_free(local_folder->base_path); - g_free(local_folder->folder_path); - g_free(local_folder->summary_path); - g_free(local_folder->index_path); - - camel_folder_change_info_free(local_folder->changes); - - g_mutex_free(local_folder->priv->search_lock); - - g_free(local_folder->priv); -} - -static CamelProperty local_property_list[] = { - { CAMEL_LOCAL_FOLDER_INDEX_BODY, "index_body", N_("Index message body data") }, -}; - -CamelType -camel_local_folder_get_type(void) -{ - static CamelType camel_local_folder_type = CAMEL_INVALID_TYPE; - - if (camel_local_folder_type == CAMEL_INVALID_TYPE) { - int i; - - parent_class = (CamelFolderClass *)camel_folder_get_type(); - camel_local_folder_type = camel_type_register(camel_folder_get_type(), "CamelLocalFolder", - sizeof(CamelLocalFolder), - sizeof(CamelLocalFolderClass), - (CamelObjectClassInitFunc) camel_local_folder_class_init, - NULL, - (CamelObjectInitFunc) local_init, - (CamelObjectFinalizeFunc) local_finalize); - - for (i=0;iparent_store)); - /* strip the trailing '/' which is always present */ - len = strlen (root_dir_path); - tmp = g_alloca (len + 1); - strcpy (tmp, root_dir_path); - if (len>1 && tmp[len-1] == '/') - tmp[len-1] = 0; - - lf->base_path = g_strdup(root_dir_path); - - /* if the base store points to a file, then use that */ - if (stat(tmp, &st) != -1 && S_ISREG(st.st_mode)) { - lf->folder_path = g_strdup(tmp); - /* not really sure to do with these for now? */ - lf->summary_path = g_strdup_printf("%s.ev-summary", tmp); - lf->index_path = g_strdup_printf("%s.ibex", tmp); - statepath = g_strdup_printf ("%s.cmeta", tmp); - } else { - lf->folder_path = CLOCALF_CLASS (lf)->get_full_path (root_dir_path, full_name); - lf->summary_path = CLOCALF_CLASS (lf)->get_meta_path (root_dir_path, full_name, ".ev-summary"); - lf->index_path = CLOCALF_CLASS (lf)->get_meta_path (root_dir_path, full_name, ".ibex"); - statepath = CLOCALF_CLASS (lf)->get_meta_path (root_dir_path, full_name, ".cmeta"); - } - camel_object_set(lf, NULL, CAMEL_OBJECT_STATE_FILE, statepath, NULL); - g_free (statepath); - - lf->flags = flags; - - if (camel_object_state_read(lf) == -1) { - /* FIXME: load defaults? */ - } - - /* follow any symlinks to the mailbox */ - if (lstat (lf->folder_path, &st) != -1 && S_ISLNK (st.st_mode) && - realpath (lf->folder_path, folder_path) != NULL) { - g_free (lf->folder_path); - lf->folder_path = g_strdup (folder_path); - } - - lf->changes = camel_folder_change_info_new(); - - /* TODO: Remove the following line, it is a temporary workaround to remove - the old-format 'ibex' files that might be lying around */ - unlink(lf->index_path); - - /* FIXME: Need to run indexing off of the setv method */ -#if 1 - forceindex = FALSE; -#else - /* if we have no/invalid index file, force it */ - forceindex = camel_text_index_check(lf->index_path) == -1; - if (flags & CAMEL_STORE_FOLDER_BODY_INDEX) { - int flag = O_RDWR|O_CREAT; - if (forceindex) - flag |= O_TRUNC; - lf->index = (CamelIndex *)camel_text_index_new(lf->index_path, flag); - if (lf->index == NULL) { - /* yes, this isn't fatal at all */ - g_warning("Could not open/create index file: %s: indexing not performed", strerror (errno)); - forceindex = FALSE; - /* record that we dont have an index afterall */ - flags &= ~CAMEL_STORE_FOLDER_BODY_INDEX; - } - } else { - /* if we do have an index file, remove it (?) */ - if (forceindex == FALSE) - camel_text_index_remove(lf->index_path); - forceindex = FALSE; - } - lf->flags = flags; -#endif - - folder->summary = (CamelFolderSummary *)CLOCALF_CLASS(lf)->create_summary(lf->summary_path, lf->folder_path, lf->index); - if (camel_local_summary_load((CamelLocalSummary *)folder->summary, forceindex, ex) == -1) { - camel_exception_clear(ex); - } - - /*if (camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex) == -1) {*/ - /* we sync here so that any hard work setting up the folder isn't lost */ - if (camel_local_summary_sync((CamelLocalSummary *)folder->summary, FALSE, lf->changes, ex) == -1) { - camel_object_unref (CAMEL_OBJECT (folder)); - return NULL; - } - - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = g_strdup (full_name); - fi->name = g_strdup (name); - fi->url = g_strdup_printf("%s:%s#%s", ((CamelService *)parent_store)->url->protocol, ((CamelService *)parent_store)->url->path, full_name); - fi->unread_message_count = camel_folder_get_unread_message_count(folder); - camel_folder_info_build_path(fi, '/'); - - camel_object_trigger_event(CAMEL_OBJECT (parent_store), "folder_created", fi); - camel_folder_info_free(fi); - - return lf; -} - -/* lock the folder, may be called repeatedly (with matching unlock calls), - with type the same or less than the first call */ -int camel_local_folder_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex) -{ - if (lf->locked > 0) { - /* lets be anal here - its important the code knows what its doing */ - g_assert(lf->locktype == type || lf->locktype == CAMEL_LOCK_WRITE); - } else { - if (CLOCALF_CLASS(lf)->lock(lf, type, ex) == -1) - return -1; - lf->locktype = type; - } - - lf->locked++; - - return 0; -} - -/* unlock folder */ -int camel_local_folder_unlock(CamelLocalFolder *lf) -{ - g_assert(lf->locked>0); - lf->locked--; - if (lf->locked == 0) - CLOCALF_CLASS(lf)->unlock(lf); - - return 0; -} - -static int -local_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args) -{ - CamelFolder *folder = (CamelFolder *)object; - int i; - guint32 tag; - - for (i=0;iargc;i++) { - CamelArgGet *arg = &args->argv[i]; - - tag = arg->tag; - - switch (tag & CAMEL_ARG_TAG) { - case CAMEL_OBJECT_ARG_DESCRIPTION: - if (folder->description == NULL) { - char *tmp, *path; - - /* check some common prefixes to shorten the name */ - tmp = ((CamelService *)folder->parent_store)->url->path; - if (tmp == NULL) - goto skip; - - path = g_alloca (strlen (tmp) + strlen (folder->full_name) + 1); - sprintf (path, "%s/%s", tmp, folder->full_name); - - if ((tmp = getenv("HOME")) && strncmp(tmp, path, strlen(tmp)) == 0) - /* $HOME relative path + protocol string */ - folder->description = g_strdup_printf(_("~%s (%s)"), path+strlen(tmp), - ((CamelService *)folder->parent_store)->url->protocol); - else if ((tmp = "/var/spool/mail") && strncmp(tmp, path, strlen(tmp)) == 0) - /* /var/spool/mail relative path + protocol */ - folder->description = g_strdup_printf(_("mailbox:%s (%s)"), path+strlen(tmp), - ((CamelService *)folder->parent_store)->url->protocol); - else if ((tmp = "/var/mail") && strncmp(tmp, path, strlen(tmp)) == 0) - folder->description = g_strdup_printf(_("mailbox:%s (%s)"), path+strlen(tmp), - ((CamelService *)folder->parent_store)->url->protocol); - else - /* a full path + protocol */ - folder->description = g_strdup_printf(_("%s (%s)"), path, - ((CamelService *)folder->parent_store)->url->protocol); - } - *arg->ca_str = folder->description; - break; - - case CAMEL_OBJECT_ARG_PERSISTENT_PROPERTIES: - case CAMEL_FOLDER_ARG_PROPERTIES: { - CamelArgGetV props; - - props.argc = 1; - props.argv[0] = *arg; - ((CamelObjectClass *)parent_class)->getv(object, ex, &props); - *arg->ca_ptr = g_slist_concat(*arg->ca_ptr, g_slist_copy(local_folder_properties)); - - break; } - - case CAMEL_LOCAL_FOLDER_ARG_INDEX_BODY: - printf("getv:'%s' flags %08x\n", ((CamelFolder *)object)->full_name, ((CamelLocalFolder *)object)->flags); - - /* FIXME: remove this from sotre flags */ - *arg->ca_int = (((CamelLocalFolder *)folder)->flags & CAMEL_STORE_FOLDER_BODY_INDEX) != 0; - break; - - default: skip: - continue; - } - - arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE; - } - - return ((CamelObjectClass *)parent_class)->getv(object, ex, args); -} - -static int -local_setv(CamelObject *object, CamelException *ex, CamelArgV *args) -{ - int i; - guint32 tag; - - for (i=0;iargc;i++) { - CamelArg *arg = &args->argv[i]; - - tag = arg->tag; - - switch (tag & CAMEL_ARG_TAG) { - case CAMEL_LOCAL_FOLDER_ARG_INDEX_BODY: - /* FIXME: implement */ - /* TODO: When turning on (off?) the index, we want to launch a task for it, - and make sure we dont have multiple tasks doing the same job */ - if (arg->ca_int) - ((CamelLocalFolder *)object)->flags |= CAMEL_STORE_FOLDER_BODY_INDEX; - else - ((CamelLocalFolder *)object)->flags &= ~CAMEL_STORE_FOLDER_BODY_INDEX; - break; - default: - continue; - } - - arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE; - } - - return ((CamelObjectClass *)parent_class)->setv(object, ex, args); -} - -static char * -local_get_full_path (const char *toplevel_dir, const char *full_name) -{ - return g_strdup_printf ("%s/%s", toplevel_dir, full_name); -} - -static char * -local_get_meta_path (const char *toplevel_dir, const char *full_name, const char *ext) -{ - return g_strdup_printf ("%s/%s%s", toplevel_dir, full_name, ext); -} - -static int -local_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex) -{ - return 0; -} - -static void -local_unlock(CamelLocalFolder *lf) -{ - /* nothing */ -} - -/* for auto-check to work */ -static void -local_refresh_info(CamelFolder *folder, CamelException *ex) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - - if (camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex) == -1) - return; - - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } -} - -static void -local_sync(CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - CamelLocalFolder *lf = CAMEL_LOCAL_FOLDER(folder); - - d(printf("local sync, expunge=%s\n", expunge?"true":"false")); - - if (camel_local_folder_lock(lf, CAMEL_LOCK_WRITE, ex) == -1) - return; - - camel_object_state_write(lf); - - /* if sync fails, we'll pass it up on exit through ex */ - camel_local_summary_sync((CamelLocalSummary *)folder->summary, expunge, lf->changes, ex); - camel_local_folder_unlock(lf); - - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event(CAMEL_OBJECT(folder), "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } -} - -static void -local_expunge(CamelFolder *folder, CamelException *ex) -{ - d(printf("expunge\n")); - - /* Just do a sync with expunge, serves the same purpose */ - /* call the callback directly, to avoid locking problems */ - CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, TRUE, ex); -} - -static void -local_delete(CamelFolder *folder) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - - if (lf->index) - camel_index_delete(lf->index); - - parent_class->delete(folder); -} - -static void -local_rename(CamelFolder *folder, const char *newname) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - - d(printf("renaming local folder paths to '%s'\n", newname)); - - /* Sync? */ - - g_free(lf->folder_path); - g_free(lf->summary_path); - g_free(lf->index_path); - lf->folder_path = g_strdup_printf("%s/%s", lf->base_path, newname); - lf->summary_path = g_strdup_printf("%s/%s.ev-summary", lf->base_path, newname); - lf->index_path = g_strdup_printf("%s/%s.ibex", lf->base_path, newname); - - /* FIXME: Poke some internals, sigh */ - camel_folder_summary_set_filename(folder->summary, lf->summary_path); - g_free(((CamelLocalSummary *)folder->summary)->folder_path); - ((CamelLocalSummary *)folder->summary)->folder_path = g_strdup(lf->folder_path); - - parent_class->rename(folder, newname); -} - -static GPtrArray * -local_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - GPtrArray *summary, *matches; - - /* NOTE: could get away without the search lock by creating a new - search object each time */ - - CAMEL_LOCAL_FOLDER_LOCK(folder, search_lock); - - if (local_folder->search == NULL) - local_folder->search = camel_folder_search_new(); - - camel_folder_search_set_folder(local_folder->search, folder); - camel_folder_search_set_body_index(local_folder->search, local_folder->index); - summary = camel_folder_get_summary(folder); - camel_folder_search_set_summary(local_folder->search, summary); - - matches = camel_folder_search_execute_expression(local_folder->search, expression, ex); - - CAMEL_LOCAL_FOLDER_UNLOCK(folder, search_lock); - - camel_folder_free_summary(folder, summary); - - return matches; -} - -static GPtrArray * -local_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - GPtrArray *summary, *matches; - int i; - - /* NOTE: could get away without the search lock by creating a new - search object each time */ - - summary = g_ptr_array_new(); - for (i=0;ilen;i++) { - CamelMessageInfo *info; - - info = camel_folder_get_message_info(folder, uids->pdata[i]); - if (info) - g_ptr_array_add(summary, info); - } - - if (summary->len == 0) - return summary; - - CAMEL_LOCAL_FOLDER_LOCK(folder, search_lock); - - if (local_folder->search == NULL) - local_folder->search = camel_folder_search_new(); - - camel_folder_search_set_folder(local_folder->search, folder); - camel_folder_search_set_body_index(local_folder->search, local_folder->index); - camel_folder_search_set_summary(local_folder->search, summary); - - matches = camel_folder_search_execute_expression(local_folder->search, expression, ex); - - CAMEL_LOCAL_FOLDER_UNLOCK(folder, search_lock); - - for (i=0;ilen;i++) - camel_folder_free_message_info(folder, summary->pdata[i]); - g_ptr_array_free(summary, TRUE); - - return matches; -} - -static void -local_search_free(CamelFolder *folder, GPtrArray * result) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - - /* we need to lock this free because of the way search_free_result works */ - /* FIXME: put the lock inside search_free_result */ - CAMEL_LOCAL_FOLDER_LOCK(folder, search_lock); - - camel_folder_search_free_result(local_folder->search, result); - - CAMEL_LOCAL_FOLDER_UNLOCK(folder, search_lock); -} diff --git a/camel/providers/local/camel-local-folder.h b/camel/providers/local/camel-local-folder.h deleted file mode 100644 index 73059f03b3..0000000000 --- a/camel/providers/local/camel-local-folder.h +++ /dev/null @@ -1,109 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Author: Michael Zucchi - * - * Copyright (C) 1999 Ximian (www.ximian.com/). - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_LOCAL_FOLDER_H -#define CAMEL_LOCAL_FOLDER_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include -#include -#include "camel-local-summary.h" -#include "camel-lock.h" - -/* #include "camel-store.h" */ - -#define CAMEL_LOCAL_FOLDER_TYPE (camel_local_folder_get_type ()) -#define CAMEL_LOCAL_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_LOCAL_FOLDER_TYPE, CamelLocalFolder)) -#define CAMEL_LOCAL_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_LOCAL_FOLDER_TYPE, CamelLocalFolderClass)) -#define CAMEL_IS_LOCAL_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_LOCAL_FOLDER_TYPE)) - -enum { - CAMEL_LOCAL_FOLDER_ARG_INDEX_BODY = CAMEL_FOLDER_ARG_LAST, - - CAMEL_LOCAL_FOLDER_ARG_LAST = CAMEL_FOLDER_ARG_LAST + 0x100 -}; - -enum { - CAMEL_LOCAL_FOLDER_INDEX_BODY = CAMEL_LOCAL_FOLDER_ARG_INDEX_BODY | CAMEL_ARG_BOO, -}; - -typedef struct { - CamelFolder parent_object; - struct _CamelLocalFolderPrivate *priv; - - guint32 flags; /* open mode flags */ - - int locked; /* lock counter */ - CamelLockType locktype; /* what type of lock we have */ - - char *base_path; /* base path of the local folder */ - char *folder_path; /* the path to the folder itself */ - char *summary_path; /* where the summary lives */ - char *index_path; /* where the index file lives */ - - CamelIndex *index; /* index for this folder */ - CamelFolderSearch *search; /* used to run searches, we just use the real thing (tm) */ - CamelFolderChangeInfo *changes; /* used to store changes to the folder during processing */ -} CamelLocalFolder; - -typedef struct { - CamelFolderClass parent_class; - - /* Virtual methods */ - - /* path construction, only used at init */ - char * (* get_full_path) (const char *toplevel_dir, const char *full_name); - char * (* get_meta_path) (const char *toplevel_dir, const char *full_name, const char *ext); - - /* summary factory, only used at init */ - CamelLocalSummary *(*create_summary)(const char *path, const char *folder, CamelIndex *index); - - /* Lock the folder for my operations */ - int (*lock)(CamelLocalFolder *, CamelLockType type, CamelException *ex); - - /* Unlock the folder for my operations */ - void (*unlock)(CamelLocalFolder *); -} CamelLocalFolderClass; - - -/* public methods */ -/* flags are taken from CAMEL_STORE_FOLDER_* flags */ -CamelLocalFolder *camel_local_folder_construct(CamelLocalFolder *lf, CamelStore *parent_store, - const char *full_name, guint32 flags, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_local_folder_get_type(void); - -/* Lock the folder for internal use. May be called repeatedly */ -/* UNIMPLEMENTED */ -int camel_local_folder_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex); -int camel_local_folder_unlock(CamelLocalFolder *lf); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_LOCAL_FOLDER_H */ diff --git a/camel/providers/local/camel-local-private.h b/camel/providers/local/camel-local-private.h deleted file mode 100644 index e8e5061fae..0000000000 --- a/camel/providers/local/camel-local-private.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Michael Zucchi - * - * Copyright 1999-2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef CAMEL_LOCAL_PRIVATE_H -#define CAMEL_LOCAL_PRIVATE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* need a way to configure and save this data, if this header is to - be installed. For now, dont install it */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -struct _CamelLocalFolderPrivate { - GMutex *search_lock; /* for locking the search object */ -}; - -#define CAMEL_LOCAL_FOLDER_LOCK(f, l) (g_mutex_lock(((CamelLocalFolder *)f)->priv->l)) -#define CAMEL_LOCAL_FOLDER_UNLOCK(f, l) (g_mutex_unlock(((CamelLocalFolder *)f)->priv->l)) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_LOCAL_PRIVATE_H */ - diff --git a/camel/providers/local/camel-local-provider.c b/camel/providers/local/camel-local-provider.c deleted file mode 100644 index a52dfbde5f..0000000000 --- a/camel/providers/local/camel-local-provider.c +++ /dev/null @@ -1,222 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi - * - * Copyright (C) 2000 Ximian (www.ximian.com). - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "camel-provider.h" -#include "camel-session.h" -#include "camel-url.h" - -#include "camel-mh-store.h" -#include "camel-mbox-store.h" -#include "camel-maildir-store.h" -#include "camel-spool-store.h" - -#define d(x) - -static CamelProviderConfEntry mh_conf_entries[] = { - CAMEL_PROVIDER_CONF_DEFAULT_PATH, - { CAMEL_PROVIDER_CONF_CHECKBOX, "dotfolders", NULL, - N_("Use the `.folders' folder summary file (exmh)"), "0" }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider mh_provider = { - "mh", - N_("MH-format mail directories"), - N_("For storing local mail in MH-like mail directories."), - "mail", - CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_IS_LOCAL, - CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE | CAMEL_URL_FRAGMENT_IS_PATH, - mh_conf_entries, - /* ... */ -}; - -static CamelProviderConfEntry mbox_conf_entries[] = { - CAMEL_PROVIDER_CONF_DEFAULT_PATH, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider mbox_provider = { - "mbox", - N_("Local delivery"), - N_("For retrieving (moving) local mail from standard mbox formated spools into folders managed by Evolution."), - "mail", - CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_IS_LOCAL, - CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE | CAMEL_URL_FRAGMENT_IS_PATH, - mbox_conf_entries, - /* ... */ -}; - -static CamelProviderConfEntry maildir_conf_entries[] = { - CAMEL_PROVIDER_CONF_DEFAULT_PATH, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter", NULL, - N_("Apply filters to new messages in INBOX"), "0" }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider maildir_provider = { - "maildir", - N_("Maildir-format mail directories"), - N_("For storing local mail in maildir directories."), - "mail", - CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_IS_LOCAL, - CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE | CAMEL_URL_FRAGMENT_IS_PATH, - maildir_conf_entries, - /* ... */ -}; - -static CamelProviderConfEntry spool_conf_entries[] = { - CAMEL_PROVIDER_CONF_DEFAULT_PATH, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter", NULL, N_("Apply filters to new messages in INBOX"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "xstatus", NULL, N_("Store status headers in Elm/Pine/Mutt format"), "0" }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider spool_provider = { - "spool", - N_("Standard Unix mbox spool or directory"), - N_("For reading and storing local mail in external standard mbox spool files.\nMay also be used to read a tree of Elm, Pine, or Mutt style folders."), - "mail", - CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE, - CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE | CAMEL_URL_FRAGMENT_IS_PATH, - spool_conf_entries, - /* ... */ -}; - -/* build a canonical 'path' */ -static char * -make_can_path(char *p, char *o) -{ - char c, last, *start = o; - - d(printf("canonical '%s' = ", p)); - - last = 0; - while ((c = *p++)) { - if (c!='/' - || (c=='/' && last != '/')) - *o++ = c; - last = c; - } - if (o>start && o[-1] == '/') - o[-1] = 0; - else - *o = 0; - - d(printf("'%s'\n", start)); - - return start; -} - -/* 'helper' function for it */ -#define get_can_path(p) ((p == NULL) ? NULL : (make_can_path ((p), g_alloca (strlen (p) + 1)))) - -static guint -local_url_hash (const void *v) -{ - const CamelURL *u = v; - guint hash = 0; - -#define ADD_HASH(s) if (s) hash ^= g_str_hash (s); - - ADD_HASH (u->protocol); - ADD_HASH (u->user); - ADD_HASH (u->authmech); - ADD_HASH (u->host); - if (u->path) - hash ^= g_str_hash(get_can_path(u->path)); - ADD_HASH (u->path); - ADD_HASH (u->query); - hash ^= u->port; - - return hash; -} - -static int -check_equal (char *s1, char *s2) -{ - if (s1 == NULL) { - if (s2 == NULL) - return TRUE; - else - return FALSE; - } - - if (s2 == NULL) - return FALSE; - - return strcmp (s1, s2) == 0; -} - -static int -local_url_equal(const void *v, const void *v2) -{ - const CamelURL *u1 = v, *u2 = v2; - char *p1, *p2; - - p1 = get_can_path(u1->path); - p2 = get_can_path(u2->path); - return check_equal(p1, p2) - && check_equal(u1->protocol, u2->protocol) - && check_equal(u1->user, u2->user) - && check_equal(u1->authmech, u2->authmech) - && check_equal(u1->host, u2->host) - && check_equal(u1->query, u2->query) - && u1->port == u2->port; -} - -void camel_provider_module_init(CamelSession * session) -{ - char *path; - - mh_conf_entries[0].value = ""; /* default path */ - mh_provider.object_types[CAMEL_PROVIDER_STORE] = camel_mh_store_get_type (); - mh_provider.url_hash = local_url_hash; - mh_provider.url_equal = local_url_equal; - camel_session_register_provider(session, &mh_provider); - - if (!(path = getenv ("MAIL"))) - path = g_strdup_printf (SYSTEM_MAIL_DIR "/%s", g_get_user_name ()); - mbox_conf_entries[0].value = path; /* default path */ - mbox_provider.object_types[CAMEL_PROVIDER_STORE] = camel_mbox_store_get_type (); - mbox_provider.url_hash = local_url_hash; - mbox_provider.url_equal = local_url_equal; - camel_session_register_provider(session, &mbox_provider); - - spool_conf_entries[0].value = path; /* default path - same as mbox */ - spool_provider.object_types[CAMEL_PROVIDER_STORE] = camel_spool_store_get_type (); - spool_provider.url_hash = local_url_hash; - spool_provider.url_equal = local_url_equal; - camel_session_register_provider(session, &spool_provider); - - path = getenv ("MAILDIR"); - maildir_conf_entries[0].value = path ? path : ""; /* default path */ - maildir_provider.object_types[CAMEL_PROVIDER_STORE] = camel_maildir_store_get_type (); - maildir_provider.url_hash = local_url_hash; - maildir_provider.url_equal = local_url_equal; - camel_session_register_provider(session, &maildir_provider); -} diff --git a/camel/providers/local/camel-local-store.c b/camel/providers/local/camel-local-store.c deleted file mode 100644 index a0eaf9d68f..0000000000 --- a/camel/providers/local/camel-local-store.c +++ /dev/null @@ -1,442 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi - * - * Copyright (C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include - -#include "camel-private.h" - -#include "camel-local-store.h" -#include "camel-exception.h" -#include "camel-url.h" - -#include "camel-local-folder.h" -#include - -#define d(x) - -/* Returns the class for a CamelLocalStore */ -#define CLOCALS_CLASS(so) CAMEL_LOCAL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static void construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex); -static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex); -static char *get_name(CamelService *service, gboolean brief); -static CamelFolder *get_inbox (CamelStore *store, CamelException *ex); -static CamelFolderInfo *get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); -static void delete_folder(CamelStore *store, const char *folder_name, CamelException *ex); -static void rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex); -static CamelFolderInfo *create_folder(CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex); - -static CamelStoreClass *parent_class = NULL; - -static void -camel_local_store_class_init (CamelLocalStoreClass *camel_local_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_local_store_class); - CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS (camel_local_store_class); - - parent_class = CAMEL_STORE_CLASS (camel_type_get_global_classfuncs (camel_store_get_type ())); - - /* virtual method overload */ - camel_service_class->construct = construct; - camel_service_class->get_name = get_name; - camel_store_class->get_folder = get_folder; - camel_store_class->get_inbox = get_inbox; - camel_store_class->get_folder_info = get_folder_info; - camel_store_class->free_folder_info = camel_store_free_folder_info_full; - - camel_store_class->create_folder = create_folder; - camel_store_class->delete_folder = delete_folder; - camel_store_class->rename_folder = rename_folder; -} - -static void -camel_local_store_finalize (CamelLocalStore *local_store) -{ - if (local_store->toplevel_dir) - g_free (local_store->toplevel_dir); -} - -CamelType -camel_local_store_get_type (void) -{ - static CamelType camel_local_store_type = CAMEL_INVALID_TYPE; - - if (camel_local_store_type == CAMEL_INVALID_TYPE) { - camel_local_store_type = camel_type_register (CAMEL_STORE_TYPE, "CamelLocalStore", - sizeof (CamelLocalStore), - sizeof (CamelLocalStoreClass), - (CamelObjectClassInitFunc) camel_local_store_class_init, - NULL, - NULL, - (CamelObjectFinalizeFunc) camel_local_store_finalize); - } - - return camel_local_store_type; -} - -static void -construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex) -{ - CamelLocalStore *local_store = CAMEL_LOCAL_STORE (service); - int len; - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set (ex)) - return; - - len = strlen (service->url->path); - if (service->url->path[len - 1] != '/') - local_store->toplevel_dir = g_strdup_printf ("%s/", service->url->path); - else - local_store->toplevel_dir = g_strdup (service->url->path); -} - -const char * -camel_local_store_get_toplevel_dir (CamelLocalStore *store) -{ - return store->toplevel_dir; -} - -static CamelFolder * -get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex) -{ - struct stat st; - char *path = ((CamelLocalStore *)store)->toplevel_dir; - char *sub, *slash; - - if (path[0] != '/') { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store root %s is not an absolute path"), path); - return NULL; - } - - if (stat(path, &st) == 0) { - if (!S_ISDIR(st.st_mode)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store root %s is not a regular directory"), path); - return NULL; - } - return (CamelFolder *) 0xdeadbeef; - } - - if (errno != ENOENT - || (flags & CAMEL_STORE_FOLDER_CREATE) == 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot get folder: %s: %s"), - path, g_strerror (errno)); - return NULL; - } - - /* need to create the dir heirarchy */ - sub = g_alloca (strlen (path) + 1); - strcpy (sub, path); - slash = sub; - do { - slash = strchr (slash + 1, '/'); - if (slash) - *slash = 0; - if (stat (sub, &st) == -1) { - if (errno != ENOENT || mkdir (sub, 0700) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot get folder: %s: %s"), - path, g_strerror (errno)); - return NULL; - } - } - if (slash) - *slash = '/'; - } while (slash); - - return (CamelFolder *) 0xdeadbeef; -} - -static CamelFolder * -get_inbox(CamelStore *store, CamelException *ex) -{ - camel_exception_set(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Local stores do not have an inbox")); - return NULL; -} - -static char * -get_name (CamelService *service, gboolean brief) -{ - char *dir = ((CamelLocalStore*)service)->toplevel_dir; - - if (brief) - return g_strdup (dir); - else - return g_strdup_printf (_("Local mail file %s"), dir); -} - -static CamelFolderInfo * -get_folder_info (CamelStore *store, const char *top, - guint32 flags, CamelException *ex) -{ - /* FIXME: This is broken, but it corresponds to what was - * there before. - */ - - d(printf("-- LOCAL STORE -- get folder info: %s\n", top)); - - return NULL; -} - -static CamelFolderInfo * -create_folder(CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex) -{ - char *path = ((CamelLocalStore *)store)->toplevel_dir; - char *name; - CamelFolder *folder; - CamelFolderInfo *info = NULL; - struct stat st; - - /* This is a pretty hacky version of create folder, but should basically work */ - - if (path[0] != '/') { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store root %s is not an absolute path"), path); - return NULL; - } - - if (parent_name) - name = g_strdup_printf("%s/%s/%s", path, parent_name, folder_name); - else - name = g_strdup_printf("%s/%s", path, folder_name); - - if (stat(name, &st) == 0 || errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot get folder: %s: %s"), - name, g_strerror (errno)); - g_free(name); - return NULL; - } - - g_free(name); - - if (parent_name) - name = g_strdup_printf("%s/%s", parent_name, folder_name); - else - name = g_strdup_printf("%s", folder_name); - - folder = ((CamelStoreClass *)((CamelObject *)store)->klass)->get_folder(store, name, CAMEL_STORE_FOLDER_CREATE, ex); - if (folder) { - camel_object_unref((CamelObject *)folder); - info = ((CamelStoreClass *)((CamelObject *)store)->klass)->get_folder_info(store, name, 0, ex); - - /* get_folder(CREATE) will emit a folder_created event for us */ - /*if (info) - camel_object_trigger_event((CamelObject *)store, "folder_created", info);*/ - } - - g_free(name); - - return info; -} - -static int xrename(const char *oldp, const char *newp, const char *prefix, const char *suffix, int missingok, CamelException *ex) -{ - struct stat st; - char *old = g_strconcat(prefix, oldp, suffix, 0); - char *new = g_strconcat(prefix, newp, suffix, 0); - int ret = -1; - int err = 0; - - d(printf("renaming %s%s to %s%s\n", oldp, suffix, newp, suffix)); - - if (stat(old, &st) == -1) { - if (missingok && errno == ENOENT) { - ret = 0; - } else { - err = errno; - ret = -1; - } - } else if (S_ISDIR(st.st_mode)) { /* use rename for dirs */ - if (rename(old, new) == 0 - || stat(new, &st) == 0) { - ret = 0; - } else { - err = errno; - ret = -1; - } - } else if (link(old, new) == 0 /* and link for files */ - || (stat(new, &st) == 0 && st.st_nlink == 2)) { - if (unlink(old) == 0) { - ret = 0; - } else { - err = errno; - unlink(new); - ret = -1; - } - } else { - err = errno; - ret = -1; - } - - if (ret == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not rename folder %s to %s: %s"), - old, new, g_strerror (err)); - } - - g_free(old); - g_free(new); - return ret; -} - -/* default implementation, rename all */ -static void -rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex) -{ - char *path = CAMEL_LOCAL_STORE (store)->toplevel_dir; - CamelLocalFolder *folder = NULL; - char *newibex = g_strdup_printf("%s%s.ibex", path, new); - char *oldibex = g_strdup_printf("%s%s.ibex", path, old); - - /* try to rollback failures, has obvious races */ - - d(printf("local rename folder '%s' '%s'\n", old, new)); - - folder = camel_object_bag_get(store->folders, old); - if (folder && folder->index) { - if (camel_index_rename(folder->index, newibex) == -1) - goto ibex_failed; - } else { - /* TODO: camel_text_index_rename should find out if we have an active index itself? */ - if (camel_text_index_rename(oldibex, newibex) == -1) - goto ibex_failed; - } - - if (xrename(old, new, path, ".ev-summary", TRUE, ex)) - goto summary_failed; - - if (xrename(old, new, path, "", FALSE, ex)) - goto base_failed; - - g_free(newibex); - g_free(oldibex); - - if (folder) - camel_object_unref(folder); - - return; - -base_failed: - xrename(new, old, path, ".ev-summary", TRUE, ex); - -summary_failed: - if (folder) { - if (folder->index) - camel_index_rename(folder->index, oldibex); - } else - camel_text_index_rename(newibex, oldibex); -ibex_failed: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not rename '%s': %s"), - old, g_strerror (errno)); - - g_free(newibex); - g_free(oldibex); - - if (folder) - camel_object_unref(folder); -} - -/* default implementation, only delete metadata */ -static void -delete_folder(CamelStore *store, const char *folder_name, CamelException *ex) -{ - CamelFolderInfo *fi; - CamelException lex; - CamelFolder *lf; - char *name; - char *str; - - /* remove metadata only */ - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - str = g_strdup_printf("%s.ev-summary", name); - if (unlink(str) == -1 && errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder summary file `%s': %s"), - str, g_strerror (errno)); - g_free(str); - g_free (name); - return; - } - g_free(str); - str = g_strdup_printf("%s.ibex", name); - if (camel_text_index_remove(str) == -1 && errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder index file `%s': %s"), - str, g_strerror (errno)); - g_free(str); - g_free (name); - return; - } - g_free(str); - - camel_exception_init (&lex); - if ((lf = camel_store_get_folder (store, folder_name, 0, &lex))) { - camel_object_get (lf, NULL, CAMEL_OBJECT_STATE_FILE, &str, NULL); - camel_object_set (lf, NULL, CAMEL_OBJECT_STATE_FILE, NULL, NULL); - camel_object_unref (lf); - } else { - camel_exception_clear (&lex); - } - - if (str == NULL) - str = g_strdup_printf ("%s.cmeta", name); - - if (unlink (str) == -1 && errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder meta file `%s': %s"), - str, g_strerror (errno)); - g_free (name); - g_free (str); - return; - } - - g_free (str); - g_free (name); - - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = g_strdup (folder_name); - fi->name = g_path_get_basename (folder_name); - fi->url = g_strdup_printf ("%s:%s#%s", ((CamelService *) store)->url->protocol, - CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - fi->unread_message_count = -1; - camel_folder_info_build_path(fi, '/'); - - camel_object_trigger_event (store, "folder_deleted", fi); - - camel_folder_info_free (fi); -} diff --git a/camel/providers/local/camel-local-store.h b/camel/providers/local/camel-local-store.h deleted file mode 100644 index 21d854c562..0000000000 --- a/camel/providers/local/camel-local-store.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-mbox-store.h : class for an mbox store */ - -/* - * - * Copyright (C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_LOCAL_STORE_H -#define CAMEL_LOCAL_STORE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-store.h" - -#define CAMEL_LOCAL_STORE_TYPE (camel_local_store_get_type ()) -#define CAMEL_LOCAL_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_LOCAL_STORE_TYPE, CamelLocalStore)) -#define CAMEL_LOCAL_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_LOCAL_STORE_TYPE, CamelLocalStoreClass)) -#define CAMEL_IS_LOCAL_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_LOCAL_STORE_TYPE)) - - -typedef struct { - CamelStore parent_object; - char *toplevel_dir; - -} CamelLocalStore; - - - -typedef struct { - CamelStoreClass parent_class; - -} CamelLocalStoreClass; - - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_local_store_get_type (void); - -const gchar *camel_local_store_get_toplevel_dir (CamelLocalStore *store); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_LOCAL_STORE_H */ - - diff --git a/camel/providers/local/camel-local-summary.c b/camel/providers/local/camel-local-summary.c deleted file mode 100644 index 42534b361d..0000000000 --- a/camel/providers/local/camel-local-summary.c +++ /dev/null @@ -1,614 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "camel-local-summary.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-stream-null.h" - -#define w(x) -#define io(x) -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#define CAMEL_LOCAL_SUMMARY_VERSION (0x200) - -static CamelMessageInfo * message_info_new (CamelFolderSummary *, struct _camel_header_raw *); - -static int local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *mi); -static char *local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo *mi); - -static int local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex); -static int local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static CamelMessageInfo *local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - -static void camel_local_summary_class_init (CamelLocalSummaryClass *klass); -static void camel_local_summary_init (CamelLocalSummary *obj); -static void camel_local_summary_finalise (CamelObject *obj); -static CamelFolderSummaryClass *camel_local_summary_parent; - -CamelType -camel_local_summary_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_folder_summary_get_type(), "CamelLocalSummary", - sizeof (CamelLocalSummary), - sizeof (CamelLocalSummaryClass), - (CamelObjectClassInitFunc) camel_local_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_local_summary_init, - (CamelObjectFinalizeFunc) camel_local_summary_finalise); - } - - return type; -} - -static void -camel_local_summary_class_init(CamelLocalSummaryClass *klass) -{ - CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) klass; - - camel_local_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type())); - - sklass->message_info_new = message_info_new; - - klass->load = local_summary_load; - klass->check = local_summary_check; - klass->sync = local_summary_sync; - klass->add = local_summary_add; - - klass->encode_x_evolution = local_summary_encode_x_evolution; - klass->decode_x_evolution = local_summary_decode_x_evolution; -} - -static void -camel_local_summary_init(CamelLocalSummary *obj) -{ - struct _CamelFolderSummary *s = (CamelFolderSummary *)obj; - - /* subclasses need to set the right instance data sizes */ - s->message_info_size = sizeof(CamelMessageInfo); - s->content_info_size = sizeof(CamelMessageContentInfo); - - /* and a unique file version */ - s->version += CAMEL_LOCAL_SUMMARY_VERSION; -} - -static void -camel_local_summary_finalise(CamelObject *obj) -{ - CamelLocalSummary *mbs = CAMEL_LOCAL_SUMMARY(obj); - - if (mbs->index) - camel_object_unref((CamelObject *)mbs->index); - g_free(mbs->folder_path); -} - -void -camel_local_summary_construct(CamelLocalSummary *new, const char *filename, const char *local_name, CamelIndex *index) -{ - camel_folder_summary_set_build_content(CAMEL_FOLDER_SUMMARY(new), FALSE); - camel_folder_summary_set_filename(CAMEL_FOLDER_SUMMARY(new), filename); - new->folder_path = g_strdup(local_name); - new->index = index; - if (index) - camel_object_ref((CamelObject *)index); -} - -static int -local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex) -{ - return camel_folder_summary_load((CamelFolderSummary *)cls); -} - -/* load/check the summary */ -int -camel_local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex) -{ - struct stat st; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - - d(printf("Loading summary ...\n")); - - if (forceindex - || stat(s->summary_path, &st) == -1 - || ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->load(cls, forceindex, ex) == -1) { - w(g_warning("Could not load summary: flags may be reset")); - camel_folder_summary_clear((CamelFolderSummary *)cls); - return -1; - } - - return 0; -} - -void camel_local_summary_check_force(CamelLocalSummary *cls) -{ - cls->check_force = 1; -} - -char * -camel_local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo *info) -{ - return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->encode_x_evolution(cls, info); -} - -int -camel_local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *info) -{ - return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->decode_x_evolution(cls, xev, info); -} - -/*#define DOSTATS*/ -#ifdef DOSTATS -struct _stat_info { - int mitotal; - int micount; - int citotal; - int cicount; - int msgid; - int msgcount; -}; - -static void -do_stat_ci(CamelLocalSummary *cls, struct _stat_info *info, CamelMessageContentInfo *ci) -{ - info->cicount++; - info->citotal += ((CamelFolderSummary *)cls)->content_info_size /*+ 4 memchunks are 1/4 byte overhead per mi */; - if (ci->id) - info->citotal += strlen(ci->id) + 4; - if (ci->description) - info->citotal += strlen(ci->description) + 4; - if (ci->encoding) - info->citotal += strlen(ci->encoding) + 4; - if (ci->type) { - CamelContentType *ct = ci->type; - struct _camel_header_param *param; - - info->citotal += sizeof(*ct) + 4; - if (ct->type) - info->citotal += strlen(ct->type) + 4; - if (ct->subtype) - info->citotal += strlen(ct->subtype) + 4; - param = ct->params; - while (param) { - info->citotal += sizeof(*param) + 4; - if (param->name) - info->citotal += strlen(param->name)+4; - if (param->value) - info->citotal += strlen(param->value)+4; - param = param->next; - } - } - ci = ci->childs; - while (ci) { - do_stat_ci(cls, info, ci); - ci = ci->next; - } -} - -static void -do_stat_mi(CamelLocalSummary *cls, struct _stat_info *info, CamelMessageInfo *mi) -{ - info->micount++; - info->mitotal += ((CamelFolderSummary *)cls)->content_info_size /*+ 4*/; - - if (mi->subject) - info->mitotal += strlen(mi->subject) + 4; - if (mi->to) - info->mitotal += strlen(mi->to) + 4; - if (mi->from) - info->mitotal += strlen(mi->from) + 4; - if (mi->cc) - info->mitotal += strlen(mi->cc) + 4; - if (mi->uid) - info->mitotal += strlen(mi->uid) + 4; - - if (mi->references) { - info->mitotal += (mi->references->size-1) * sizeof(CamelSummaryMessageID) + sizeof(CamelSummaryReferences) + 4; - info->msgid += (mi->references->size) * sizeof(CamelSummaryMessageID); - info->msgcount += mi->references->size; - } - - /* dont have any user flags yet */ - - if (mi->content) { - do_stat_ci(cls, info, mi->content); - } -} - -#endif - -int -camel_local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int ret; - - ret = ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->check(cls, changeinfo, ex); - -#ifdef DOSTATS - if (ret != -1) { - int i; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - struct _stat_info stats = { 0 }; - - for (i=0;isync(cls, expunge, changeinfo, ex); -} - -CamelMessageInfo * -camel_local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex) -{ - return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->add(cls, msg, info, ci, ex); -} - -/** - * camel_local_summary_write_headers: - * @fd: - * @header: - * @xevline: - * @status: - * @xstatus: - * - * Write a bunch of headers to the file @fd. IF xevline is non NULL, then - * an X-Evolution header line is created at the end of all of the headers. - * If @status is non NULL, then a Status header line is also written. - * The headers written are termianted with a blank line. - * - * Return value: -1 on error, otherwise the number of bytes written. - **/ -int -camel_local_summary_write_headers(int fd, struct _camel_header_raw *header, const char *xevline, const char *status, const char *xstatus) -{ - int outlen = 0, len; - int newfd; - FILE *out; - - /* dum de dum, maybe the whole sync function should just use stdio for output */ - newfd = dup(fd); - if (newfd == -1) - return -1; - - out = fdopen(newfd, "w"); - if (out == NULL) { - close(newfd); - errno = EINVAL; - return -1; - } - - while (header) { - if (strcmp(header->name, "X-Evolution") != 0 - && (status == NULL || strcmp(header->name, "Status") != 0) - && (xstatus == NULL || strcmp(header->name, "X-Status") != 0)) { - len = fprintf(out, "%s:%s\n", header->name, header->value); - if (len == -1) { - fclose(out); - return -1; - } - outlen += len; - } - header = header->next; - } - - if (status) { - len = fprintf(out, "Status: %s\n", status); - if (len == -1) { - fclose(out); - return -1; - } - outlen += len; - } - - if (xstatus) { - len = fprintf(out, "X-Status: %s\n", xstatus); - if (len == -1) { - fclose(out); - return -1; - } - outlen += len; - } - - if (xevline) { - len = fprintf(out, "X-Evolution: %s\n", xevline); - if (len == -1) { - fclose(out); - return -1; - } - outlen += len; - } - - len = fprintf(out, "\n"); - if (len == -1) { - fclose(out); - return -1; - } - outlen += len; - - if (fclose(out) == -1) - return -1; - - return outlen; -} - -static int -local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - /* FIXME: sync index here ? */ - return 0; -} - -static int -local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int ret = 0; - - ret = camel_folder_summary_save((CamelFolderSummary *)cls); - if (ret == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not save summary: %s: %s"), - cls->folder_path, g_strerror (errno)); - - g_warning ("Could not save summary for %s: %s", cls->folder_path, strerror (errno)); - } - - if (cls->index && camel_index_sync(cls->index) == -1) - g_warning ("Could not sync index for %s: %s", cls->folder_path, strerror (errno)); - - return ret; -} - -static CamelMessageInfo * -local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex) -{ - CamelMessageInfo *mi; - char *xev; - - d(printf("Adding message to summary\n")); - - mi = camel_folder_summary_add_from_message((CamelFolderSummary *)cls, msg); - if (mi) { - d(printf("Added, uid = %s\n", mi->uid)); - if (info) { - CamelTag *tag = info->user_tags; - CamelFlag *flag = info->user_flags; - - while (flag) { - camel_flag_set(&mi->user_flags, flag->name, TRUE); - flag = flag->next; - } - - while (tag) { - camel_tag_set(&mi->user_tags, tag->name, tag->value); - tag = tag->next; - } - - mi->flags = mi->flags | (info->flags & 0xffff); - if (info->size) - mi->size = info->size; - } - - /* we need to calculate the size ourselves */ - if (mi->size == 0) { - CamelStreamNull *sn = (CamelStreamNull *)camel_stream_null_new(); - - camel_data_wrapper_write_to_stream((CamelDataWrapper *)msg, (CamelStream *)sn); - mi->size = sn->written; - camel_object_unref((CamelObject *)sn); - } - - mi->flags &= ~(CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_FLAGGED); - xev = camel_local_summary_encode_x_evolution(cls, mi); - camel_medium_set_header((CamelMedium *)msg, "X-Evolution", xev); - g_free(xev); - camel_folder_change_info_add_uid(ci, camel_message_info_uid(mi)); - } else { - d(printf("Failed!\n")); - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unable to add message to summary: unknown reason")); - } - return mi; -} - -static char * -local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo *mi) -{ - GString *out = g_string_new(""); - struct _camel_header_param *params = NULL; - GString *val = g_string_new(""); - CamelFlag *flag = mi->user_flags; - CamelTag *tag = mi->user_tags; - char *ret; - const char *p, *uidstr; - guint32 uid; - - /* FIXME: work out what to do with uid's that aren't stored here? */ - /* FIXME: perhaps make that a mbox folder only issue?? */ - p = uidstr = camel_message_info_uid(mi); - while (*p && isdigit(*p)) - p++; - if (*p == 0 && sscanf (uidstr, "%u", &uid) == 1) { - g_string_printf (out, "%08x-%04x", uid, mi->flags & 0xffff); - } else { - g_string_printf (out, "%s-%04x", uidstr, mi->flags & 0xffff); - } - - if (flag || tag) { - val = g_string_new (""); - - if (flag) { - while (flag) { - g_string_append (val, flag->name); - if (flag->next) - g_string_append_c (val, ','); - flag = flag->next; - } - camel_header_set_param (¶ms, "flags", val->str); - g_string_truncate (val, 0); - } - if (tag) { - while (tag) { - g_string_append (val, tag->name); - g_string_append_c (val, '='); - g_string_append (val, tag->value); - if (tag->next) - g_string_append_c (val, ','); - tag = tag->next; - } - camel_header_set_param (¶ms, "tags", val->str); - } - g_string_free (val, TRUE); - camel_header_param_list_format_append (out, params); - camel_header_param_list_free (params); - } - ret = out->str; - g_string_free (out, FALSE); - - return ret; -} - -static int -local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *mi) -{ - struct _camel_header_param *params, *scan; - guint32 uid, flags; - char *header; - int i; - - /* check for uid/flags */ - header = camel_header_token_decode(xev); - if (header && strlen(header) == strlen("00000000-0000") - && sscanf(header, "%08x-%04x", &uid, &flags) == 2) { - char uidstr[20]; - if (mi) { - sprintf(uidstr, "%u", uid); - camel_message_info_set_uid(mi, g_strdup(uidstr)); - mi->flags = flags; - } - } else { - g_free(header); - return -1; - } - g_free(header); - - if (mi == NULL) - return 0; - - /* check for additional data */ - header = strchr(xev, ';'); - if (header) { - params = camel_header_param_list_decode(header+1); - scan = params; - while (scan) { - if (!strcasecmp(scan->name, "flags")) { - char **flagv = g_strsplit(scan->value, ",", 1000); - - for (i=0;flagv[i];i++) { - camel_flag_set(&mi->user_flags, flagv[i], TRUE); - } - g_strfreev(flagv); - } else if (!strcasecmp(scan->name, "tags")) { - char **tagv = g_strsplit(scan->value, ",", 10000); - char *val; - - for (i=0;tagv[i];i++) { - val = strchr(tagv[i], '='); - if (val) { - *val++ = 0; - camel_tag_set(&mi->user_tags, tagv[i], val); - val[-1]='='; - } - } - g_strfreev(tagv); - } - scan = scan->next; - } - camel_header_param_list_free(params); - } - return 0; -} - -static CamelMessageInfo * -message_info_new(CamelFolderSummary *s, struct _camel_header_raw *h) -{ - CamelMessageInfo *mi; - CamelLocalSummary *cls = (CamelLocalSummary *)s; - - mi = ((CamelFolderSummaryClass *)camel_local_summary_parent)->message_info_new(s, h); - if (mi) { - const char *xev; - int doindex = FALSE; - - xev = camel_header_raw_find(&h, "X-Evolution", NULL); - if (xev==NULL || camel_local_summary_decode_x_evolution(cls, xev, mi) == -1) { - /* to indicate it has no xev header */ - mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV; - camel_message_info_set_uid(mi, camel_folder_summary_next_uid_string(s)); - - /* shortcut, no need to look it up in the index library */ - doindex = TRUE; - } - - if (cls->index - && (doindex - || cls->index_force - || !camel_index_has_name(cls->index, camel_message_info_uid(mi)))) { - d(printf("Am indexing message %s\n", camel_message_info_uid(mi))); - camel_folder_summary_set_index(s, cls->index); - } else { - d(printf("Not indexing message %s\n", camel_message_info_uid(mi))); - camel_folder_summary_set_index(s, NULL); - } - } - - return mi; -} diff --git a/camel/providers/local/camel-local-summary.h b/camel/providers/local/camel-local-summary.h deleted file mode 100644 index 25d77e62c3..0000000000 --- a/camel/providers/local/camel-local-summary.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_LOCAL_SUMMARY_H -#define _CAMEL_LOCAL_SUMMARY_H - -#include -#include -#include -#include - -#define CAMEL_LOCAL_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_local_summary_get_type (), CamelLocalSummary) -#define CAMEL_LOCAL_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_local_summary_get_type (), CamelLocalSummaryClass) -#define CAMEL_IS_LOCAL_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_local_summary_get_type ()) - -typedef struct _CamelLocalSummary CamelLocalSummary; -typedef struct _CamelLocalSummaryClass CamelLocalSummaryClass; - -/* extra summary flags */ -enum { - CAMEL_MESSAGE_FOLDER_NOXEV = 1<<17, - CAMEL_MESSAGE_FOLDER_XEVCHANGE = 1<<18, - CAMEL_MESSAGE_FOLDER_NOTSEEN = 1<<19, /* have we seen this in processing this loop? */ -}; - -struct _CamelLocalSummary { - CamelFolderSummary parent; - - char *folder_path; /* name of matching folder */ - - CamelIndex *index; - unsigned int index_force:1; /* do we force index during creation? */ - unsigned int check_force:1; /* does a check force a full check? */ -}; - -struct _CamelLocalSummaryClass { - CamelFolderSummaryClass parent_class; - - int (*load)(CamelLocalSummary *cls, int forceindex, CamelException *ex); - int (*check)(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); - int (*sync)(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); - CamelMessageInfo *(*add)(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - - char *(*encode_x_evolution)(CamelLocalSummary *cls, const CamelMessageInfo *info); - int (*decode_x_evolution)(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *info); -}; - -CamelType camel_local_summary_get_type (void); -void camel_local_summary_construct (CamelLocalSummary *new, const char *filename, const char *local_name, CamelIndex *index); - -/* load/check the summary */ -int camel_local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex); -/* check for new/removed messages */ -int camel_local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *, CamelException *ex); -/* perform a folder sync or expunge, if needed */ -int camel_local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *, CamelException *ex); -/* add a new message to the summary */ -CamelMessageInfo *camel_local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - -/* force the next check to be a full check/rebuild */ -void camel_local_summary_check_force(CamelLocalSummary *cls); - -/* generate an X-Evolution header line */ -char *camel_local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo *info); -int camel_local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *info); - -/* utility functions - write headers to a file with optional X-Evolution header and/or status header */ -int camel_local_summary_write_headers(int fd, struct _camel_header_raw *header, const char *xevline, const char *status, const char *xstatus); - -#endif /* ! _CAMEL_LOCAL_SUMMARY_H */ - diff --git a/camel/providers/local/camel-maildir-folder.c b/camel/providers/local/camel-maildir-folder.c deleted file mode 100644 index eca07efbef..0000000000 --- a/camel/providers/local/camel-maildir-folder.c +++ /dev/null @@ -1,245 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Authors: Michael Zucchi - * - * Copyright (C) 1999, 2003 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "camel-maildir-folder.h" -#include "camel-maildir-store.h" -#include "camel-stream-fs.h" -#include "camel-maildir-summary.h" -#include "camel-data-wrapper.h" -#include "camel-mime-message.h" -#include "camel-exception.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -static CamelLocalFolderClass *parent_class = NULL; - -/* Returns the class for a CamelMaildirFolder */ -#define CMAILDIRF_CLASS(so) CAMEL_MAILDIR_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMAILDIRS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static CamelLocalSummary *maildir_create_summary(const char *path, const char *folder, CamelIndex *index); - -static void maildir_append_message(CamelFolder * folder, CamelMimeMessage * message, const CamelMessageInfo *info, char **appended_uid, CamelException * ex); -static CamelMimeMessage *maildir_get_message(CamelFolder * folder, const gchar * uid, CamelException * ex); - -static void maildir_finalize(CamelObject * object); - -static void camel_maildir_folder_class_init(CamelObjectClass * camel_maildir_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_maildir_folder_class); - CamelLocalFolderClass *lclass = (CamelLocalFolderClass *)camel_maildir_folder_class; - - parent_class = CAMEL_LOCAL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_local_folder_get_type())); - - /* virtual method definition */ - - /* virtual method overload */ - camel_folder_class->append_message = maildir_append_message; - camel_folder_class->get_message = maildir_get_message; - - lclass->create_summary = maildir_create_summary; -} - -static void maildir_init(gpointer object, gpointer klass) -{ - /*CamelFolder *folder = object; - CamelMaildirFolder *maildir_folder = object;*/ -} - -static void maildir_finalize(CamelObject * object) -{ - /*CamelMaildirFolder *maildir_folder = CAMEL_MAILDIR_FOLDER(object);*/ -} - -CamelType camel_maildir_folder_get_type(void) -{ - static CamelType camel_maildir_folder_type = CAMEL_INVALID_TYPE; - - if (camel_maildir_folder_type == CAMEL_INVALID_TYPE) { - camel_maildir_folder_type = camel_type_register(CAMEL_LOCAL_FOLDER_TYPE, "CamelMaildirFolder", - sizeof(CamelMaildirFolder), - sizeof(CamelMaildirFolderClass), - (CamelObjectClassInitFunc) camel_maildir_folder_class_init, - NULL, - (CamelObjectInitFunc) maildir_init, - (CamelObjectFinalizeFunc) maildir_finalize); - } - - return camel_maildir_folder_type; -} - -CamelFolder * -camel_maildir_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) -{ - CamelFolder *folder; - - d(printf("Creating maildir folder: %s\n", full_name)); - - folder = (CamelFolder *)camel_object_new(CAMEL_MAILDIR_FOLDER_TYPE); - - if (parent_store->flags & CAMEL_STORE_FILTER_INBOX - && strcmp(full_name, ".") == 0) - folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT; - - folder = (CamelFolder *)camel_local_folder_construct((CamelLocalFolder *)folder, - parent_store, full_name, flags, ex); - - return folder; -} - -static CamelLocalSummary *maildir_create_summary(const char *path, const char *folder, CamelIndex *index) -{ - return (CamelLocalSummary *)camel_maildir_summary_new(path, folder, index); -} - -static void -maildir_append_message (CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, char **appended_uid, CamelException *ex) -{ - CamelMaildirFolder *maildir_folder = (CamelMaildirFolder *)folder; - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *output_stream; - CamelMessageInfo *mi; - CamelMaildirMessageInfo *mdi; - char *name, *dest = NULL; - - d(printf("Appending message\n")); - - /* add it to the summary/assign the uid, etc */ - mi = camel_local_summary_add((CamelLocalSummary *)folder->summary, message, info, lf->changes, ex); - if (camel_exception_is_set (ex)) - return; - - mdi = (CamelMaildirMessageInfo *)mi; - - d(printf("Appending message: uid is %s filename is %s\n", camel_message_info_uid(mi), mdi->filename)); - - /* write it out to tmp, use the uid we got from the summary */ - name = g_strdup_printf ("%s/tmp/%s", lf->folder_path, camel_message_info_uid(mi)); - output_stream = camel_stream_fs_new_with_name (name, O_WRONLY|O_CREAT, 0600); - if (output_stream == NULL) - goto fail_write; - - if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *)message, output_stream) == -1 - || camel_stream_close (output_stream) == -1) - goto fail_write; - - /* now move from tmp to cur (bypass new, does it matter?) */ - dest = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename (mdi)); - if (rename (name, dest) == 1) - goto fail_write; - - g_free (dest); - g_free (name); - - camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", - ((CamelLocalFolder *)maildir_folder)->changes); - camel_folder_change_info_clear (((CamelLocalFolder *)maildir_folder)->changes); - - if (appended_uid) - *appended_uid = g_strdup(camel_message_info_uid(mi)); - - return; - - fail_write: - - /* remove the summary info so we are not out-of-sync with the mh folder */ - camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (folder->summary), - camel_message_info_uid (mi)); - - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Maildir append message cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to maildir folder: %s: %s"), - name, g_strerror (errno)); - - if (output_stream) { - camel_object_unref (CAMEL_OBJECT (output_stream)); - unlink (name); - } - - g_free (name); - g_free (dest); -} - -static CamelMimeMessage *maildir_get_message(CamelFolder * folder, const gchar * uid, CamelException * ex) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *message_stream = NULL; - CamelMimeMessage *message = NULL; - CamelMessageInfo *info; - char *name; - CamelMaildirMessageInfo *mdi; - - d(printf("getting message: %s\n", uid)); - - /* get the message summary info */ - if ((info = camel_folder_summary_uid(folder->summary, uid)) == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s\n %s"), uid, _("No such message")); - return NULL; - } - - mdi = (CamelMaildirMessageInfo *)info; - - /* what do we do if the message flags (and :info data) changes? filename mismatch - need to recheck I guess */ - name = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename(mdi)); - - camel_folder_summary_info_free(folder->summary, info); - - if ((message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0)) == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s\n %s"), - name, g_strerror (errno)); - g_free(name); - return NULL; - } - - message = camel_mime_message_new(); - if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, message_stream) == -1) { - camel_exception_setv(ex, (errno==EINTR)?CAMEL_EXCEPTION_USER_CANCEL:CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s\n %s"), - name, _("Invalid message contents")); - g_free(name); - camel_object_unref((CamelObject *)message_stream); - camel_object_unref((CamelObject *)message); - return NULL; - - } - camel_object_unref((CamelObject *)message_stream); - g_free(name); - - return message; -} diff --git a/camel/providers/local/camel-maildir-folder.h b/camel/providers/local/camel-maildir-folder.h deleted file mode 100644 index c495d9b14d..0000000000 --- a/camel/providers/local/camel-maildir-folder.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: - * Michael Zucchi - * - * Copyright (C) 1999 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_MAILDIR_FOLDER_H -#define CAMEL_MAILDIR_FOLDER_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus } */ -#include "camel-local-folder.h" - -#define CAMEL_MAILDIR_FOLDER_TYPE (camel_maildir_folder_get_type ()) -#define CAMEL_MAILDIR_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MAILDIR_FOLDER_TYPE, CamelMaildirFolder)) -#define CAMEL_MAILDIR_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MAILDIR_FOLDER_TYPE, CamelMaildirFolderClass)) -#define CAMEL_IS_MAILDIR_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_MAILDIR_FOLDER_TYPE)) - -typedef struct { - CamelLocalFolder parent_object; - -} CamelMaildirFolder; - -typedef struct { - CamelLocalFolderClass parent_class; - - /* Virtual methods */ - -} CamelMaildirFolderClass; - -/* public methods */ -CamelFolder *camel_maildir_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_maildir_folder_get_type(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* CAMEL_MAILDIR_FOLDER_H */ diff --git a/camel/providers/local/camel-maildir-store.c b/camel/providers/local/camel-maildir-store.c deleted file mode 100644 index c84c37158c..0000000000 --- a/camel/providers/local/camel-maildir-store.c +++ /dev/null @@ -1,416 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2000 Ximian, Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include - -#include "camel-maildir-store.h" -#include "camel-maildir-folder.h" -#include "camel-exception.h" -#include "camel-url.h" -#include "camel-private.h" - -#define d(x) - -static CamelLocalStoreClass *parent_class = NULL; - -/* Returns the class for a CamelMaildirStore */ -#define CMAILDIRS_CLASS(so) CAMEL_MAILDIR_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMAILDIRF_CLASS(so) CAMEL_MAILDIR_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex); -static CamelFolder *get_inbox (CamelStore *store, CamelException *ex); -static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex); - -static CamelFolderInfo * get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); - -static void camel_maildir_store_class_init(CamelObjectClass * camel_maildir_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_maildir_store_class); - /*CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_maildir_store_class);*/ - - parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type()); - - /* virtual method overload, use defaults for most */ - camel_store_class->get_folder = get_folder; - camel_store_class->get_inbox = get_inbox; - camel_store_class->delete_folder = delete_folder; - - camel_store_class->get_folder_info = get_folder_info; - camel_store_class->free_folder_info = camel_store_free_folder_info_full; -} - -CamelType camel_maildir_store_get_type(void) -{ - static CamelType camel_maildir_store_type = CAMEL_INVALID_TYPE; - - if (camel_maildir_store_type == CAMEL_INVALID_TYPE) { - camel_maildir_store_type = camel_type_register(CAMEL_LOCAL_STORE_TYPE, "CamelMaildirStore", - sizeof(CamelMaildirStore), - sizeof(CamelMaildirStoreClass), - (CamelObjectClassInitFunc) camel_maildir_store_class_init, - NULL, - NULL, - NULL); - } - - return camel_maildir_store_type; -} - -static CamelFolder * -get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex) -{ - char *name, *tmp, *cur, *new; - struct stat st; - CamelFolder *folder = NULL; - - if (!((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex)) - return NULL; - - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - tmp = g_strdup_printf("%s/tmp", name); - cur = g_strdup_printf("%s/cur", name); - new = g_strdup_printf("%s/new", name); - - if (stat(name, &st) == -1) { - if (errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open folder `%s':\n%s"), - folder_name, g_strerror (errno)); - } else if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Folder `%s' does not exist."), folder_name); - } else { - if (mkdir(name, 0700) != 0 - || mkdir(tmp, 0700) != 0 - || mkdir(cur, 0700) != 0 - || mkdir(new, 0700) != 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create folder `%s':\n%s"), - folder_name, g_strerror (errno)); - rmdir(tmp); - rmdir(cur); - rmdir(new); - rmdir(name); - } else { - folder = camel_maildir_folder_new(store, folder_name, flags, ex); - } - } - } else if (!S_ISDIR(st.st_mode) - || stat(tmp, &st) != 0 || !S_ISDIR(st.st_mode) - || stat(cur, &st) != 0 || !S_ISDIR(st.st_mode) - || stat(new, &st) != 0 || !S_ISDIR(st.st_mode)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("`%s' is not a maildir directory."), name); - } else { - folder = camel_maildir_folder_new(store, folder_name, flags, ex); - } - - g_free(name); - g_free(tmp); - g_free(cur); - g_free(new); - - return folder; -} - -static CamelFolder * -get_inbox (CamelStore *store, CamelException *ex) -{ - return get_folder (store, ".", 0, ex); -} - -static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex) -{ - char *name, *tmp, *cur, *new; - struct stat st; - - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - - tmp = g_strdup_printf("%s/tmp", name); - cur = g_strdup_printf("%s/cur", name); - new = g_strdup_printf("%s/new", name); - - if (stat(name, &st) == -1 || !S_ISDIR(st.st_mode) - || stat(tmp, &st) == -1 || !S_ISDIR(st.st_mode) - || stat(cur, &st) == -1 || !S_ISDIR(st.st_mode) - || stat(new, &st) == -1 || !S_ISDIR(st.st_mode)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s': %s"), - folder_name, errno ? g_strerror (errno) : - _("not a maildir directory")); - } else { - int err = 0; - - /* remove subdirs first - will fail if not empty */ - if (rmdir(cur) == -1 || rmdir(new) == -1) { - err = errno; - } else { - DIR *dir; - struct dirent *d; - - /* for tmp (only), its contents is irrelevant */ - dir = opendir(tmp); - if (dir) { - while ( (d=readdir(dir)) ) { - char *name = d->d_name, *file; - - if (!strcmp(name, ".") || !strcmp(name, "..")) - continue; - file = g_strdup_printf("%s/%s", tmp, name); - unlink(file); - g_free(file); - } - closedir(dir); - } - if (rmdir(tmp) == -1 || rmdir(name) == -1) - err = errno; - } - - if (err != 0) { - /* easier just to mkdir all (and let them fail), than remember what we got to */ - mkdir(name, 0700); - mkdir(cur, 0700); - mkdir(new, 0700); - mkdir(tmp, 0700); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s': %s"), - folder_name, g_strerror (err)); - } else { - /* and remove metadata */ - ((CamelStoreClass *)parent_class)->delete_folder(store, folder_name, ex); - } - } - - g_free(name); - g_free(tmp); - g_free(cur); - g_free(new); -} - -static CamelFolderInfo *camel_folder_info_new(const char *url, const char *full, const char *name, int unread) -{ - CamelFolderInfo *fi; - - fi = g_malloc0(sizeof(*fi)); - fi->url = g_strdup(url); - fi->full_name = g_strdup(full); - fi->name = g_strdup(name); - fi->unread_message_count = unread; - camel_folder_info_build_path(fi, '/'); - - d(printf("Adding maildir info: '%s' '%s' '%s' '%s'\n", fi->path, fi->name, fi->full_name, fi->url)); - - return fi; -} - -/* used to find out where we've visited already */ -struct _inode { - dev_t dnode; - ino_t inode; -}; - -/* returns number of records found at or below this level */ -static int scan_dir(CamelStore *store, GHashTable *visited, char *root, const char *path, guint32 flags, CamelFolderInfo *parent, CamelFolderInfo **fip, CamelException *ex) -{ - DIR *dir; - struct dirent *d; - char *name, *uri, *tmp, *cur, *new; - const char *base; - CamelFolderInfo *fi = NULL; - struct stat st; - CamelFolder *folder; - int unread; - - /* look for folders matching the right structure, recursively */ - name = g_strdup_printf("%s/%s", root, path); - - d(printf("checking dir '%s' part '%s' for maildir content\n", root, path)); - - tmp = g_strdup_printf("%s/tmp", name); - cur = g_strdup_printf("%s/cur", name); - new = g_strdup_printf("%s/new", name); - - if (stat(tmp, &st) == 0 && S_ISDIR(st.st_mode) - && stat(cur, &st) == 0 && S_ISDIR(st.st_mode) - && stat(new, &st) == 0 && S_ISDIR(st.st_mode)) { - uri = g_strdup_printf("maildir:%s#%s", root, path); - } else - uri = g_strdup_printf("maildir:%s;noselect=yes#%s", root, path); - - base = strrchr(path, '/'); - if (base) - base++; - else - base = path; - - /* if we have this folder open, get the real unread count */ - folder = camel_object_bag_get(store->folders, path); - if (folder) { - if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) - camel_folder_refresh_info(folder, NULL); - unread = camel_folder_get_unread_message_count(folder); - camel_object_unref(folder); - } else { - unread = -1; - } - - /* if we dont have a folder, then scan the directory and get the unread - count from there, which is reasonably cheap (on decent filesystem) */ - /* Well we could get this from the summary, but this is more accurate */ - if (folder == NULL - && (flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) { - unread = 0; - dir = opendir(new); - if (dir) { - /* we assume that all files here are unread ones */ - while ( (d = readdir(dir)) ) { - if (d->d_name[0] != '.') - unread++; - } - closedir(dir); - } - dir = opendir(cur); - if (dir) { - /* any files with flags but not the 'S' (seen) flag are unread */ - while ( (d = readdir(dir)) ) { - char *p = strstr(d->d_name, ":2,"); - - if (p && strchr(p, 'S') == NULL) - unread++; - } - closedir(dir); - } - } - - fi = camel_folder_info_new(uri, path, base, unread); - - d(printf("found! uri = %s\n", fi->url)); - d(printf(" full_name = %s\n name = '%s'\n", fi->full_name, fi->name)); - - fi->parent = parent; - fi->sibling = *fip; - *fip = fi; - g_free(uri); - - g_free(tmp); - g_free(cur); - g_free(new); - - unread = 0; - - /* always look further if asked */ - if (((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) || parent == NULL)) { - dir = opendir(name); - if (dir == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not scan folder `%s': %s"), - root, g_strerror (errno)); - g_free(name); - return -1; - } - - while ( (d = readdir(dir)) ) { - if (strcmp(d->d_name, "tmp") == 0 - || strcmp(d->d_name, "cur") == 0 - || strcmp(d->d_name, "new") == 0 - || strcmp(d->d_name, ".") == 0 - || strcmp(d->d_name, "..") == 0) - continue; - - tmp = g_strdup_printf("%s/%s", name, d->d_name); - if (stat(tmp, &st) == 0 && S_ISDIR(st.st_mode)) { - struct _inode in = { st.st_dev, st.st_ino }; - - /* see if we've visited already */ - if (g_hash_table_lookup(visited, &in) == NULL) { - struct _inode *inew = g_malloc(sizeof(*inew)); - - *inew = in; - g_hash_table_insert(visited, inew, inew); - new = g_strdup_printf("%s/%s", path, d->d_name); - if (scan_dir(store, visited, root, new, flags, fi, &fi->child, ex) == -1) { - g_free(tmp); - g_free(new); - closedir(dir); - return -1; - } - g_free(new); - } - } - g_free(tmp); - } - closedir(dir); - } - - g_free(name); - - return 0; -} - -static guint inode_hash(const void *d) -{ - const struct _inode *v = d; - - return v->inode ^ v->dnode; -} - -static gboolean inode_equal(const void *a, const void *b) -{ - const struct _inode *v1 = a, *v2 = b; - - return v1->inode == v2->inode && v1->dnode == v2->dnode; -} - -static void inode_free(void *k, void *v, void *d) -{ - g_free(k); -} - -static CamelFolderInfo * -get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *fi = NULL; - CamelLocalStore *local_store = (CamelLocalStore *)store; - GHashTable *visited; - - visited = g_hash_table_new(inode_hash, inode_equal); - - if (scan_dir(store, visited, ((CamelService *)local_store)->url->path, top?top:".", flags, NULL, &fi, ex) == -1 && fi != NULL) { - camel_store_free_folder_info_full(store, fi); - fi = NULL; - } - - g_hash_table_foreach(visited, inode_free, NULL); - g_hash_table_destroy(visited); - - return fi; -} diff --git a/camel/providers/local/camel-maildir-store.h b/camel/providers/local/camel-maildir-store.h deleted file mode 100644 index f7725bc189..0000000000 --- a/camel/providers/local/camel-maildir-store.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2000 Ximian, Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_MAILDIR_STORE_H -#define CAMEL_MAILDIR_STORE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus } */ - -#include "camel-local-store.h" - -#define CAMEL_MAILDIR_STORE_TYPE (camel_maildir_store_get_type ()) -#define CAMEL_MAILDIR_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MAILDIR_STORE_TYPE, CamelMaildirStore)) -#define CAMEL_MAILDIR_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MAILDIR_STORE_TYPE, CamelMaildirStoreClass)) -#define CAMEL_IS_MAILDIR_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_MAILDIR_STORE_TYPE)) - -typedef struct { - CamelLocalStore parent_object; - -} CamelMaildirStore; - -typedef struct { - CamelLocalStoreClass parent_class; - -} CamelMaildirStoreClass; - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_maildir_store_get_type(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* CAMEL_MAILDIR_STORE_H */ diff --git a/camel/providers/local/camel-maildir-summary.c b/camel/providers/local/camel-maildir-summary.c deleted file mode 100644 index 37e1ac2ce7..0000000000 --- a/camel/providers/local/camel-maildir-summary.c +++ /dev/null @@ -1,807 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Not Zed - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "camel-maildir-summary.h" -#include -#include - -#include "camel-private.h" -#include "e-util/e-memory.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#define CAMEL_MAILDIR_SUMMARY_VERSION (0x2000) - -static CamelMessageInfo *message_info_load(CamelFolderSummary *s, FILE *in); -static CamelMessageInfo *message_info_new(CamelFolderSummary *, struct _camel_header_raw *); -static void message_info_free(CamelFolderSummary *, CamelMessageInfo *mi); - -static int maildir_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex); -static int maildir_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int maildir_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static CamelMessageInfo *maildir_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - -static char *maildir_summary_next_uid_string(CamelFolderSummary *s); -static int maildir_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *mi); -static char *maildir_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo *mi); - -static void camel_maildir_summary_class_init (CamelMaildirSummaryClass *class); -static void camel_maildir_summary_init (CamelMaildirSummary *gspaper); -static void camel_maildir_summary_finalise (CamelObject *obj); - -#define _PRIVATE(x) (((CamelMaildirSummary *)(x))->priv) - -struct _CamelMaildirSummaryPrivate { - char *current_file; - char *hostname; - - GHashTable *load_map; -}; - -static CamelLocalSummaryClass *parent_class; - -CamelType -camel_maildir_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_local_summary_get_type (), "CamelMaildirSummary", - sizeof(CamelMaildirSummary), - sizeof(CamelMaildirSummaryClass), - (CamelObjectClassInitFunc)camel_maildir_summary_class_init, - NULL, - (CamelObjectInitFunc)camel_maildir_summary_init, - (CamelObjectFinalizeFunc)camel_maildir_summary_finalise); - } - - return type; -} - -static void -camel_maildir_summary_class_init (CamelMaildirSummaryClass *class) -{ - CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) class; - CamelLocalSummaryClass *lklass = (CamelLocalSummaryClass *)class; - - parent_class = (CamelLocalSummaryClass *)camel_type_get_global_classfuncs(camel_local_summary_get_type ()); - - /* override methods */ - sklass->message_info_load = message_info_load; - sklass->message_info_new = message_info_new; - sklass->message_info_free = message_info_free; - sklass->next_uid_string = maildir_summary_next_uid_string; - - lklass->load = maildir_summary_load; - lklass->check = maildir_summary_check; - lklass->sync = maildir_summary_sync; - lklass->add = maildir_summary_add; - lklass->encode_x_evolution = maildir_summary_encode_x_evolution; - lklass->decode_x_evolution = maildir_summary_decode_x_evolution; -} - -static void -camel_maildir_summary_init (CamelMaildirSummary *o) -{ - struct _CamelFolderSummary *s = (CamelFolderSummary *) o; - char hostname[256]; - - o->priv = g_malloc0(sizeof(*o->priv)); - /* set unique file version */ - s->version += CAMEL_MAILDIR_SUMMARY_VERSION; - - s->message_info_size = sizeof(CamelMaildirMessageInfo); - s->content_info_size = sizeof(CamelMaildirMessageContentInfo); - -#if defined (DOEPOOLV) || defined (DOESTRV) - s->message_info_strings = CAMEL_MAILDIR_INFO_LAST; -#endif - - if (gethostname(hostname, 256) == 0) { - o->priv->hostname = g_strdup(hostname); - } else { - o->priv->hostname = g_strdup("localhost"); - } -} - -static void -camel_maildir_summary_finalise(CamelObject *obj) -{ - CamelMaildirSummary *o = (CamelMaildirSummary *)obj; - - g_free(o->priv->hostname); - g_free(o->priv); -} - -/** - * camel_maildir_summary_new: - * - * Create a new CamelMaildirSummary object. - * - * Return value: A new #CamelMaildirSummary object. - **/ -CamelMaildirSummary *camel_maildir_summary_new (const char *filename, const char *maildirdir, CamelIndex *index) -{ - CamelMaildirSummary *o = (CamelMaildirSummary *)camel_object_new(camel_maildir_summary_get_type ()); - - camel_local_summary_construct((CamelLocalSummary *)o, filename, maildirdir, index); - return o; -} - -/* the 'standard' maildir flags. should be defined in sorted order. */ -static struct { - char flag; - guint32 flagbit; -} flagbits[] = { - { 'F', CAMEL_MESSAGE_FLAGGED }, - { 'R', CAMEL_MESSAGE_ANSWERED }, - { 'S', CAMEL_MESSAGE_SEEN }, - { 'T', CAMEL_MESSAGE_DELETED }, -}; - -/* convert the uid + flags into a unique:info maildir format */ -char *camel_maildir_summary_info_to_name(const CamelMessageInfo *info) -{ - const char *uid; - char *p, *buf; - int i; - - uid = camel_message_info_uid (info); - buf = g_alloca (strlen (uid) + strlen (":2,") + (sizeof (flagbits) / sizeof (flagbits[0])) + 1); - p = buf + sprintf (buf, "%s:2,", uid); - for (i = 0; i < sizeof (flagbits) / sizeof (flagbits[0]); i++) { - if (info->flags & flagbits[i].flagbit) - *p++ = flagbits[i].flag; - } - *p = 0; - - return g_strdup(buf); -} - -/* returns 0 if the info matches (or there was none), otherwise we changed it */ -int camel_maildir_summary_name_to_info(CamelMessageInfo *info, const char *name) -{ - char *p, c; - guint32 set = 0; /* what we set */ - /*guint32 all = 0;*/ /* all flags */ - int i; - - p = strstr(name, ":2,"); - if (p) { - p+=3; - while ((c = *p++)) { - /* we could assume that the flags are in order, but its just as easy not to require */ - for (i=0;iflags & flagbits[i].flagbit) == 0) { - set |= flagbits[i].flagbit; - } - /*all |= flagbits[i].flagbit;*/ - } - } - - /* changed? */ - /*if ((info->flags & all) != set) {*/ - if ((info->flags & set) != set) { - /* ok, they did change, only add the new flags ('merge flags'?) */ - /*info->flags &= all; if we wanted to set only the new flags, which we probably dont */ - info->flags |= set; - return 1; - } - } - - return 0; -} - -/* for maildir, x-evolution isn't used, so dont try and get anything out of it */ -static int maildir_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *mi) -{ - return -1; -} - -static char *maildir_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo *mi) -{ - return NULL; -} - -/* FIXME: - both 'new' and 'add' will try and set the filename, this is not ideal ... -*/ -static CamelMessageInfo *maildir_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *changes, CamelException *ex) -{ - CamelMessageInfo *mi; - - mi = ((CamelLocalSummaryClass *) parent_class)->add(cls, msg, info, changes, ex); - if (mi) { - if (info) { - camel_maildir_info_set_filename(mi, camel_maildir_summary_info_to_name(mi)); - d(printf("Setting filename to %s\n", camel_maildir_info_filename(mi))); - } - } - - return mi; -} - -static CamelMessageInfo *message_info_new(CamelFolderSummary * s, struct _camel_header_raw *h) -{ - CamelMessageInfo *mi, *info; - CamelMaildirSummary *mds = (CamelMaildirSummary *)s; - CamelMaildirMessageInfo *mdi; - const char *uid; - - mi = ((CamelFolderSummaryClass *) parent_class)->message_info_new(s, h); - /* assign the uid and new filename */ - if (mi) { - mdi = (CamelMaildirMessageInfo *)mi; - - uid = camel_message_info_uid(mi); - if (uid==NULL || uid[0] == 0) - camel_message_info_set_uid(mi, camel_folder_summary_next_uid_string(s)); - - /* handle 'duplicates' */ - info = camel_folder_summary_uid(s, uid); - if (info) { - d(printf("already seen uid '%s', just summarising instead\n", uid)); - camel_folder_summary_info_free(s, mi); - mdi = (CamelMaildirMessageInfo *)mi = info; - } - - /* with maildir we know the real received date, from the filename */ - mi->date_received = strtoul(camel_message_info_uid(mi), NULL, 10); - - if (mds->priv->current_file) { -#if 0 - char *p1, *p2, *p3; - unsigned long uid; -#endif - /* if setting from a file, grab the flags from it */ - camel_maildir_info_set_filename(mi, g_strdup(mds->priv->current_file)); - camel_maildir_summary_name_to_info(mi, mds->priv->current_file); - -#if 0 - /* Actually, I dont think all this effort is worth it at all ... */ - - /* also, see if we can extract the next-id from tne name, and safe-if-fy ourselves against collisions */ - /* we check for something.something_number.something */ - p1 = strchr(mdi->filename, '.'); - if (p1) { - p2 = strchr(p1+1, '.'); - p3 = strchr(p1+1, '_'); - if (p2 && p3 && p30) - camel_folder_summary_set_uid(s, uid); - } - } -#endif - } else { - /* if creating a file, set its name from the flags we have */ - camel_maildir_info_set_filename(mdi, camel_maildir_summary_info_to_name(mi)); - d(printf("Setting filename to %s\n", camel_maildir_info_filename(mi))); - } - } - - return mi; -} - - -static void message_info_free(CamelFolderSummary *s, CamelMessageInfo *mi) -{ -#if !defined (DOEPOOLV) && !defined (DOESTRV) - CamelMaildirMessageInfo *mdi = (CamelMaildirMessageInfo *)mi; - - g_free(mdi->filename); -#endif - ((CamelFolderSummaryClass *) parent_class)->message_info_free(s, mi); -} - - -static char *maildir_summary_next_uid_string(CamelFolderSummary *s) -{ - CamelMaildirSummary *mds = (CamelMaildirSummary *)s; - - d(printf("next uid string called?\n")); - - /* if we have a current file, then use that to get the uid */ - if (mds->priv->current_file) { - char *cln; - - cln = strchr(mds->priv->current_file, ':'); - if (cln) - return g_strndup(mds->priv->current_file, cln-mds->priv->current_file); - else - return g_strdup(mds->priv->current_file); - } else { - /* the first would probably work, but just to be safe, check for collisions */ -#if 0 - return g_strdup_printf("%ld.%d_%u.%s", time(0), getpid(), camel_folder_summary_next_uid(s), mds->priv->hostname); -#else - CamelLocalSummary *cls = (CamelLocalSummary *)s; - char *name = NULL, *uid = NULL; - struct stat st; - int retry = 0; - guint32 nextuid = camel_folder_summary_next_uid(s); - - /* we use time.pid_count.hostname */ - do { - if (retry > 0) { - g_free(name); - g_free(uid); - sleep(2); - } - uid = g_strdup_printf("%ld.%d_%u.%s", time(0), getpid(), nextuid, mds->priv->hostname); - name = g_strdup_printf("%s/tmp/%s", cls->folder_path, uid); - retry++; - } while (stat(name, &st) == 0 && retry<3); - - /* I dont know what we're supposed to do if it fails to find a unique name?? */ - - g_free(name); - return uid; -#endif - } -} - -static CamelMessageInfo * -message_info_load(CamelFolderSummary *s, FILE *in) -{ - CamelMessageInfo *mi; - CamelMaildirSummary *mds = (CamelMaildirSummary *)s; - - mi = ((CamelFolderSummaryClass *) parent_class)->message_info_load(s, in); - if (mi) { - char *name; - - if (mds->priv->load_map - && (name = g_hash_table_lookup(mds->priv->load_map, camel_message_info_uid(mi)))) { - d(printf("Setting filename of %s to %s\n", camel_message_info_uid(mi), name)); - camel_maildir_info_set_filename(mi, g_strdup(name)); - camel_maildir_summary_name_to_info(mi, name); - } - } - - return mi; -} - -static int maildir_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex) -{ - char *cur; - DIR *dir; - struct dirent *d; - CamelMaildirSummary *mds = (CamelMaildirSummary *)cls; - char *uid; - EMemPool *pool; - int ret; - - cur = g_strdup_printf("%s/cur", cls->folder_path); - - d(printf("pre-loading uid <> filename map\n")); - - dir = opendir(cur); - if (dir == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot open maildir directory path: %s: %s"), - cls->folder_path, g_strerror (errno)); - g_free(cur); - return -1; - } - - mds->priv->load_map = g_hash_table_new(g_str_hash, g_str_equal); - pool = e_mempool_new(1024, 512, E_MEMPOOL_ALIGN_BYTE); - - while ( (d = readdir(dir)) ) { - if (d->d_name[0] == '.') - continue; - - /* map the filename -> uid */ - uid = strchr(d->d_name, ':'); - if (uid) { - int len = uid-d->d_name; - uid = e_mempool_alloc(pool, len+1); - memcpy(uid, d->d_name, len); - uid[len] = 0; - g_hash_table_insert(mds->priv->load_map, uid, e_mempool_strdup(pool, d->d_name)); - } else { - uid = e_mempool_strdup(pool, d->d_name); - g_hash_table_insert(mds->priv->load_map, uid, uid); - } - } - closedir(dir); - g_free(cur); - - ret = ((CamelLocalSummaryClass *) parent_class)->load(cls, forceindex, ex); - - g_hash_table_destroy(mds->priv->load_map); - mds->priv->load_map = NULL; - e_mempool_destroy(pool); - - return ret; -} - -static int camel_maildir_summary_add(CamelLocalSummary *cls, const char *name, int forceindex) -{ - CamelMaildirSummary *maildirs = (CamelMaildirSummary *)cls; - char *filename = g_strdup_printf("%s/cur/%s", cls->folder_path, name); - int fd; - CamelMimeParser *mp; - - d(printf("summarising: %s\n", name)); - - fd = open(filename, O_RDONLY); - if (fd == -1) { - g_warning ("Cannot summarise/index: %s: %s", filename, strerror (errno)); - g_free(filename); - return -1; - } - mp = camel_mime_parser_new(); - camel_mime_parser_scan_from(mp, FALSE); - camel_mime_parser_init_with_fd(mp, fd); - if (cls->index && (forceindex || !camel_index_has_name(cls->index, name))) { - d(printf("forcing indexing of message content\n")); - camel_folder_summary_set_index((CamelFolderSummary *)maildirs, cls->index); - } else { - camel_folder_summary_set_index((CamelFolderSummary *)maildirs, NULL); - } - maildirs->priv->current_file = (char *)name; - camel_folder_summary_add_from_parser((CamelFolderSummary *)maildirs, mp); - camel_object_unref((CamelObject *)mp); - maildirs->priv->current_file = NULL; - camel_folder_summary_set_index((CamelFolderSummary *)maildirs, NULL); - g_free(filename); - return 0; -} - -struct _remove_data { - CamelLocalSummary *cls; - CamelFolderChangeInfo *changes; -}; - -static void -remove_summary(char *key, CamelMessageInfo *info, struct _remove_data *rd) -{ - d(printf("removing message %s from summary\n", key)); - if (rd->cls->index) - camel_index_delete_name(rd->cls->index, camel_message_info_uid(info)); - if (rd->changes) - camel_folder_change_info_remove_uid(rd->changes, key); - camel_folder_summary_remove((CamelFolderSummary *)rd->cls, info); - camel_folder_summary_info_free((CamelFolderSummary *)rd->cls, info); -} - -static int -sort_receive_cmp(const void *ap, const void *bp) -{ - const CamelMessageInfo - *a = *((CamelMessageInfo **)ap), - *b = *((CamelMessageInfo **)bp); - - if (a->date_received < b->date_received) - return -1; - else if (a->date_received > b->date_received) - return 1; - - return 0; -} - -static int -maildir_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, CamelException *ex) -{ - DIR *dir; - struct dirent *d; - char *p; - CamelMessageInfo *info; - CamelMaildirMessageInfo *mdi; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - GHashTable *left; - int i, count, total; - int forceindex; - char *new, *cur; - char *uid; - struct _remove_data rd = { cls, changes }; - - new = g_strdup_printf("%s/new", cls->folder_path); - cur = g_strdup_printf("%s/cur", cls->folder_path); - - d(printf("checking summary ...\n")); - - camel_operation_start(NULL, _("Checking folder consistency")); - - /* scan the directory, check for mail files not in the index, or index entries that - no longer exist */ - dir = opendir(cur); - if (dir == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot open maildir directory path: %s: %s"), - cls->folder_path, g_strerror (errno)); - g_free(cur); - g_free(new); - camel_operation_end(NULL); - return -1; - } - - /* keeps track of all uid's that have not been processed */ - left = g_hash_table_new(g_str_hash, g_str_equal); - count = camel_folder_summary_count((CamelFolderSummary *)cls); - forceindex = count == 0; - for (i=0;id_name; - if (p[0] == '.') - continue; - - /* map the filename -> uid */ - uid = strchr(d->d_name, ':'); - if (uid) - uid = g_strndup(d->d_name, uid-d->d_name); - else - uid = g_strdup(d->d_name); - - info = g_hash_table_lookup(left, uid); - if (info) { - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); - g_hash_table_remove(left, uid); - } - - info = camel_folder_summary_uid((CamelFolderSummary *)cls, uid); - if (info == NULL) { - /* must be a message incorporated by another client, this is not a 'recent' uid */ - if (camel_maildir_summary_add(cls, d->d_name, forceindex) == 0) - if (changes) - camel_folder_change_info_add_uid(changes, uid); - } else { - const char *filename; - - if (cls->index && (!camel_index_has_name(cls->index, uid))) { - /* message_info_new will handle duplicates */ - camel_maildir_summary_add(cls, d->d_name, forceindex); - } - - mdi = (CamelMaildirMessageInfo *)info; - filename = camel_maildir_info_filename(mdi); - /* TODO: only store the extension in the mdi->filename struct, not the whole lot */ - if (filename == NULL || strcmp(filename, d->d_name) != 0) { -#ifdef DOESTRV -#warning "cannot modify the estrv after its been setup, for mt-safe code" - CAMEL_SUMMARY_LOCK(s, summary_lock); - /* need to update the summary hash ref */ - g_hash_table_remove(s->messages_uid, camel_message_info_uid(info)); - info->strings = e_strv_set_ref(info->strings, CAMEL_MAILDIR_INFO_FILENAME, d->d_name); - info->strings = e_strv_pack(info->strings); - g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info); - CAMEL_SUMMARY_UNLOCK(s, summary_lock); -#else -# ifdef DOEPOOLV - info->strings = e_poolv_set(info->strings, CAMEL_MAILDIR_INFO_FILENAME, d->d_name, FALSE); -# else - g_free(mdi->filename); - mdi->filename = g_strdup(d->d_name); -# endif -#endif - } - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); - } - g_free(uid); - } - closedir(dir); - g_hash_table_foreach(left, (GHFunc)remove_summary, &rd); - g_hash_table_destroy(left); - - camel_operation_end(NULL); - - camel_operation_start(NULL, _("Checking for new messages")); - - /* now, scan new for new messages, and copy them to cur, and so forth */ - dir = opendir(new); - if (dir != NULL) { - total = 0; - count = 0; - while ( (d = readdir(dir)) ) - total++; - rewinddir(dir); - - while ( (d = readdir(dir)) ) { - char *name, *newname, *destname, *destfilename; - char *src, *dest; - int pc = count * 100 / total; - - camel_operation_progress(NULL, pc); - count++; - - name = d->d_name; - if (name[0] == '.') - continue; - - /* already in summary? shouldn't happen, but just incase ... */ - if ((info = camel_folder_summary_uid((CamelFolderSummary *)cls, name))) { - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); - newname = destname = camel_folder_summary_next_uid_string(s); - } else { - newname = NULL; - destname = name; - } - - /* copy this to the destination folder, use 'standard' semantics for maildir info field */ - src = g_strdup_printf("%s/%s", new, name); - destfilename = g_strdup_printf("%s:2,", destname); - dest = g_strdup_printf("%s/%s", cur, destfilename); - - /* FIXME: This should probably use link/unlink */ - - if (rename(src, dest) == 0) { - camel_maildir_summary_add(cls, destfilename, forceindex); - if (changes) { - camel_folder_change_info_add_uid(changes, destname); - camel_folder_change_info_recent_uid(changes, destname); - } - } else { - /* else? we should probably care about failures, but wont */ - g_warning("Failed to move new maildir message %s to cur %s", src, dest); - } - - /* c strings are painful to work with ... */ - g_free(destfilename); - g_free(newname); - g_free(src); - g_free(dest); - } - camel_operation_end(NULL); - } - closedir(dir); - - g_free(new); - g_free(cur); - - /* sort the summary based on receive time, since the directory order is not useful */ - CAMEL_SUMMARY_LOCK(s, summary_lock); - qsort(s->messages->pdata, s->messages->len, sizeof(CamelMessageInfo *), sort_receive_cmp); - CAMEL_SUMMARY_UNLOCK(s, summary_lock); - - return 0; -} - -/* sync the summary with the ondisk files. */ -static int -maildir_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changes, CamelException *ex) -{ - int count, i; - CamelMessageInfo *info; - CamelMaildirMessageInfo *mdi; -#ifdef DOESTRV - CamelFolderSummary *s = (CamelFolderSummary *)cls; -#endif - char *name; - struct stat st; - - d(printf("summary_sync(expunge=%s)\n", expunge?"true":"false")); - - if (camel_local_summary_check(cls, changes, ex) == -1) - return -1; - - camel_operation_start(NULL, _("Storing folder")); - - count = camel_folder_summary_count((CamelFolderSummary *)cls); - for (i=count-1;i>=0;i--) { - camel_operation_progress(NULL, (count-i)*100/count); - - info = camel_folder_summary_index((CamelFolderSummary *)cls, i); - mdi = (CamelMaildirMessageInfo *)info; - if (info && (info->flags & CAMEL_MESSAGE_DELETED) && expunge) { - name = g_strdup_printf("%s/cur/%s", cls->folder_path, camel_maildir_info_filename(mdi)); - d(printf("deleting %s\n", name)); - if (unlink(name) == 0 || errno==ENOENT) { - - /* FIXME: put this in folder_summary::remove()? */ - if (cls->index) - camel_index_delete_name(cls->index, camel_message_info_uid(info)); - - camel_folder_change_info_remove_uid(changes, camel_message_info_uid(info)); - camel_folder_summary_remove((CamelFolderSummary *)cls, info); - } - g_free(name); - } else if (info && (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) { - char *newname = camel_maildir_summary_info_to_name(info); - char *dest; - - /* do we care about additional metainfo stored inside the message? */ - /* probably should all go in the filename? */ - - /* have our flags/ i.e. name changed? */ - if (strcmp(newname, camel_maildir_info_filename(mdi))) { - name = g_strdup_printf("%s/cur/%s", cls->folder_path, camel_maildir_info_filename(mdi)); - dest = g_strdup_printf("%s/cur/%s", cls->folder_path, newname); - rename(name, dest); - if (stat(dest, &st) == -1) { - /* we'll assume it didn't work, but dont change anything else */ - g_free(newname); - } else { - /* TODO: If this is made mt-safe, then this code could be a problem, since - the estrv is being modified. - Sigh, this may mean the maildir name has to be cached another way */ -#ifdef DOESTRV -#warning "cannot modify the estrv after its been setup, for mt-safe code" - CAMEL_SUMMARY_LOCK(s, summary_lock); - /* need to update the summary hash ref */ - g_hash_table_remove(s->messages_uid, camel_message_info_uid(info)); - info->strings = e_strv_set_ref_free(info->strings, CAMEL_MAILDIR_INFO_FILENAME, newname); - info->strings = e_strv_pack(info->strings); - g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info); - CAMEL_SUMMARY_UNLOCK(s, summary_lock); -#else -# ifdef DOEPOOLV - info->strings = e_poolv_set(info->strings, CAMEL_MAILDIR_INFO_FILENAME, newname, TRUE); -# else - g_free(mdi->filename); - mdi->filename = newname; -# endif -#endif - } - g_free(name); - g_free(dest); - } else { - g_free(newname); - } - - /* strip FOLDER_MESSAGE_FLAGED, etc */ - info->flags &= 0xffff; - } - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); - } - - camel_operation_end(NULL); - - return ((CamelLocalSummaryClass *)parent_class)->sync(cls, expunge, changes, ex); -} - diff --git a/camel/providers/local/camel-maildir-summary.h b/camel/providers/local/camel-maildir-summary.h deleted file mode 100644 index 0cae785c6c..0000000000 --- a/camel/providers/local/camel-maildir-summary.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Not Zed - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_MAILDIR_SUMMARY_H -#define _CAMEL_MAILDIR_SUMMARY_H - -#include "camel-local-summary.h" -#include -#include -#include - -#define CAMEL_MAILDIR_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_maildir_summary_get_type (), CamelMaildirSummary) -#define CAMEL_MAILDIR_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_maildir_summary_get_type (), CamelMaildirSummaryClass) -#define CAMEL_IS_MAILDIR_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_maildir_summary_get_type ()) - -typedef struct _CamelMaildirSummary CamelMaildirSummary; -typedef struct _CamelMaildirSummaryClass CamelMaildirSummaryClass; - -typedef struct _CamelMaildirMessageContentInfo { - CamelMessageContentInfo info; -} CamelMaildirMessageContentInfo; - -#if defined (DOEPOOLV) || defined (DOESTRV) -enum { - CAMEL_MAILDIR_INFO_FILENAME = CAMEL_MESSAGE_INFO_LAST, - CAMEL_MAILDIR_INFO_LAST, -}; -#endif - -typedef struct _CamelMaildirMessageInfo { - CamelMessageInfo info; - -#if !defined (DOEPOOLV) && !defined (DOESTRV) - char *filename; /* maildir has this annoying status shit on the end of the filename, use this to get the real message id */ -#endif -} CamelMaildirMessageInfo; - -struct _CamelMaildirSummary { - CamelLocalSummary parent; - struct _CamelMaildirSummaryPrivate *priv; -}; - -struct _CamelMaildirSummaryClass { - CamelLocalSummaryClass parent_class; - - /* virtual methods */ - - /* signals */ -}; - -CamelType camel_maildir_summary_get_type (void); -CamelMaildirSummary *camel_maildir_summary_new (const char *filename, const char *maildirdir, CamelIndex *index); - -/* convert some info->flags to/from the messageinfo */ -char *camel_maildir_summary_info_to_name(const CamelMessageInfo *info); -int camel_maildir_summary_name_to_info(CamelMessageInfo *info, const char *name); - -#if defined (DOEPOOLV) || defined (DOESTRV) -#define camel_maildir_info_filename(x) camel_message_info_string((const CamelMessageInfo *)(x), CAMEL_MAILDIR_INFO_FILENAME) -#define camel_maildir_info_set_filename(x, s) camel_message_info_set_string((CamelMessageInfo *)(x), CAMEL_MAILDIR_INFO_FILENAME, s) -#else -#define camel_maildir_info_filename(x) (((CamelMaildirMessageInfo *)x)->filename) -#define camel_maildir_info_set_filename(x, s) (g_free(((CamelMaildirMessageInfo *)x)->filename),((CamelMaildirMessageInfo *)x)->filename = s) -#endif - -#endif /* ! _CAMEL_MAILDIR_SUMMARY_H */ - diff --git a/camel/providers/local/camel-mbox-folder.c b/camel/providers/local/camel-mbox-folder.c deleted file mode 100644 index 9c3a7036f2..0000000000 --- a/camel/providers/local/camel-mbox-folder.c +++ /dev/null @@ -1,549 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Authors: Michael Zucchi - * Jeffrey Stedfast - * - * Copyright (C) 1999, 2003 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "camel-mbox-folder.h" -#include "camel-mbox-store.h" -#include "camel-stream-fs.h" -#include "camel-mbox-summary.h" -#include "camel-data-wrapper.h" -#include "camel-mime-message.h" -#include "camel-stream-filter.h" -#include "camel-mime-filter-from.h" -#include "camel-exception.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -static CamelLocalFolderClass *parent_class = NULL; - -/* Returns the class for a CamelMboxFolder */ -#define CMBOXF_CLASS(so) CAMEL_MBOX_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMBOXS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -char *camel_mbox_folder_get_full_path (const char *toplevel_dir, const char *full_name); -char *camel_mbox_folder_get_meta_path (const char *toplevel_dir, const char *full_name, const char *ext); - -static int mbox_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex); -static void mbox_unlock(CamelLocalFolder *lf); - -#ifdef STATUS_PINE -static void mbox_set_message_flags(CamelFolder *folder, const char *uid, guint32 flags, guint32 set); -#endif - -static void mbox_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value); -static void mbox_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value); - -static void mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info, char **appended_uid, CamelException *ex); -static CamelMimeMessage *mbox_get_message(CamelFolder *folder, const gchar * uid, CamelException *ex); -static CamelLocalSummary *mbox_create_summary(const char *path, const char *folder, CamelIndex *index); - -static void mbox_finalise(CamelObject * object); - -static void -camel_mbox_folder_class_init(CamelMboxFolderClass * camel_mbox_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_mbox_folder_class); - CamelLocalFolderClass *lclass = (CamelLocalFolderClass *)camel_mbox_folder_class; - - parent_class = (CamelLocalFolderClass *)camel_type_get_global_classfuncs(camel_local_folder_get_type()); - - /* virtual method definition */ - - /* virtual method overload */ - camel_folder_class->append_message = mbox_append_message; - camel_folder_class->get_message = mbox_get_message; - -#ifdef STATUS_PINE - camel_folder_class->set_message_flags = mbox_set_message_flags; -#endif - camel_folder_class->set_message_user_flag = mbox_set_message_user_flag; - camel_folder_class->set_message_user_tag = mbox_set_message_user_tag; - - lclass->get_full_path = camel_mbox_folder_get_full_path; - lclass->get_meta_path = camel_mbox_folder_get_meta_path; - lclass->create_summary = mbox_create_summary; - lclass->lock = mbox_lock; - lclass->unlock = mbox_unlock; -} - -static void -mbox_init(gpointer object, gpointer klass) -{ - /*CamelFolder *folder = object;*/ - CamelMboxFolder *mbox_folder = object; - - mbox_folder->lockfd = -1; -} - -static void -mbox_finalise(CamelObject * object) -{ - CamelMboxFolder *mbox_folder = (CamelMboxFolder *)object; - - g_assert(mbox_folder->lockfd == -1); -} - -CamelType camel_mbox_folder_get_type(void) -{ - static CamelType camel_mbox_folder_type = CAMEL_INVALID_TYPE; - - if (camel_mbox_folder_type == CAMEL_INVALID_TYPE) { - camel_mbox_folder_type = camel_type_register(CAMEL_LOCAL_FOLDER_TYPE, "CamelMboxFolder", - sizeof(CamelMboxFolder), - sizeof(CamelMboxFolderClass), - (CamelObjectClassInitFunc) camel_mbox_folder_class_init, - NULL, - (CamelObjectInitFunc) mbox_init, - (CamelObjectFinalizeFunc) mbox_finalise); - } - - return camel_mbox_folder_type; -} - -CamelFolder * -camel_mbox_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) -{ - CamelFolder *folder; - - d(printf("Creating mbox folder: %s in %s\n", full_name, camel_local_store_get_toplevel_dir((CamelLocalStore *)parent_store))); - - folder = (CamelFolder *)camel_object_new(CAMEL_MBOX_FOLDER_TYPE); - folder = (CamelFolder *)camel_local_folder_construct((CamelLocalFolder *)folder, - parent_store, full_name, flags, ex); - - return folder; -} - -char * -camel_mbox_folder_get_full_path (const char *toplevel_dir, const char *full_name) -{ - const char *inptr = full_name; - int subdirs = 0; - char *path, *p; - - while (*inptr != '\0') { - if (*inptr == '/') - subdirs++; - inptr++; - } - - path = g_malloc (strlen (toplevel_dir) + (inptr - full_name) + (4 * subdirs) + 1); - p = g_stpcpy (path, toplevel_dir); - - inptr = full_name; - while (*inptr != '\0') { - while (*inptr != '/' && *inptr != '\0') - *p++ = *inptr++; - - if (*inptr == '/') { - p = g_stpcpy (p, ".sbd/"); - inptr++; - - /* strip extranaeous '/'s */ - while (*inptr == '/') - inptr++; - } - } - - *p = '\0'; - - return path; -} - -char * -camel_mbox_folder_get_meta_path (const char *toplevel_dir, const char *full_name, const char *ext) -{ -/*#define USE_HIDDEN_META_FILES*/ -#ifdef USE_HIDDEN_META_FILES - char *name, *slash; - - name = g_alloca (strlen (full_name) + strlen (ext) + 2); - if ((slash = strrchr (full_name, '/'))) - sprintf (name, "%.*s.%s%s", slash - full_name + 1, full_name, slash + 1, ext); - else - sprintf (name, ".%s%s", full_name, ext); - - return camel_mbox_folder_get_full_path (toplevel_dir, name); -#else - char *full_path, *path; - - full_path = camel_mbox_folder_get_full_path (toplevel_dir, full_name); - path = g_strdup_printf ("%s%s", full_path, ext); - g_free (full_path); - - return path; -#endif -} - -static CamelLocalSummary *mbox_create_summary(const char *path, const char *folder, CamelIndex *index) -{ - return (CamelLocalSummary *)camel_mbox_summary_new(path, folder, index); -} - -static int mbox_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex) -{ - CamelMboxFolder *mf = (CamelMboxFolder *)lf; - - /* make sure we have matching unlocks for locks, camel-local-folder class should enforce this */ - g_assert(mf->lockfd == -1); - - mf->lockfd = open(lf->folder_path, O_RDWR, 0); - if (mf->lockfd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder lock on %s: %s"), - lf->folder_path, g_strerror (errno)); - return -1; - } - - if (camel_lock_folder(lf->folder_path, mf->lockfd, type, ex) == -1) { - close(mf->lockfd); - mf->lockfd = -1; - return -1; - } - - return 0; -} - -static void mbox_unlock(CamelLocalFolder *lf) -{ - CamelMboxFolder *mf = (CamelMboxFolder *)lf; - - g_assert(mf->lockfd != -1); - camel_unlock_folder(lf->folder_path, mf->lockfd); - close(mf->lockfd); - mf->lockfd = -1; -} - -static void -mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info, char **appended_uid, CamelException *ex) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *output_stream = NULL, *filter_stream = NULL; - CamelMimeFilter *filter_from = NULL; - CamelMboxSummary *mbs = (CamelMboxSummary *)folder->summary; - CamelMessageInfo *mi; - char *fromline = NULL; - int fd, retval; - struct stat st; -#if 0 - char *xev; -#endif - /* If we can't lock, dont do anything */ - if (camel_local_folder_lock(lf, CAMEL_LOCK_WRITE, ex) == -1) - return; - - d(printf("Appending message\n")); - - /* first, check the summary is correct (updates folder_size too) */ - retval = camel_local_summary_check ((CamelLocalSummary *)folder->summary, lf->changes, ex); - if (retval == -1) - goto fail; - - /* add it to the summary/assign the uid, etc */ - mi = camel_local_summary_add((CamelLocalSummary *)folder->summary, message, info, lf->changes, ex); - if (mi == NULL) - goto fail; - - d(printf("Appending message: uid is %s\n", camel_message_info_uid(mi))); - - output_stream = camel_stream_fs_new_with_name(lf->folder_path, O_WRONLY|O_APPEND, 0600); - if (output_stream == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot open mailbox: %s: %s\n"), - lf->folder_path, g_strerror (errno)); - goto fail; - } - - /* and we need to set the frompos/XEV explicitly */ - ((CamelMboxMessageInfo *)mi)->frompos = mbs->folder_size; -#if 0 - xev = camel_local_summary_encode_x_evolution((CamelLocalSummary *)folder->summary, mi); - if (xev) { - /* the x-ev header should match the 'current' flags, no problem, so store as much */ - camel_medium_set_header((CamelMedium *)message, "X-Evolution", xev); - mi->flags &= ~ CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_FLAGGED; - g_free(xev); - } -#endif - - /* we must write this to the non-filtered stream ... */ - fromline = camel_mime_message_build_mbox_from(message); - if (camel_stream_write(output_stream, fromline, strlen(fromline)) == -1) - goto fail_write; - - /* and write the content to the filtering stream, that translates '\nFrom' into '\n>From' */ - filter_stream = (CamelStream *) camel_stream_filter_new_with_stream(output_stream); - filter_from = (CamelMimeFilter *) camel_mime_filter_from_new(); - camel_stream_filter_add((CamelStreamFilter *) filter_stream, filter_from); - if (camel_data_wrapper_write_to_stream((CamelDataWrapper *)message, filter_stream) == -1 - || camel_stream_write(filter_stream, "\n", 1) == -1 - || camel_stream_close(filter_stream) == -1) - goto fail_write; - - /* filter stream ref's the output stream itself, so we need to unref it too */ - camel_object_unref((CamelObject *)filter_from); - camel_object_unref((CamelObject *)filter_stream); - camel_object_unref((CamelObject *)output_stream); - g_free(fromline); - - /* now we 'fudge' the summary to tell it its uptodate, because its idea of uptodate has just changed */ - /* the stat really shouldn't fail, we just wrote to it */ - if (stat(lf->folder_path, &st) == 0) { - mbs->folder_size = st.st_size; - ((CamelFolderSummary *)mbs)->time = st.st_mtime; - } - - /* unlock as soon as we can */ - camel_local_folder_unlock(lf); - - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } - - if (appended_uid) - *appended_uid = g_strdup(camel_message_info_uid(mi)); - - return; - -fail_write: - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Mail append cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to mbox file: %s: %s"), - lf->folder_path, g_strerror (errno)); - - if (filter_stream) - camel_object_unref(CAMEL_OBJECT(filter_stream)); - - if (output_stream) - camel_object_unref(CAMEL_OBJECT(output_stream)); - - if (filter_from) - camel_object_unref(CAMEL_OBJECT(filter_from)); - - g_free(fromline); - - /* reset the file to original size */ - fd = open(lf->folder_path, O_WRONLY, 0600); - if (fd != -1) { - ftruncate(fd, mbs->folder_size); - close(fd); - } - - /* remove the summary info so we are not out-of-sync with the mbox */ - camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (mbs), camel_message_info_uid (mi)); - - /* and tell the summary its uptodate */ - if (stat(lf->folder_path, &st) == 0) { - mbs->folder_size = st.st_size; - ((CamelFolderSummary *)mbs)->time = st.st_mtime; - } - -fail: - /* make sure we unlock the folder - before we start triggering events into appland */ - camel_local_folder_unlock(lf); - - /* cascade the changes through, anyway, if there are any outstanding */ - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } -} - -static CamelMimeMessage * -mbox_get_message(CamelFolder *folder, const gchar * uid, CamelException *ex) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelMimeMessage *message = NULL; - CamelMboxMessageInfo *info; - CamelMimeParser *parser = NULL; - int fd, retval; - int retried = FALSE; - off_t frompos; - - d(printf("Getting message %s\n", uid)); - - /* lock the folder first, burn if we can't, need write lock for summary check */ - if (camel_local_folder_lock(lf, CAMEL_LOCK_WRITE, ex) == -1) - return NULL; - - /* check for new messages always */ - if (camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex) == -1) { - camel_local_folder_unlock(lf); - return NULL; - } - -retry: - /* get the message summary info */ - info = (CamelMboxMessageInfo *) camel_folder_summary_uid(folder->summary, uid); - - if (info == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s\n %s"), uid, _("No such message")); - goto fail; - } - - /* no frompos, its an error in the library (and we can't do anything with it) */ - g_assert(info->frompos != -1); - - frompos = info->frompos; - camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)info); - - /* we use an fd instead of a normal stream here - the reason is subtle, camel_mime_part will cache - the whole message in memory if the stream is non-seekable (which it is when built from a parser - with no stream). This means we dont have to lock the mbox for the life of the message, but only - while it is being created. */ - - fd = open(lf->folder_path, O_RDONLY); - if (fd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s from folder %s\n %s"), - uid, lf->folder_path, g_strerror (errno)); - goto fail; - } - - /* we use a parser to verify the message is correct, and in the correct position */ - parser = camel_mime_parser_new(); - camel_mime_parser_init_with_fd(parser, fd); - camel_mime_parser_scan_from(parser, TRUE); - - camel_mime_parser_seek(parser, frompos, SEEK_SET); - if (camel_mime_parser_step(parser, NULL, NULL) != CAMEL_MIME_PARSER_STATE_FROM - || camel_mime_parser_tell_start_from(parser) != frompos) { - - g_warning("Summary doesn't match the folder contents! eek!\n" - " expecting offset %ld got %ld, state = %d", (long int)frompos, - (long int)camel_mime_parser_tell_start_from(parser), - camel_mime_parser_state(parser)); - - camel_object_unref((CamelObject *)parser); - parser = NULL; - - if (!retried) { - retried = TRUE; - camel_local_summary_check_force((CamelLocalSummary *)folder->summary); - retval = camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex); - if (retval != -1) - goto retry; - } - - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s from folder %s\n %s"), uid, lf->folder_path, - _("The folder appears to be irrecoverably corrupted.")); - goto fail; - } - - message = camel_mime_message_new(); - if (camel_mime_part_construct_from_parser((CamelMimePart *)message, parser) == -1) { - camel_exception_setv(ex, errno==EINTR?CAMEL_EXCEPTION_USER_CANCEL:CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s from folder %s\n %s"), uid, lf->folder_path, - _("Message construction failed: Corrupt mailbox?")); - camel_object_unref((CamelObject *)message); - message = NULL; - goto fail; - } - - camel_medium_remove_header((CamelMedium *)message, "X-Evolution"); -fail: - /* and unlock now we're finished with it */ - camel_local_folder_unlock(lf); - - if (parser) - camel_object_unref((CamelObject *)parser); - - /* use the opportunity to notify of changes (particularly if we had a rebuild) */ - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } - - return message; -} - -#ifdef STATUS_PINE -static void -mbox_set_message_flags(CamelFolder *folder, const char *uid, guint32 flags, guint32 set) -{ - /* Basically, if anything could change the Status line, presume it does */ - if (((CamelMboxSummary *)folder->summary)->xstatus - && (flags & (CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_FLAGGED|CAMEL_MESSAGE_ANSWERED|CAMEL_MESSAGE_DELETED))) { - flags |= CAMEL_MESSAGE_FOLDER_XEVCHANGE|CAMEL_MESSAGE_FOLDER_FLAGGED; - set |= CAMEL_MESSAGE_FOLDER_XEVCHANGE|CAMEL_MESSAGE_FOLDER_FLAGGED; - } - - ((CamelFolderClass *)parent_class)->set_message_flags(folder, uid, flags, set); -} -#endif - -static void -mbox_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value) -{ - CamelMessageInfo *info; - - g_return_if_fail(folder->summary != NULL); - - info = camel_folder_summary_uid(folder->summary, uid); - if (info == NULL) - return; - - if (camel_flag_set(&info->user_flags, name, value)) { - info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED|CAMEL_MESSAGE_FOLDER_XEVCHANGE; - camel_folder_summary_touch(folder->summary); - camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid); - } - camel_folder_summary_info_free(folder->summary, info); -} - -static void -mbox_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value) -{ - CamelMessageInfo *info; - - g_return_if_fail(folder->summary != NULL); - - info = camel_folder_summary_uid(folder->summary, uid); - if (info == NULL) - return; - - if (camel_tag_set(&info->user_tags, name, value)) { - info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED|CAMEL_MESSAGE_FOLDER_XEVCHANGE; - camel_folder_summary_touch(folder->summary); - camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid); - } - camel_folder_summary_info_free(folder->summary, info); -} diff --git a/camel/providers/local/camel-mbox-folder.h b/camel/providers/local/camel-mbox-folder.h deleted file mode 100644 index aa0b67201f..0000000000 --- a/camel/providers/local/camel-mbox-folder.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi - * - * Copyright (C) 1999 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_MBOX_FOLDER_H -#define CAMEL_MBOX_FOLDER_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-local-folder.h" -#include "camel-mbox-summary.h" - -#define CAMEL_MBOX_FOLDER_TYPE (camel_mbox_folder_get_type ()) -#define CAMEL_MBOX_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MBOX_FOLDER_TYPE, CamelMboxFolder)) -#define CAMEL_MBOX_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MBOX_FOLDER_TYPE, CamelMboxFolderClass)) -#define CAMEL_IS_MBOX_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_MBOX_FOLDER_TYPE)) - -typedef struct { - CamelLocalFolder parent_object; - - int lockfd; /* for when we have a lock on the folder */ -} CamelMboxFolder; - -typedef struct { - CamelLocalFolderClass parent_class; - - /* Virtual methods */ - -} CamelMboxFolderClass; - -/* public methods */ -/* flags are taken from CAMEL_STORE_FOLDER_* flags */ -CamelFolder *camel_mbox_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_mbox_folder_get_type(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_MBOX_FOLDER_H */ diff --git a/camel/providers/local/camel-mbox-store.c b/camel/providers/local/camel-mbox-store.c deleted file mode 100644 index ffce19171f..0000000000 --- a/camel/providers/local/camel-mbox-store.c +++ /dev/null @@ -1,753 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi - * - * Copyright (C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "camel-mbox-store.h" -#include "camel-mbox-folder.h" -#include "camel-file-utils.h" -#include "camel-text-index.h" -#include "camel-exception.h" -#include "camel-url.h" - -#define d(x) - -static CamelLocalStoreClass *parent_class = NULL; - -/* Returns the class for a CamelMboxStore */ -#define CMBOXS_CLASS(so) CAMEL_MBOX_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMBOXF_CLASS(so) CAMEL_MBOX_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -extern char *camel_mbox_folder_get_full_path (const char *toplevel_dir, const char *full_name); -extern char *camel_mbox_folder_get_meta_path (const char *toplevel_dir, const char *full_name, const char *ext); - -static CamelFolder *get_folder(CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex); -static void delete_folder(CamelStore *store, const char *folder_name, CamelException *ex); -static void rename_folder (CamelStore *store, const char *old, const char *new, CamelException *ex); -static CamelFolderInfo *create_folder (CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex); -static CamelFolderInfo *get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); - -static void -camel_mbox_store_class_init (CamelMboxStoreClass *camel_mbox_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_mbox_store_class); - - parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type()); - - /* virtual method overload */ - camel_store_class->get_folder = get_folder; - camel_store_class->delete_folder = delete_folder; - camel_store_class->rename_folder = rename_folder; - camel_store_class->create_folder = create_folder; - - camel_store_class->get_folder_info = get_folder_info; - camel_store_class->free_folder_info = camel_store_free_folder_info_full; -} - -CamelType -camel_mbox_store_get_type (void) -{ - static CamelType camel_mbox_store_type = CAMEL_INVALID_TYPE; - - if (camel_mbox_store_type == CAMEL_INVALID_TYPE) { - camel_mbox_store_type = camel_type_register (CAMEL_LOCAL_STORE_TYPE, "CamelMboxStore", - sizeof (CamelMboxStore), - sizeof (CamelMboxStoreClass), - (CamelObjectClassInitFunc) camel_mbox_store_class_init, - NULL, - NULL, - NULL); - } - - return camel_mbox_store_type; -} - -static char * -mbox_folder_name_to_path (CamelStore *store, const char *folder_name) -{ - const char *toplevel_dir = CAMEL_LOCAL_STORE (store)->toplevel_dir; - - return camel_mbox_folder_get_full_path (toplevel_dir, folder_name); -} - -static char * -mbox_folder_name_to_meta_path (CamelStore *store, const char *folder_name, const char *ext) -{ - const char *toplevel_dir = CAMEL_LOCAL_STORE (store)->toplevel_dir; - - return camel_mbox_folder_get_meta_path (toplevel_dir, folder_name, ext); -} - -static char *extensions[] = { - ".msf", ".ev-summary", ".ibex.index", ".ibex.index.data", ".cmeta" -}; - -static gboolean -ignore_file (const char *filename, gboolean sbd) -{ - int flen, len, i; - - flen = strlen (filename); - for (i = 0; i < (sizeof (extensions) / sizeof (extensions[0])); i++) { - len = strlen (extensions[i]); - if (len < flen && !strcmp (filename + flen - len, extensions[i])) - return TRUE; - } - - if (sbd && flen > 4 && !strcmp (filename + flen - 4, ".sbd")) - return TRUE; - - return FALSE; -} - -static CamelFolder * -get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) -{ - struct stat st; - char *name; - - if (!((CamelStoreClass *) parent_class)->get_folder (store, folder_name, flags, ex)) - return NULL; - - name = mbox_folder_name_to_path (store, folder_name); - - if (stat (name, &st) == -1) { - char *dirname; - int fd; - - if (errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open file `%s':\n%s"), - name, g_strerror (errno)); - g_free (name); - return NULL; - } - - if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Folder `%s' does not exist."), - folder_name); - g_free (name); - return NULL; - } - - dirname = g_path_get_dirname (name); - if (camel_mkdir (dirname, 0777) == -1 && errno != EEXIST) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Could not create directory `%s':\n%s"), - dirname, g_strerror (errno)); - g_free (dirname); - g_free (name); - return NULL; - } - - g_free (dirname); - - fd = open (name, O_WRONLY | O_CREAT | O_APPEND, 0666); - if (fd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create file `%s':\n%s"), - name, g_strerror (errno)); - g_free (name); - return NULL; - } - - g_free (name); - close (fd); - } else if (!S_ISREG (st.st_mode)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("`%s' is not a regular file."), - name); - g_free (name); - return NULL; - } else - g_free (name); - - return camel_mbox_folder_new (store, folder_name, flags, ex); -} - -static void -delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) -{ - CamelFolderInfo *fi; - CamelException lex; - CamelFolder *lf; - char *name, *path; - struct stat st; - - name = mbox_folder_name_to_path (store, folder_name); - path = g_strdup_printf ("%s.sbd", name); - - if (rmdir (path) == -1 && errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s':\n%s"), - folder_name, g_strerror (errno)); - g_free (path); - g_free (name); - return; - } - - g_free (path); - - if (stat (name, &st) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s':\n%s"), - folder_name, g_strerror (errno)); - g_free (name); - return; - } - - if (!S_ISREG (st.st_mode)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("`%s' is not a regular file."), name); - g_free (name); - return; - } - - if (st.st_size != 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_NON_EMPTY, - _("Folder `%s' is not empty. Not deleted."), - folder_name); - g_free (name); - return; - } - - if (unlink (name) == -1 && errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s':\n%s"), - name, g_strerror (errno)); - g_free (name); - return; - } - - /* FIXME: we have to do our own meta cleanup here rather than - * calling our parent class' delete_folder() method since our - * naming convention is different. Need to find a way for - * CamelLocalStore to be able to construct the folder & meta - * paths itself */ - path = mbox_folder_name_to_meta_path (store, folder_name, ".ev-summary"); - if (unlink (path) == -1 && errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder summary file `%s': %s"), - path, g_strerror (errno)); - g_free (path); - g_free (name); - return; - } - - g_free (path); - - path = mbox_folder_name_to_meta_path (store, folder_name, ".ibex"); - if (camel_text_index_remove (path) == -1 && errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder index file `%s': %s"), - path, g_strerror (errno)); - g_free (path); - g_free (name); - return; - } - - g_free (path); - - camel_exception_init (&lex); - if ((lf = camel_store_get_folder (store, folder_name, 0, &lex))) { - camel_object_get (lf, NULL, CAMEL_OBJECT_STATE_FILE, &path, NULL); - camel_object_set (lf, NULL, CAMEL_OBJECT_STATE_FILE, NULL, NULL); - camel_object_unref (lf); - } else { - camel_exception_clear (&lex); - } - - if (path == NULL) - path = mbox_folder_name_to_meta_path (store, folder_name, ".cmeta"); - - if (unlink (path) == -1 && errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder meta file `%s': %s"), - path, g_strerror (errno)); - - g_free (path); - g_free (name); - return; - } - - g_free (path); - g_free (name); - - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = g_strdup (folder_name); - fi->name = g_path_get_basename (folder_name); - fi->url = g_strdup_printf ("mbox:%s#%s", ((CamelService *) store)->url->path, folder_name); - fi->unread_message_count = -1; - camel_folder_info_build_path (fi, '/'); - - camel_object_trigger_event (store, "folder_deleted", fi); - - camel_folder_info_free (fi); -} - -static CamelFolderInfo * -create_folder (CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex) -{ - /* FIXME: this is almost an exact copy of CamelLocalStore::create_folder() except that we use - * different path schemes... need to find a way to share parent's code? */ - const char *toplevel_dir = ((CamelLocalStore *) store)->toplevel_dir; - CamelFolderInfo *info = NULL; - char *path, *name, *dir; - CamelFolder *folder; - struct stat st; - - if (toplevel_dir[0] != '/') { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store root %s is not an absolute path"), toplevel_dir); - return NULL; - } - - if (folder_name[0] == '.' || ignore_file (folder_name, TRUE)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create a folder by this name.")); - return NULL; - } - - if (parent_name && *parent_name) - name = g_strdup_printf ("%s/%s", parent_name, folder_name); - else - name = g_strdup (folder_name); - - path = mbox_folder_name_to_path (store, name); - - dir = g_path_get_dirname (path); - if (camel_mkdir (dir, 0777) == -1 && errno != EEXIST) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create directory `%s': %s."), - dir, g_strerror (errno)); - - g_free (path); - g_free (name); - g_free (dir); - - return NULL; - } - - g_free (dir); - - if (stat (path, &st) == 0 || errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot create folder: %s: %s"), - path, errno ? g_strerror (errno) : - _("Folder already exists")); - - g_free (path); - g_free (name); - - return NULL; - } - - g_free (path); - - folder = ((CamelStoreClass *) ((CamelObject *) store)->klass)->get_folder (store, name, CAMEL_STORE_FOLDER_CREATE, ex); - if (folder) { - camel_object_unref (folder); - info = ((CamelStoreClass *) ((CamelObject *) store)->klass)->get_folder_info (store, name, 0, ex); - } - - g_free (name); - - return info; -} - -static int -xrename (CamelStore *store, const char *old_name, const char *new_name, const char *ext, gboolean missingok, CamelException *ex) -{ - const char *toplevel_dir = ((CamelLocalStore *) store)->toplevel_dir; - char *oldpath, *newpath; - struct stat st; - int ret = -1; - int err = 0; - - if (ext != NULL) { - oldpath = camel_mbox_folder_get_meta_path (toplevel_dir, old_name, ext); - newpath = camel_mbox_folder_get_meta_path (toplevel_dir, new_name, ext); - } else { - oldpath = camel_mbox_folder_get_full_path (toplevel_dir, old_name); - newpath = camel_mbox_folder_get_full_path (toplevel_dir, new_name); - } - - if (stat (oldpath, &st) == -1) { - if (missingok && errno == ENOENT) { - ret = 0; - } else { - err = errno; - ret = -1; - } - } else if (S_ISDIR (st.st_mode)) { - /* use rename for dirs */ - if (rename (oldpath, newpath) == 0 || stat (newpath, &st) == 0) { - ret = 0; - } else { - err = errno; - ret = -1; - } - } else if (link (oldpath, newpath) == 0 /* and link for files */ - || (stat (newpath, &st) == 0 && st.st_nlink == 2)) { - if (unlink (oldpath) == 0) { - ret = 0; - } else { - err = errno; - unlink (newpath); - ret = -1; - } - } else { - err = errno; - ret = -1; - } - - if (ret == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not rename %s to %s: %s"), - oldpath, newpath, g_strerror (err)); - } - - g_free (oldpath); - g_free (newpath); - - return ret; -} - -static void -rename_folder (CamelStore *store, const char *old, const char *new, CamelException *ex) -{ - CamelLocalFolder *folder = NULL; - char *oldibex, *newibex; - - if (new[0] == '.' || ignore_file (new, TRUE)) { - printf ("exception: The new folder name is illegal.\n"); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("The new folder name is illegal.")); - return; - } - - /* try to rollback failures, has obvious races */ - - oldibex = mbox_folder_name_to_meta_path (store, old, ".ibex"); - newibex = mbox_folder_name_to_meta_path (store, new, ".ibex"); - - folder = camel_object_bag_get (store->folders, old); - if (folder && folder->index) { - if (camel_index_rename (folder->index, newibex) == -1) - goto ibex_failed; - } else { - /* TODO: camel_text_index_rename should find out if we have an active index itself? */ - if (camel_text_index_rename (oldibex, newibex) == -1) - goto ibex_failed; - } - - if (xrename (store, old, new, ".ev-summary", TRUE, ex)) - goto summary_failed; - - if (xrename (store, old, new, NULL, FALSE, ex)) - goto base_failed; - - g_free (oldibex); - g_free (newibex); - - if (folder) - camel_object_unref (folder); - - return; - - base_failed: - - xrename (store, new, old, ".ev-summary", TRUE, ex); - - summary_failed: - - if (folder) { - if (folder->index) - camel_index_rename (folder->index, oldibex); - } else - camel_text_index_rename (newibex, oldibex); - ibex_failed: - - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not rename '%s': %s"), - old, g_strerror (errno)); - - g_free (newibex); - g_free (oldibex); - - if (folder) - camel_object_unref (folder); -} - - -/* used to find out where we've visited already */ -struct _inode { - dev_t dnode; - ino_t inode; -}; - -static guint -inode_hash (const void *d) -{ - const struct _inode *v = d; - - return v->inode ^ v->dnode; -} - -static gboolean -inode_equal (const void *a, const void *b) -{ - const struct _inode *v1 = a, *v2 = b; - - return v1->inode == v2->inode && v1->dnode == v2->dnode; -} - -static void -inode_free (void *k, void *v, void *d) -{ - g_free (k); -} - -static CamelFolderInfo * -scan_dir (CamelStore *store, GHashTable *visited, CamelFolderInfo *parent, const char *root, - const char *name, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *folders, *tail, *fi; - GHashTable *folder_hash; - struct dirent *dent; - DIR *dir; - - tail = folders = NULL; - - if (!(dir = opendir (root))) - return NULL; - - folder_hash = g_hash_table_new (g_str_hash, g_str_equal); - - /* FIXME: it would be better if we queue'd up the recursive - * scans till the end so that we can limit the number of - * directory descriptors open at any given time... */ - - while ((dent = readdir (dir))) { - char *short_name, *full_name, *path, *ext; - CamelFolder *folder; - struct stat st; - int unread = -1; - - if (dent->d_name[0] == '.') - continue; - - if (ignore_file (dent->d_name, FALSE)) - continue; - - path = g_strdup_printf ("%s/%s", root, dent->d_name); - if (stat (path, &st) == -1) { - g_free (path); - continue; - } - - if (S_ISDIR (st.st_mode)) { - struct _inode in = { st.st_dev, st.st_ino }; - - if (g_hash_table_lookup (visited, &in)) { - g_free (path); - continue; - } - } - - short_name = g_strdup (dent->d_name); - if ((ext = strrchr (short_name, '.')) && !strcmp (ext, ".sbd")) - *ext = '\0'; - - if (name != NULL) - full_name = g_strdup_printf ("%s/%s", name, short_name); - else - full_name = g_strdup (short_name); - - if (!S_ISDIR (st.st_mode)) { - folder = camel_object_bag_get (store->folders, full_name); - if (folder) { - if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) - camel_folder_refresh_info (folder, NULL); - unread = camel_folder_get_unread_message_count (folder); - camel_object_unref (folder); - } - } - - if ((fi = g_hash_table_lookup (folder_hash, short_name)) != NULL) { - g_free (short_name); - g_free (full_name); - - if (S_ISDIR (st.st_mode)) { - fi->flags = (fi->flags & ~CAMEL_FOLDER_NOINFERIORS) | CAMEL_FOLDER_CHILDREN; - } else { - fi->unread_message_count = unread; - fi->flags &= ~CAMEL_FOLDER_NOSELECT; - if ((ext = strchr (fi->url, ';')) && !strncmp (ext, ";noselect=yes", 13)) - memmove (ext, ext + 13, strlen (ext + 13) + 1); - } - } else { - fi = g_new0 (CamelFolderInfo, 1); - fi->parent = parent; - - /* add ";noselect=yes" if we haven't found the mbox file yet. when we find it, remove the noselect */ - fi->url = g_strdup_printf ("mbox:%s%s#%s", ((CamelService *) store)->url->path, - S_ISDIR (st.st_mode) ? ";noselect=yes" : "", full_name); - fi->name = short_name; - fi->full_name = full_name; - fi->path = g_strdup_printf ("/%s", full_name); - fi->unread_message_count = unread; - - if (S_ISDIR (st.st_mode)) - fi->flags = CAMEL_FOLDER_NOSELECT; - else - fi->flags = CAMEL_FOLDER_NOINFERIORS; - - if (tail == NULL) - folders = fi; - else - tail->sibling = fi; - - tail = fi; - - g_hash_table_insert (folder_hash, fi->name, fi); - } - - if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) && S_ISDIR (st.st_mode)) { - struct _inode in = { st.st_dev, st.st_ino }; - - if (g_hash_table_lookup (visited, &in) == NULL) { - struct _inode *inew = g_new (struct _inode, 1); - - *inew = in; - - g_hash_table_insert (visited, inew, inew); - - if ((fi->child = scan_dir (store, visited, fi, path, fi->full_name, flags, ex))) - fi->flags |= CAMEL_FOLDER_CHILDREN; - } - } - - g_free (path); - } - - closedir (dir); - - g_hash_table_destroy (folder_hash); - - return folders; -} - -static CamelFolderInfo * -get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - GHashTable *visited; - struct _inode *inode; - char *path, *subdir; - CamelFolderInfo *fi; - CamelFolder *folder; - const char *base; - struct stat st; - int unread = -1; - - top = top ? top : ""; - path = mbox_folder_name_to_path (store, top); - - if (*top == '\0') { - /* requesting root dir scan */ - if (stat (path, &st) == -1 || !S_ISDIR (st.st_mode)) { - g_free (path); - return NULL; - } - - visited = g_hash_table_new (inode_hash, inode_equal); - - inode = g_new (struct _inode, 1); - inode->dnode = st.st_dev; - inode->inode = st.st_ino; - - g_hash_table_insert (visited, inode, inode); - - fi = scan_dir (store, visited, NULL, path, NULL, flags, ex); - g_hash_table_foreach (visited, inode_free, NULL); - g_hash_table_destroy (visited); - g_free (path); - - return fi; - } - - /* requesting scan of specific folder */ - if (stat (path, &st) == -1 || !S_ISREG (st.st_mode)) { - g_free (path); - return NULL; - } - - visited = g_hash_table_new (inode_hash, inode_equal); - - if (!(base = strrchr (top, '/'))) - base = top; - else - base++; - - folder = camel_object_bag_get (store->folders, top); - if (folder) { - if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) - camel_folder_refresh_info (folder, NULL); - unread = camel_folder_get_unread_message_count (folder); - camel_object_unref (folder); - } - - fi = g_new0 (CamelFolderInfo, 1); - fi->parent = NULL; - fi->url = g_strdup_printf ("mbox:%s#%s", ((CamelService *) store)->url->path, top); - fi->name = g_strdup (base); - fi->full_name = g_strdup (top); - fi->unread_message_count = unread; - fi->path = g_strdup_printf ("/%s", top); - - subdir = g_strdup_printf ("%s.sbd", path); - if (stat (subdir, &st) == 0 && S_ISDIR (st.st_mode)) - fi->child = scan_dir (store, visited, fi, subdir, top, flags, ex); - - if (fi->child) - fi->flags |= CAMEL_FOLDER_CHILDREN; - else - fi->flags |= CAMEL_FOLDER_NOINFERIORS; - - g_free (subdir); - - g_hash_table_foreach (visited, inode_free, NULL); - g_hash_table_destroy (visited); - g_free (path); - - return fi; -} diff --git a/camel/providers/local/camel-mbox-store.h b/camel/providers/local/camel-mbox-store.h deleted file mode 100644 index 5b6fbdd926..0000000000 --- a/camel/providers/local/camel-mbox-store.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi - * - * Copyright (C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_MBOX_STORE_H -#define CAMEL_MBOX_STORE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-local-store.h" - -#define CAMEL_MBOX_STORE_TYPE (camel_mbox_store_get_type ()) -#define CAMEL_MBOX_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MBOX_STORE_TYPE, CamelMboxStore)) -#define CAMEL_MBOX_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MBOX_STORE_TYPE, CamelMboxStoreClass)) -#define CAMEL_IS_MBOX_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_MBOX_STORE_TYPE)) - -typedef struct { - CamelLocalStore parent_object; - -} CamelMboxStore; - -typedef struct { - CamelLocalStoreClass parent_class; - -} CamelMboxStoreClass; - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_mbox_store_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_MBOX_STORE_H */ - - diff --git a/camel/providers/local/camel-mbox-summary.c b/camel/providers/local/camel-mbox-summary.c deleted file mode 100644 index 4018fc93c9..0000000000 --- a/camel/providers/local/camel-mbox-summary.c +++ /dev/null @@ -1,1029 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "camel-mbox-summary.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-operation.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "camel-mbox-summary.h" -#include "camel/camel-file-utils.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-operation.h" - -#define io(x) -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#define CAMEL_MBOX_SUMMARY_VERSION (0x1000) - -static int summary_header_load (CamelFolderSummary *, FILE *); -static int summary_header_save (CamelFolderSummary *, FILE *); - -static CamelMessageInfo * message_info_new (CamelFolderSummary *, struct _camel_header_raw *); -static CamelMessageInfo * message_info_new_from_parser (CamelFolderSummary *, CamelMimeParser *); -static CamelMessageInfo * message_info_load (CamelFolderSummary *, FILE *); -static int message_info_save (CamelFolderSummary *, FILE *, CamelMessageInfo *); -/*static void message_info_free (CamelFolderSummary *, CamelMessageInfo *);*/ - -static int mbox_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int mbox_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -#ifdef STATUS_PINE -static CamelMessageInfo *mbox_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex); -#endif - -static int mbox_summary_sync_quick(CamelMboxSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int mbox_summary_sync_full(CamelMboxSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); - -static void camel_mbox_summary_class_init (CamelMboxSummaryClass *klass); -static void camel_mbox_summary_init (CamelMboxSummary *obj); -static void camel_mbox_summary_finalise (CamelObject *obj); - -#ifdef STATUS_PINE -/* Which status flags are stored in each separate header */ -#define STATUS_XSTATUS (CAMEL_MESSAGE_FLAGGED|CAMEL_MESSAGE_ANSWERED|CAMEL_MESSAGE_DELETED) -#define STATUS_STATUS (CAMEL_MESSAGE_SEEN) - -static void encode_status(guint32 flags, char status[8]); -static guint32 decode_status(const char *status); -#endif - -static CamelLocalSummaryClass *camel_mbox_summary_parent; - -CamelType -camel_mbox_summary_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_local_summary_get_type(), "CamelMboxSummary", - sizeof (CamelMboxSummary), - sizeof (CamelMboxSummaryClass), - (CamelObjectClassInitFunc) camel_mbox_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_mbox_summary_init, - (CamelObjectFinalizeFunc) camel_mbox_summary_finalise); - } - - return type; -} - -static void -camel_mbox_summary_class_init(CamelMboxSummaryClass *klass) -{ - CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *)klass; - CamelLocalSummaryClass *lklass = (CamelLocalSummaryClass *)klass; - - camel_mbox_summary_parent = (CamelLocalSummaryClass *)camel_type_get_global_classfuncs(camel_local_summary_get_type()); - - sklass->summary_header_load = summary_header_load; - sklass->summary_header_save = summary_header_save; - - sklass->message_info_new = message_info_new; - sklass->message_info_new_from_parser = message_info_new_from_parser; - sklass->message_info_load = message_info_load; - sklass->message_info_save = message_info_save; - /*sklass->message_info_free = message_info_free;*/ - - lklass->check = mbox_summary_check; - lklass->sync = mbox_summary_sync; -#ifdef STATUS_PINE - lklass->add = mbox_summary_add; -#endif - - klass->sync_quick = mbox_summary_sync_quick; - klass->sync_full = mbox_summary_sync_full; -} - -static void -camel_mbox_summary_init(CamelMboxSummary *obj) -{ - struct _CamelFolderSummary *s = (CamelFolderSummary *)obj; - - /* subclasses need to set the right instance data sizes */ - s->message_info_size = sizeof(CamelMboxMessageInfo); - s->content_info_size = sizeof(CamelMboxMessageContentInfo); - - /* and a unique file version */ - s->version += CAMEL_MBOX_SUMMARY_VERSION; -} - -static void -camel_mbox_summary_finalise(CamelObject *obj) -{ - /*CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(obj);*/ -} - -/** - * camel_mbox_summary_new: - * - * Create a new CamelMboxSummary object. - * - * Return value: A new CamelMboxSummary widget. - **/ -CamelMboxSummary * -camel_mbox_summary_new(const char *filename, const char *mbox_name, CamelIndex *index) -{ - CamelMboxSummary *new = (CamelMboxSummary *)camel_object_new(camel_mbox_summary_get_type()); - - camel_local_summary_construct((CamelLocalSummary *)new, filename, mbox_name, index); - return new; -} - -void camel_mbox_summary_xstatus(CamelMboxSummary *mbs, int state) -{ - mbs->xstatus = state; -} - -static int -summary_header_load(CamelFolderSummary *s, FILE *in) -{ - CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(s); - - if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->summary_header_load(s, in) == -1) - return -1; - - return camel_file_util_decode_uint32(in, (guint32 *) &mbs->folder_size); -} - -static int -summary_header_save(CamelFolderSummary *s, FILE *out) -{ - CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(s); - - if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->summary_header_save(s, out) == -1) - return -1; - - return camel_file_util_encode_uint32(out, mbs->folder_size); -} - -static CamelMessageInfo * -message_info_new(CamelFolderSummary *s, struct _camel_header_raw *h) -{ - CamelMessageInfo *mi; - CamelMboxSummary *mbs = (CamelMboxSummary *)s; - - mi = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_new(s, h); - if (mi) { - CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi; - const char *xev, *uid; - CamelMessageInfo *info = NULL; - int add = 0; /* bitmask of things to add, 1 assign uid, 2, just add as new, 4 = recent */ -#ifdef STATUS_PINE - const char *status = NULL, *xstatus = NULL; - guint32 flags = 0; - - if (mbs->xstatus) { - /* check for existance of status & x-status headers */ - status = camel_header_raw_find(&h, "Status", NULL); - if (status) - flags = decode_status(status); - xstatus = camel_header_raw_find(&h, "X-Status", NULL); - if (xstatus) - flags |= decode_status(xstatus); - } -#endif - /* if we have an xev header, use it, else assign a new one */ - xev = camel_header_raw_find(&h, "X-Evolution", NULL); - if (xev != NULL - && camel_local_summary_decode_x_evolution((CamelLocalSummary *)s, xev, mi) == 0) { - uid = camel_message_info_uid(mi); - d(printf("found valid x-evolution: %s\n", uid)); - info = camel_folder_summary_uid(s, uid); - if (info) { - if ((info->flags & CAMEL_MESSAGE_FOLDER_NOTSEEN)) { - info->flags &= ~CAMEL_MESSAGE_FOLDER_NOTSEEN; - camel_folder_summary_info_free(s, mi); - mbi = (CamelMboxMessageInfo *)mi = info; - } else { - add = 7; - d(printf("seen '%s' before, adding anew\n", uid)); - camel_folder_summary_info_free(s, info); - } - } else { - add = 2; - d(printf("but isn't present in summary\n")); - } - } else { - d(printf("didn't find x-evolution\n")); - add = 7; - } - - if (add&1) { - mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV; - camel_message_info_set_uid(mi, camel_folder_summary_next_uid_string(s)); - } else { - camel_folder_summary_set_uid(s, strtoul(camel_message_info_uid(mi), NULL, 10)); - } -#ifdef STATUS_PINE - if (mbs->xstatus && add&2) { - /* use the status as the flags when we read it the first time */ - if (status) - mi->flags = (mi->flags & ~(STATUS_STATUS)) | (flags & STATUS_STATUS); - if (xstatus) - mi->flags = (mi->flags & ~(STATUS_XSTATUS)) | (flags & STATUS_XSTATUS); - } -#endif - if (mbs->changes) { - if (add&2) - camel_folder_change_info_add_uid(mbs->changes, camel_message_info_uid(mi)); - if ((add&4) && status == NULL) - camel_folder_change_info_recent_uid(mbs->changes, camel_message_info_uid(mi)); - } - - mbi->frompos = -1; - } - - return mi; -} - -static CamelMessageInfo * -message_info_new_from_parser(CamelFolderSummary *s, CamelMimeParser *mp) -{ - CamelMessageInfo *mi; - - mi = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_new_from_parser(s, mp); - if (mi) { - CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi; - - mbi->frompos = camel_mime_parser_tell_start_from(mp); - } - - return mi; -} - -static CamelMessageInfo * -message_info_load(CamelFolderSummary *s, FILE *in) -{ - CamelMessageInfo *mi; - - io(printf("loading mbox message info\n")); - - mi = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_load(s, in); - if (mi) { - CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi; - - if (camel_file_util_decode_off_t(in, &mbi->frompos) == -1) - goto error; - } - - return mi; -error: - camel_folder_summary_info_free(s, mi); - return NULL; -} - -static int -message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *mi) -{ - CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi; - - io(printf("saving mbox message info\n")); - - if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_save(s, out, mi) == -1 - || camel_file_util_encode_off_t(out, mbi->frompos) == -1) - return -1; - - return 0; -} - -/* like summary_rebuild, but also do changeinfo stuff (if supplied) */ -static int -summary_update(CamelLocalSummary *cls, off_t offset, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int i, count; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - CamelMboxSummary *mbs = (CamelMboxSummary *)cls; - CamelMimeParser *mp; - CamelMessageInfo *mi; - int fd; - int ok = 0; - struct stat st; - off_t size = 0; - - d(printf("Calling summary update, from pos %d\n", (int)offset)); - - cls->index_force = FALSE; - - camel_operation_start(NULL, _("Storing folder")); - - fd = open(cls->folder_path, O_RDONLY); - if (fd == -1) { - d(printf("%s failed to open: %s\n", cls->folder_path, strerror (errno))); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open folder: %s: %s"), - cls->folder_path, g_strerror (errno)); - camel_operation_end(NULL); - return -1; - } - - if (fstat(fd, &st) == 0) - size = st.st_size; - - mp = camel_mime_parser_new(); - camel_mime_parser_init_with_fd(mp, fd); - camel_mime_parser_scan_from(mp, TRUE); - camel_mime_parser_seek(mp, offset, SEEK_SET); - - if (offset > 0) { - if (camel_mime_parser_step(mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM - && camel_mime_parser_tell_start_from(mp) == offset) { - camel_mime_parser_unstep(mp); - } else { - g_warning("The next message didn't start where I expected, building summary from start"); - camel_mime_parser_drop_step(mp); - offset = 0; - camel_mime_parser_seek(mp, offset, SEEK_SET); - } - } - - /* we mark messages as to whether we've seen them or not. - If we're not starting from the start, we must be starting - from the old end, so everything must be treated as new */ - count = camel_folder_summary_count(s); - for (i=0;iflags |= CAMEL_MESSAGE_FOLDER_NOTSEEN; - else - mi->flags &= ~CAMEL_MESSAGE_FOLDER_NOTSEEN; - camel_folder_summary_info_free(s, mi); - } - mbs->changes = changeinfo; - - while (camel_mime_parser_step(mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM) { - CamelMessageInfo *info; - off_t pc = camel_mime_parser_tell_start_from (mp) + 1; - - camel_operation_progress (NULL, (int) (((float) pc / size) * 100)); - - info = camel_folder_summary_add_from_parser(s, mp); - if (info == NULL) { - camel_exception_setv(ex, 1, _("Fatal mail parser error near position %ld in folder %s"), - camel_mime_parser_tell(mp), cls->folder_path); - ok = -1; - break; - } - - g_assert(camel_mime_parser_step(mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM_END); - } - - camel_object_unref(CAMEL_OBJECT (mp)); - - count = camel_folder_summary_count(s); - for (i=0;iflags & CAMEL_MESSAGE_FOLDER_NOTSEEN) { - d(printf("uid '%s' vanished, removing", camel_message_info_uid(mi))); - if (changeinfo) - camel_folder_change_info_remove_uid(changeinfo, camel_message_info_uid(mi)); - camel_folder_summary_remove(s, mi); - count--; - i--; - } - camel_folder_summary_info_free(s, mi); - } - mbs->changes = NULL; - - /* update the file size/mtime in the summary */ - if (ok != -1) { - if (stat(cls->folder_path, &st) == 0) { - camel_folder_summary_touch(s); - mbs->folder_size = st.st_size; - s->time = st.st_mtime; - } - } - - camel_operation_end(NULL); - - return ok; -} - -static int -mbox_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, CamelException *ex) -{ - CamelMboxSummary *mbs = (CamelMboxSummary *)cls; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - struct stat st; - int ret = 0; - int i, count; - - d(printf("Checking summary\n")); - - /* check if the summary is up-to-date */ - if (stat(cls->folder_path, &st) == -1) { - camel_folder_summary_clear(s); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot check folder: %s: %s"), - cls->folder_path, g_strerror (errno)); - return -1; - } - - if (cls->check_force) - mbs->folder_size = 0; - cls->check_force = 0; - - if (st.st_size == 0) { - /* empty? No need to scan at all */ - d(printf("Empty mbox, clearing summary\n")); - count= camel_folder_summary_count(s); - for (i=0;ifolder_size || st.st_mtime != s->time) { - if (mbs->folder_size < st.st_size) { - /* this will automatically rescan from 0 if there is a problem */ - d(printf("folder grew, attempting to rebuild from %d\n", mbs->folder_size)); - ret = summary_update(cls, mbs->folder_size, changes, ex); - } else { - d(printf("folder shrank! rebuilding from start\n")); - ret = summary_update(cls, 0, changes, ex); - } - } else { - d(printf("Folder unchanged, do nothing\n")); - } - } - - /* FIXME: move upstream? */ - - if (ret != -1) { - if (mbs->folder_size != st.st_size || s->time != st.st_mtime) { - mbs->folder_size = st.st_size; - s->time = st.st_mtime; - camel_folder_summary_touch(s); - } - } - - return ret; -} - -/* perform a full sync */ -static int -mbox_summary_sync_full(CamelMboxSummary *mbs, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - CamelLocalSummary *cls = (CamelLocalSummary *)mbs; - int fd = -1, fdout = -1; - char *tmpname = NULL; - guint32 flags = (expunge?1:0); - - d(printf("performing full summary/sync\n")); - - camel_operation_start(NULL, _("Storing folder")); - - fd = open(cls->folder_path, O_RDONLY); - if (fd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open file: %s: %s"), - cls->folder_path, g_strerror (errno)); - camel_operation_end(NULL); - return -1; - } - - tmpname = g_alloca (strlen (cls->folder_path) + 5); - sprintf (tmpname, "%s.tmp", cls->folder_path); - d(printf("Writing tmp file to %s\n", tmpname)); - fdout = open(tmpname, O_WRONLY|O_CREAT|O_TRUNC, 0600); - if (fdout == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot open temporary mailbox: %s"), - g_strerror (errno)); - goto error; - } - - if (camel_mbox_summary_sync_mbox((CamelMboxSummary *)cls, flags, changeinfo, fd, fdout, ex) == -1) - goto error; - - d(printf("Closing folders\n")); - - if (close(fd) == -1) { - g_warning("Cannot close source folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not close source folder %s: %s"), - cls->folder_path, g_strerror (errno)); - fd = -1; - goto error; - } - - if (close(fdout) == -1) { - g_warning("Cannot close tmp folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not close temp folder: %s"), - g_strerror (errno)); - fdout = -1; - goto error; - } - - /* this should probably either use unlink/link/unlink, or recopy over - the original mailbox, for various locking reasons/etc */ - if (rename(tmpname, cls->folder_path) == -1) { - g_warning("Cannot rename folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not rename folder: %s"), - g_strerror (errno)); - goto error; - } - tmpname = NULL; - - camel_operation_end(NULL); - - return 0; - error: - if (fd != -1) - close(fd); - - if (fdout != -1) - close(fdout); - - if (tmpname) - unlink(tmpname); - - camel_operation_end(NULL); - - return -1; -} - -/* perform a quick sync - only system flags have changed */ -static int -mbox_summary_sync_quick(CamelMboxSummary *mbs, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - CamelLocalSummary *cls = (CamelLocalSummary *)mbs; - CamelFolderSummary *s = (CamelFolderSummary *)mbs; - CamelMimeParser *mp = NULL; - int i, count; - CamelMboxMessageInfo *info = NULL; - int fd = -1; - char *xevnew, *xevtmp; - const char *xev; - int len; - off_t lastpos; - - d(printf("Performing quick summary sync\n")); - - camel_operation_start(NULL, _("Storing folder")); - - fd = open(cls->folder_path, O_RDWR); - if (fd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open file: %s: %s"), - cls->folder_path, g_strerror (errno)); - - camel_operation_end(NULL); - return -1; - } - - mp = camel_mime_parser_new(); - camel_mime_parser_scan_from(mp, TRUE); - camel_mime_parser_scan_pre_from(mp, TRUE); - camel_mime_parser_init_with_fd(mp, fd); - - count = camel_folder_summary_count(s); - for (i = 0; i < count; i++) { - int xevoffset; - int pc = (i+1)*100/count; - - camel_operation_progress(NULL, pc); - - info = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i); - - g_assert(info); - - d(printf("Checking message %s %08x\n", camel_message_info_uid(info), info->info.flags)); - - if ((info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) == 0) { - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - info = NULL; - continue; - } - - d(printf("Updating message %s\n", camel_message_info_uid(info))); - - camel_mime_parser_seek(mp, info->frompos, SEEK_SET); - - if (camel_mime_parser_step(mp, 0, 0) != CAMEL_MIME_PARSER_STATE_FROM) { - g_warning("Expected a From line here, didn't get it"); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - if (camel_mime_parser_tell_start_from(mp) != info->frompos) { - g_warning("Didn't get the next message where I expected (%d) got %d instead", - (int)info->frompos, (int)camel_mime_parser_tell_start_from(mp)); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - if (camel_mime_parser_step(mp, 0, 0) == CAMEL_MIME_PARSER_STATE_FROM_END) { - g_warning("camel_mime_parser_step failed (2)"); - goto error; - } - - xev = camel_mime_parser_header(mp, "X-Evolution", &xevoffset); - if (xev == NULL || camel_local_summary_decode_x_evolution(cls, xev, NULL) == -1) { - g_warning("We're supposed to have a valid x-ev header, but we dont"); - goto error; - } - xevnew = camel_local_summary_encode_x_evolution(cls, (CamelMessageInfo *)info); - /* SIGH: encode_param_list is about the only function which folds headers by itself. - This should be fixed somehow differently (either parser doesn't fold headers, - or param_list doesn't, or something */ - xevtmp = camel_header_unfold(xevnew); - /* the raw header contains a leading ' ', so (dis)count that too */ - if (strlen(xev)-1 != strlen(xevtmp)) { - printf ("strlen(xev)-1 = %d; strlen(xevtmp) = %d\n", strlen(xev)-1, strlen(xevtmp)); - printf ("xev='%s'; xevtmp='%s'\n", xev, xevtmp); - g_free(xevnew); - g_free(xevtmp); - g_warning("Hmm, the xev headers shouldn't have changed size, but they did"); - goto error; - } - g_free(xevtmp); - - /* we write out the xevnew string, assuming its been folded identically to the original too! */ - - lastpos = lseek(fd, 0, SEEK_CUR); - lseek(fd, xevoffset+strlen("X-Evolution: "), SEEK_SET); - do { - len = write(fd, xevnew, strlen(xevnew)); - } while (len == -1 && errno == EINTR); - lseek(fd, lastpos, SEEK_SET); - g_free(xevnew); - - camel_mime_parser_drop_step(mp); - camel_mime_parser_drop_step(mp); - - info->info.flags &= 0xffff; - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - } - - d(printf("Closing folders\n")); - - if (close(fd) == -1) { - g_warning ("Cannot close source folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not close source folder %s: %s"), - cls->folder_path, g_strerror (errno)); - fd = -1; - goto error; - } - - camel_object_unref((CamelObject *)mp); - - camel_operation_end(NULL); - - return 0; - error: - if (fd != -1) - close(fd); - if (mp) - camel_object_unref((CamelObject *)mp); - if (info) - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - - camel_operation_end(NULL); - - return -1; -} - -static int -mbox_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - struct stat st; - CamelMboxSummary *mbs = (CamelMboxSummary *)cls; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - int i, count; - int quick = TRUE, work=FALSE; - int ret; - - /* first, sync ourselves up, just to make sure */ - if (camel_local_summary_check(cls, changeinfo, ex) == -1) - return -1; - - count = camel_folder_summary_count(s); - if (count == 0) - return 0; - - /* check what work we have to do, if any */ - for (i=0;quick && iflags & CAMEL_MESSAGE_DELETED)) || - (info->flags & (CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_XEVCHANGE))) - quick = FALSE; - else - work |= (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0; - camel_folder_summary_info_free(s, info); - } - - /* yuck i hate this logic, but its to simplify the 'all ok, update summary' and failover cases */ - ret = -1; - if (quick) { - if (work) { - ret = ((CamelMboxSummaryClass *)((CamelObject *)cls)->klass)->sync_quick(mbs, expunge, changeinfo, ex); - if (ret == -1) { - g_warning("failed a quick-sync, trying a full sync"); - camel_exception_clear(ex); - } - } else { - ret = 0; - } - } - - if (ret == -1) - ret = ((CamelMboxSummaryClass *)((CamelObject *)cls)->klass)->sync_full(mbs, expunge, changeinfo, ex); - if (ret == -1) - return -1; - - if (stat(cls->folder_path, &st) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unknown error: %s"), g_strerror (errno)); - return -1; - } - - if (mbs->folder_size != st.st_size || s->time != st.st_mtime) { - s->time = st.st_mtime; - mbs->folder_size = st.st_size; - camel_folder_summary_touch(s); - } - - return ((CamelLocalSummaryClass *)camel_mbox_summary_parent)->sync(cls, expunge, changeinfo, ex); -} - -int -camel_mbox_summary_sync_mbox(CamelMboxSummary *cls, guint32 flags, CamelFolderChangeInfo *changeinfo, int fd, int fdout, CamelException *ex) -{ - CamelMboxSummary *mbs = (CamelMboxSummary *)cls; - CamelFolderSummary *s = (CamelFolderSummary *)mbs; - CamelMimeParser *mp = NULL; - int i, count; - CamelMboxMessageInfo *info = NULL; - char *buffer, *xevnew = NULL; - size_t len; - const char *fromline; - int lastdel = FALSE; -#ifdef STATUS_PINE - char statnew[8], xstatnew[8]; -#endif - - d(printf("performing full summary/sync\n")); - - /* need to dup this because the mime-parser owns the fd after we give it to it */ - fd = dup(fd); - if (fd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not store folder: %s"), - g_strerror (errno)); - return -1; - } - - mp = camel_mime_parser_new(); - camel_mime_parser_scan_from(mp, TRUE); - camel_mime_parser_scan_pre_from(mp, TRUE); - camel_mime_parser_init_with_fd(mp, fd); - - count = camel_folder_summary_count(s); - for (i = 0; i < count; i++) { - int pc = (i + 1) * 100 / count; - - camel_operation_progress(NULL, pc); - - info = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i); - - g_assert(info); - - d(printf("Looking at message %s\n", camel_message_info_uid(info))); - - /* only need to seek past deleted messages, otherwise we should be at the right spot/state already */ - if (lastdel) { - d(printf("seeking to %d\n", (int)info->frompos)); - camel_mime_parser_seek(mp, info->frompos, SEEK_SET); - } - - if (camel_mime_parser_step(mp, &buffer, &len) != CAMEL_MIME_PARSER_STATE_FROM) { - g_warning("Expected a From line here, didn't get it"); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - if (camel_mime_parser_tell_start_from(mp) != info->frompos) { - g_warning("Didn't get the next message where I expected (%d) got %d instead", - (int)info->frompos, (int)camel_mime_parser_tell_start_from(mp)); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - lastdel = FALSE; - if ((flags&1) && info->info.flags & CAMEL_MESSAGE_DELETED) { - const char *uid = camel_message_info_uid(info); - - d(printf("Deleting %s\n", uid)); - - if (((CamelLocalSummary *)cls)->index) - camel_index_delete_name(((CamelLocalSummary *)cls)->index, uid); - - /* remove it from the change list */ - camel_folder_change_info_remove_uid(changeinfo, uid); - camel_folder_summary_remove(s, (CamelMessageInfo *)info); - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - count--; - i--; - info = NULL; - lastdel = TRUE; - } else { - /* otherwise, the message is staying, copy its From_ line across */ -#if 0 - if (i>0) - write(fdout, "\n", 1); -#endif - info->frompos = lseek(fdout, 0, SEEK_CUR); - fromline = camel_mime_parser_from_line(mp); - write(fdout, fromline, strlen(fromline)); - } - - if (info && info->info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED)) { - d(printf("Updating header for %s flags = %08x\n", camel_message_info_uid(info), info->info.flags)); - - if (camel_mime_parser_step(mp, &buffer, &len) == CAMEL_MIME_PARSER_STATE_FROM_END) { - g_warning("camel_mime_parser_step failed (2)"); - goto error; - } - - xevnew = camel_local_summary_encode_x_evolution((CamelLocalSummary *)cls, (CamelMessageInfo *)info); -#ifdef STATUS_PINE - if (mbs->xstatus) { - encode_status(((CamelMessageInfo *)info)->flags & STATUS_STATUS, statnew); - encode_status(((CamelMessageInfo *)info)->flags & STATUS_XSTATUS, xstatnew); - len = camel_local_summary_write_headers(fdout, camel_mime_parser_headers_raw(mp), xevnew, statnew, xstatnew); - } else { -#endif - len = camel_local_summary_write_headers(fdout, camel_mime_parser_headers_raw(mp), xevnew, NULL, NULL); -#ifdef STATUS_PINE - } -#endif - if (len == -1) { - d(printf("Error writing to tmp mailbox\n")); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Error writing to temp mailbox: %s"), - g_strerror (errno)); - goto error; - } - info->info.flags &= 0xffff; - g_free(xevnew); - xevnew = NULL; - camel_mime_parser_drop_step(mp); - } - - camel_mime_parser_drop_step(mp); - if (info) { - d(printf("looking for message content to copy across from %d\n", (int)camel_mime_parser_tell(mp))); - while (camel_mime_parser_step(mp, &buffer, &len) == CAMEL_MIME_PARSER_STATE_PRE_FROM) { - /*d(printf("copying mbox contents to tmp: '%.*s'\n", len, buffer));*/ - if (write(fdout, buffer, len) != len) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Writing to tmp mailbox failed: %s: %s"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno)); - goto error; - } - } - - if (write(fdout, "\n", 1) != 1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Error writing to temp mailbox: %s"), - g_strerror (errno)); - goto error; - } - - d(printf("we are now at %d, from = %d\n", (int)camel_mime_parser_tell(mp), - (int)camel_mime_parser_tell_start_from(mp))); - camel_mime_parser_unstep(mp); - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - info = NULL; - } - } - -#if 0 - /* if last was deleted, append the \n we removed */ - if (lastdel && count > 0) - write(fdout, "\n", 1); -#endif - - camel_object_unref((CamelObject *)mp); - - return 0; - error: - g_free(xevnew); - - if (mp) - camel_object_unref((CamelObject *)mp); - if (info) - camel_folder_summary_info_free(s, (CamelMessageInfo *)info); - - return -1; -} - -#ifdef STATUS_PINE -static CamelMessageInfo * -mbox_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex) -{ - CamelMessageInfo *mi; - - mi = ((CamelLocalSummaryClass *)camel_mbox_summary_parent)->add(cls, msg, info, ci, ex); - if (mi && ((CamelMboxSummary *)cls)->xstatus) { - char status[8]; - - /* we snoop and add status/x-status headers to suit */ - encode_status(mi->flags & STATUS_STATUS, status); - camel_medium_set_header((CamelMedium *)msg, "Status", status); - encode_status(mi->flags & STATUS_XSTATUS, status); - camel_medium_set_header((CamelMedium *)msg, "X-Status", status); - } - - return mi; -} - -static struct { - char tag; - guint32 flag; -} status_flags[] = { - { 'F', CAMEL_MESSAGE_FLAGGED }, - { 'A', CAMEL_MESSAGE_ANSWERED }, - { 'D', CAMEL_MESSAGE_DELETED }, - { 'R', CAMEL_MESSAGE_SEEN }, -}; - -static void -encode_status(guint32 flags, char status[8]) -{ - char *p; - int i; - - p = status; - for (i=0;i - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_MBOX_SUMMARY_H -#define _CAMEL_MBOX_SUMMARY_H - -#include "camel-local-summary.h" - -/* Enable the use of elm/pine style "Status" & "X-Status" headers */ -#define STATUS_PINE - -#define CAMEL_MBOX_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_mbox_summary_get_type (), CamelMboxSummary) -#define CAMEL_MBOX_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_mbox_summary_get_type (), CamelMboxSummaryClass) -#define CAMEL_IS_MBOX_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_mbox_summary_get_type ()) - -typedef struct _CamelMboxSummary CamelMboxSummary; -typedef struct _CamelMboxSummaryClass CamelMboxSummaryClass; - -typedef struct _CamelMboxMessageContentInfo { - CamelMessageContentInfo info; -} CamelMboxMessageContentInfo; - -typedef struct _CamelMboxMessageInfo { - CamelMessageInfo info; - - off_t frompos; -} CamelMboxMessageInfo; - -struct _CamelMboxSummary { - CamelLocalSummary parent; - - CamelFolderChangeInfo *changes; /* used to build change sets */ - - size_t folder_size; /* size of the mbox file, last sync */ - - unsigned int xstatus:1; /* do we store/honour xstatus/status headers */ -}; - -struct _CamelMboxSummaryClass { - CamelLocalSummaryClass parent_class; - - /* sync in-place */ - int (*sync_quick)(CamelMboxSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); - /* sync requires copy */ - int (*sync_full)(CamelMboxSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -}; - -CamelType camel_mbox_summary_get_type (void); -CamelMboxSummary *camel_mbox_summary_new (const char *filename, const char *mbox_name, CamelIndex *index); - -/* do we honour/use xstatus headers, etc */ -void camel_mbox_summary_xstatus(CamelMboxSummary *mbs, int state); - -/* build a new mbox from an existing mbox storing summary information */ -int camel_mbox_summary_sync_mbox(CamelMboxSummary *cls, guint32 flags, CamelFolderChangeInfo *changeinfo, int fd, int fdout, CamelException *ex); - -#endif /* ! _CAMEL_MBOX_SUMMARY_H */ - diff --git a/camel/providers/local/camel-mh-folder.c b/camel/providers/local/camel-mh-folder.c deleted file mode 100644 index 25dbacc49a..0000000000 --- a/camel/providers/local/camel-mh-folder.c +++ /dev/null @@ -1,231 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Authors: Michael Zucchi - * - * Copyright (C) 1999, 2003 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "camel-mh-folder.h" -#include "camel-mh-store.h" -#include "camel-stream-fs.h" -#include "camel-mh-summary.h" -#include "camel-data-wrapper.h" -#include "camel-mime-message.h" -#include "camel-exception.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -static CamelLocalFolderClass *parent_class = NULL; - -/* Returns the class for a CamelMhFolder */ -#define CMHF_CLASS(so) CAMEL_MH_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMHS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static CamelLocalSummary *mh_create_summary(const char *path, const char *folder, CamelIndex *index); - -static void mh_append_message(CamelFolder * folder, CamelMimeMessage * message, const CamelMessageInfo *info, char **appended_uid, CamelException * ex); -static CamelMimeMessage *mh_get_message(CamelFolder * folder, const gchar * uid, CamelException * ex); - -static void mh_finalize(CamelObject * object); - -static void camel_mh_folder_class_init(CamelObjectClass * camel_mh_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_mh_folder_class); - CamelLocalFolderClass *lclass = (CamelLocalFolderClass *)camel_mh_folder_class; - - parent_class = CAMEL_LOCAL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_local_folder_get_type())); - - /* virtual method definition */ - - /* virtual method overload */ - camel_folder_class->append_message = mh_append_message; - camel_folder_class->get_message = mh_get_message; - - lclass->create_summary = mh_create_summary; -} - -static void mh_init(gpointer object, gpointer klass) -{ - /*CamelFolder *folder = object; - CamelMhFolder *mh_folder = object;*/ -} - -static void mh_finalize(CamelObject * object) -{ - /*CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(object);*/ -} - -CamelType camel_mh_folder_get_type(void) -{ - static CamelType camel_mh_folder_type = CAMEL_INVALID_TYPE; - - if (camel_mh_folder_type == CAMEL_INVALID_TYPE) { - camel_mh_folder_type = camel_type_register(CAMEL_LOCAL_FOLDER_TYPE, "CamelMhFolder", - sizeof(CamelMhFolder), - sizeof(CamelMhFolderClass), - (CamelObjectClassInitFunc) camel_mh_folder_class_init, - NULL, - (CamelObjectInitFunc) mh_init, - (CamelObjectFinalizeFunc) mh_finalize); - } - - return camel_mh_folder_type; -} - -CamelFolder * -camel_mh_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) -{ - CamelFolder *folder; - - d(printf("Creating mh folder: %s\n", full_name)); - - folder = (CamelFolder *)camel_object_new(CAMEL_MH_FOLDER_TYPE); - folder = (CamelFolder *)camel_local_folder_construct((CamelLocalFolder *)folder, - parent_store, full_name, flags, ex); - - return folder; -} - -static CamelLocalSummary *mh_create_summary(const char *path, const char *folder, CamelIndex *index) -{ - return (CamelLocalSummary *)camel_mh_summary_new(path, folder, index); -} - -static void -mh_append_message (CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, char **appended_uid, CamelException *ex) -{ - CamelMhFolder *mh_folder = (CamelMhFolder *)folder; - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *output_stream; - CamelMessageInfo *mi; - char *name; - - /* FIXME: probably needs additional locking (although mh doesn't appear do do it) */ - - d(printf("Appending message\n")); - - /* add it to the summary/assign the uid, etc */ - mi = camel_local_summary_add((CamelLocalSummary *)folder->summary, message, info, lf->changes, ex); - if (camel_exception_is_set (ex)) - return; - - d(printf("Appending message: uid is %s\n", camel_message_info_uid(mi))); - - /* write it out, use the uid we got from the summary */ - name = g_strdup_printf("%s/%s", lf->folder_path, camel_message_info_uid(mi)); - output_stream = camel_stream_fs_new_with_name(name, O_WRONLY|O_CREAT, 0600); - if (output_stream == NULL) - goto fail_write; - - if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *)message, output_stream) == -1 - || camel_stream_close (output_stream) == -1) - goto fail_write; - - /* close this? */ - camel_object_unref (CAMEL_OBJECT (output_stream)); - - g_free(name); - - camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", - ((CamelLocalFolder *)mh_folder)->changes); - camel_folder_change_info_clear (((CamelLocalFolder *)mh_folder)->changes); - - if (appended_uid) - *appended_uid = g_strdup(camel_message_info_uid(mi)); - - return; - - fail_write: - - /* remove the summary info so we are not out-of-sync with the mh folder */ - camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (folder->summary), - camel_message_info_uid (mi)); - - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("MH append message cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to mh folder: %s: %s"), - name, g_strerror (errno)); - - if (output_stream) { - camel_object_unref (CAMEL_OBJECT (output_stream)); - unlink (name); - } - - g_free (name); -} - -static CamelMimeMessage *mh_get_message(CamelFolder * folder, const gchar * uid, CamelException * ex) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *message_stream = NULL; - CamelMimeMessage *message = NULL; - CamelMessageInfo *info; - char *name; - - d(printf("getting message: %s\n", uid)); - - /* get the message summary info */ - if ((info = camel_folder_summary_uid(folder->summary, uid)) == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s\n %s"), uid, _("No such message")); - return NULL; - } - - /* we only need it to check the message exists */ - camel_folder_summary_info_free(folder->summary, info); - - name = g_strdup_printf("%s/%s", lf->folder_path, uid); - if ((message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0)) == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s\n %s"), - name, g_strerror (errno)); - g_free(name); - return NULL; - } - - message = camel_mime_message_new(); - if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, message_stream) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s\n %s"), - name, _("Invalid message contents")); - g_free(name); - camel_object_unref((CamelObject *)message_stream); - camel_object_unref((CamelObject *)message); - return NULL; - - } - camel_object_unref((CamelObject *)message_stream); - g_free(name); - - return message; -} diff --git a/camel/providers/local/camel-mh-folder.h b/camel/providers/local/camel-mh-folder.h deleted file mode 100644 index 125f8c8ac5..0000000000 --- a/camel/providers/local/camel-mh-folder.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: - * Michael Zucchi - * - * Copyright (C) 1999 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_MH_FOLDER_H -#define CAMEL_MH_FOLDER_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus } */ -#include "camel-local-folder.h" - -#define CAMEL_MH_FOLDER_TYPE (camel_mh_folder_get_type ()) -#define CAMEL_MH_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MH_FOLDER_TYPE, CamelMhFolder)) -#define CAMEL_MH_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MH_FOLDER_TYPE, CamelMhFolderClass)) -#define CAMEL_IS_MH_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_MH_FOLDER_TYPE)) - -typedef struct { - CamelLocalFolder parent_object; - -} CamelMhFolder; - -typedef struct { - CamelLocalFolderClass parent_class; - - /* Virtual methods */ - -} CamelMhFolderClass; - -/* public methods */ -CamelFolder *camel_mh_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_mh_folder_get_type(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* CAMEL_MH_FOLDER_H */ diff --git a/camel/providers/local/camel-mh-store.c b/camel/providers/local/camel-mh-store.c deleted file mode 100644 index 73a3d2046f..0000000000 --- a/camel/providers/local/camel-mh-store.c +++ /dev/null @@ -1,533 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2000 Ximian, Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "camel-mh-store.h" -#include "camel-mh-folder.h" -#include "camel-exception.h" -#include "camel-url.h" -#include "camel-private.h" - -#include -#include - -static CamelLocalStoreClass *parent_class = NULL; - -#define d(x) - -/* Returns the class for a CamelMhStore */ -#define CMHS_CLASS(so) CAMEL_MH_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMHF_CLASS(so) CAMEL_MH_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static void construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex); -static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex); -static CamelFolder *get_inbox (CamelStore *store, CamelException *ex); -static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex); -static void rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex); -static CamelFolderInfo * get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); - -static void camel_mh_store_class_init(CamelObjectClass * camel_mh_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_mh_store_class); - CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_mh_store_class); - - parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type()); - - /* virtual method overload, use defaults for most */ - camel_service_class->construct = construct; - - camel_store_class->get_folder = get_folder; - camel_store_class->get_inbox = get_inbox; - camel_store_class->delete_folder = delete_folder; - camel_store_class->rename_folder = rename_folder; - camel_store_class->get_folder_info = get_folder_info; -} - -CamelType camel_mh_store_get_type(void) -{ - static CamelType camel_mh_store_type = CAMEL_INVALID_TYPE; - - if (camel_mh_store_type == CAMEL_INVALID_TYPE) { - camel_mh_store_type = camel_type_register(CAMEL_LOCAL_STORE_TYPE, "CamelMhStore", - sizeof(CamelMhStore), - sizeof(CamelMhStoreClass), - (CamelObjectClassInitFunc) camel_mh_store_class_init, - NULL, - NULL, - NULL); - } - - return camel_mh_store_type; -} - -static void -construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex) -{ - CamelMhStore *mh_store = (CamelMhStore *)service; - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set (ex)) - return; - - if (camel_url_get_param(url, "dotfolders")) - mh_store->flags |= CAMEL_MH_DOTFOLDERS; -} - -enum { - UPDATE_NONE, - UPDATE_ADD, - UPDATE_REMOVE, -}; - -/* update the .folders file if it exists, or create it if it doesn't */ -static void -folders_update(const char *root, const char *folder, int mode) -{ - char *tmp, *tmpnew, *line = NULL; - CamelStream *stream, *in = NULL, *out = NULL; - - tmpnew = g_alloca (strlen (root) + 16); - sprintf (tmpnew, "%s.folders~", root); - - out = camel_stream_fs_new_with_name(tmpnew, O_WRONLY|O_CREAT|O_TRUNC, 0666); - if (out == NULL) - goto fail; - - tmp = g_alloca (strlen (root) + 16); - sprintf (tmp, "%s.folders", root); - stream = camel_stream_fs_new_with_name(tmp, O_RDONLY, 0); - if (stream) { - in = camel_stream_buffer_new(stream, CAMEL_STREAM_BUFFER_READ); - camel_object_unref(stream); - } - if (in == NULL || stream == NULL) { - if (mode == UPDATE_ADD && camel_stream_printf(out, "%s\n", folder) == -1) - goto fail; - goto done; - } - - while ((line = camel_stream_buffer_read_line((CamelStreamBuffer *)in))) { - int copy = TRUE; - - switch (mode) { - case UPDATE_REMOVE: - if (strcmp(line, folder) == 0) - copy = FALSE; - break; - case UPDATE_ADD: { - int cmp = strcmp(line, folder); - - if (cmp > 0) { - /* found insertion point */ - if (camel_stream_printf(out, "%s\n", folder) == -1) - goto fail; - mode = UPDATE_NONE; - } else if (tmp == 0) { - /* already there */ - mode = UPDATE_NONE; - } - break; } - case UPDATE_NONE: - break; - } - - if (copy && camel_stream_printf(out, "%s\n", line) == -1) - goto fail; - - g_free(line); - line = NULL; - } - - /* add to end? */ - if (mode == UPDATE_ADD && camel_stream_printf(out, "%s\n", folder) == -1) - goto fail; - - if (camel_stream_close(out) == -1) - goto fail; - -done: - /* should we care if this fails? I suppose so ... */ - rename(tmpnew, tmp); -fail: - unlink(tmpnew); /* remove it if its there */ - g_free(line); - if (in) - camel_object_unref(in); - if (out) - camel_object_unref(out); -} - -static CamelFolder * -get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex) -{ - char *name; - struct stat st; - - if (!((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex)) - return NULL; - - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - - if (stat(name, &st) == -1) { - if (errno != ENOENT) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open folder `%s':\n%s"), - folder_name, g_strerror (errno)); - g_free (name); - return NULL; - } - if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Folder `%s' does not exist."), folder_name); - g_free (name); - return NULL; - } - - if (mkdir(name, 0700) != 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create folder `%s':\n%s"), - folder_name, g_strerror (errno)); - g_free (name); - return NULL; - } - - /* add to .folders if we are supposed to */ - /* FIXME: throw exception on error */ - if (((CamelMhStore *)store)->flags & CAMEL_MH_DOTFOLDERS) - folders_update(((CamelLocalStore *)store)->toplevel_dir, folder_name, UPDATE_ADD); - - } else if (!S_ISDIR(st.st_mode)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("`%s' is not a directory."), name); - g_free (name); - return NULL; - } - g_free(name); - - return camel_mh_folder_new(store, folder_name, flags, ex); -} - -static CamelFolder * -get_inbox (CamelStore *store, CamelException *ex) -{ - return get_folder (store, "inbox", 0, ex); -} - -static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex) -{ - char *name; - - /* remove folder directory - will fail if not empty */ - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - if (rmdir(name) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s': %s"), - folder_name, g_strerror (errno)); - g_free(name); - return; - } - g_free(name); - - /* remove from .folders if we are supposed to */ - if (((CamelMhStore *)store)->flags & CAMEL_MH_DOTFOLDERS) - folders_update(((CamelLocalStore *)store)->toplevel_dir, folder_name, UPDATE_REMOVE); - - /* and remove metadata */ - ((CamelStoreClass *)parent_class)->delete_folder(store, folder_name, ex); -} - -static void -rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex) -{ - CamelException e; - - camel_exception_init(&e); - ((CamelStoreClass *)parent_class)->rename_folder(store, old, new, &e); - if (camel_exception_is_set(&e)) { - camel_exception_xfer(ex, &e); - return; - } - camel_exception_clear(&e); - - if (((CamelMhStore *)store)->flags & CAMEL_MH_DOTFOLDERS) { - /* yeah this is messy, but so is mh! */ - folders_update(((CamelLocalStore *)store)->toplevel_dir, new, UPDATE_ADD); - folders_update(((CamelLocalStore *)store)->toplevel_dir, old, UPDATE_REMOVE); - } -} - -static CamelFolderInfo *folder_info_new(CamelStore *store, const char *root, const char *path) -{ - CamelFolderInfo *fi; - char *base; - CamelFolder *folder; - - base = strrchr(path, '/'); - - /* Build the folder info structure. */ - fi = g_malloc0(sizeof(*fi)); - fi->url = g_strdup_printf("mh:%s#%s", root, path); - fi->full_name = g_strdup(path); - fi->name = g_strdup(base?base+1:path); - fi->unread_message_count = 0; - - /* check unread count if open */ - folder = camel_object_bag_get(store->folders, path); - if (folder) { - if ((((CamelMhStore *)store)->flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) - camel_folder_refresh_info(folder, NULL); - fi->unread_message_count = camel_folder_get_unread_message_count(folder); - camel_object_unref(folder); - } - - /* We could: if we have no folder, and FAST isn't specified, perform a full - scan of all messages for their status flags. But its probably not worth - it as we need to read the top of every file, i.e. very very slow */ - - camel_folder_info_build_path(fi, '/'); - - d(printf("New folderinfo:\n '%s'\n '%s'\n '%s'\n", fi->full_name, fi->url, fi->path)); - - return fi; -} - -/* used to find out where we've visited already */ -struct _inode { - dev_t dnode; - ino_t inode; -}; - -/* Scan path, under root, for directories to add folders for. Both - * root and path should have a trailing "/" if they aren't empty. */ -static void recursive_scan(CamelStore *store, CamelFolderInfo **fip, CamelFolderInfo *parent, GHashTable *visited, const char *root, const char *path) -{ - char *fullpath, *tmp; - DIR *dp; - struct dirent *d; - struct stat st; - CamelFolderInfo *fi; - struct _inode in, *inew; - - /* Open the specified directory. */ - if (path[0]) { - fullpath = alloca (strlen (root) + strlen (path) + 2); - sprintf (fullpath, "%s/%s", root, path); - } else - fullpath = (char *)root; - - if (stat(fullpath, &st) == -1 || !S_ISDIR(st.st_mode)) - return; - - in.dnode = st.st_dev; - in.inode = st.st_ino; - - /* see if we've visited already */ - if (g_hash_table_lookup(visited, &in) != NULL) - return; - - inew = g_malloc(sizeof(*inew)); - *inew = in; - g_hash_table_insert(visited, inew, inew); - - /* link in ... */ - fi = folder_info_new(store, root, path); - fi->parent = parent; - fi->sibling = *fip; - *fip = fi; - - if ((( ((CamelMhStore *)store)->flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) || parent == NULL)) { - /* now check content for possible other directories */ - dp = opendir(fullpath); - if (dp == NULL) - return; - - /* Look for subdirectories to add and scan. */ - while ((d = readdir(dp)) != NULL) { - /* Skip current and parent directory. */ - if (strcmp(d->d_name, ".") == 0 - || strcmp(d->d_name, "..") == 0) - continue; - - /* skip fully-numerical entries (i.e. mh messages) */ - strtoul(d->d_name, &tmp, 10); - if (*tmp == 0) - continue; - - /* otherwise, treat at potential node, and recurse, a bit more expensive than needed, but tough! */ - if (path[0]) { - tmp = g_strdup_printf("%s/%s", path, d->d_name); - recursive_scan(store, &fi->child, fi, visited, root, tmp); - g_free(tmp); - } else { - recursive_scan(store, &fi->child, fi, visited, root, d->d_name); - } - } - - closedir(dp); - } -} - -/* scan a .folders file */ -static void -folders_scan(CamelStore *store, const char *root, const char *top, CamelFolderInfo **fip) -{ - CamelFolderInfo *fi; - char line[512], *path, *tmp; - CamelStream *stream, *in; - struct stat st; - GPtrArray *folders; - GHashTable *visited; - int len; - - tmp = g_alloca (strlen (root) + 16); - sprintf (tmp, "%s/.folders", root); - stream = camel_stream_fs_new_with_name(tmp, 0, O_RDONLY); - if (stream == NULL) - return; - - in = camel_stream_buffer_new(stream, CAMEL_STREAM_BUFFER_READ); - camel_object_unref(stream); - if (in == NULL) - return; - - visited = g_hash_table_new(g_str_hash, g_str_equal); - folders = g_ptr_array_new(); - - while ( (len = camel_stream_buffer_gets((CamelStreamBuffer *)in, line, sizeof(line))) > 0) { - /* ignore blank lines */ - if (len <= 1) - continue; - /* check for invalidly long lines, we abort evreything and fallback */ - if (line[len-1] != '\n') { - int i; - - for (i=0;ilen;i++) - camel_folder_info_free(folders->pdata[i]); - g_ptr_array_set_size(folders, 0); - break; - } - line[len-1] = 0; - - /* check for \r ? */ - - if (top && top[0]) { - int toplen = strlen(top); - - /* check is subdir */ - if (strncmp(top, line, len) != 0) - continue; - - /* check is not sub-subdir if not recursive */ - if (( ((CamelMhStore *)store)->flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) == 0 - && (tmp = strrchr(line, '/')) - && tmp > line+toplen) - continue; - } - - if (g_hash_table_lookup(visited, line) != NULL) - continue; - - tmp = g_strdup(line); - g_hash_table_insert(visited, tmp, tmp); - - path = g_strdup_printf("%s/%s", root, line); - if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { - fi = folder_info_new(store, root, line); - g_ptr_array_add(folders, fi); - } - g_free(path); - } - - if (folders->len) - *fip = camel_folder_info_build(folders, NULL, '/', TRUE); - g_ptr_array_free(folders, TRUE); - - g_hash_table_foreach(visited, (GHFunc)g_free, NULL); - g_hash_table_destroy(visited); - - camel_object_unref(in); -} - -/* FIXME: move to camel-local, this is shared with maildir code */ -static guint inode_hash(const void *d) -{ - const struct _inode *v = d; - - return v->inode ^ v->dnode; -} - -static gboolean inode_equal(const void *a, const void *b) -{ - const struct _inode *v1 = a, *v2 = b; - - return v1->inode == v2->inode && v1->dnode == v2->dnode; -} - -static void inode_free(void *k, void *v, void *d) -{ - g_free(k); -} - -static CamelFolderInfo * -get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *fi = NULL; - char *root; - - root = ((CamelService *)store)->url->path; - - /* use .folders if we are supposed to */ - if (((CamelMhStore *)store)->flags & CAMEL_MH_DOTFOLDERS) { - folders_scan(store, root, top, &fi); - } else { - GHashTable *visited = g_hash_table_new(inode_hash, inode_equal); - - if (top == NULL) - top = ""; - - recursive_scan(store, &fi, NULL, visited, root, top); - - /* if we actually scanned from root, we have a "" root node we dont want */ - if (fi != NULL && top[0] == 0) { - CamelFolderInfo *rfi; - - rfi = fi; - fi = rfi->child; - rfi->child = NULL; - camel_folder_info_free(rfi); - } - - g_hash_table_foreach(visited, inode_free, NULL); - g_hash_table_destroy(visited); - } - - return fi; -} diff --git a/camel/providers/local/camel-mh-store.h b/camel/providers/local/camel-mh-store.h deleted file mode 100644 index 96522cb01f..0000000000 --- a/camel/providers/local/camel-mh-store.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2000 Ximian, Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_MH_STORE_H -#define CAMEL_MH_STORE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus } */ - -#include "camel-local-store.h" - -#define CAMEL_MH_STORE_TYPE (camel_mh_store_get_type ()) -#define CAMEL_MH_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MH_STORE_TYPE, CamelMhStore)) -#define CAMEL_MH_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MH_STORE_TYPE, CamelMhStoreClass)) -#define CAMEL_IS_MH_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_MH_STORE_TYPE)) - -enum { - CAMEL_MH_DOTFOLDERS = (1<<0), /* update/use .folders file */ -}; - -typedef struct { - CamelLocalStore parent_object; - - guint32 flags; -} CamelMhStore; - -typedef struct { - CamelLocalStoreClass parent_class; - -} CamelMhStoreClass; - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_mh_store_get_type(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* CAMEL_MH_STORE_H */ diff --git a/camel/providers/local/camel-mh-summary.c b/camel/providers/local/camel-mh-summary.c deleted file mode 100644 index 5dd26ac9ba..0000000000 --- a/camel/providers/local/camel-mh-summary.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Not Zed - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include "camel-mh-summary.h" -#include - -#include "camel-private.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#define CAMEL_MH_SUMMARY_VERSION (0x2000) - -static int mh_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int mh_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -/*static int mh_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex);*/ - -static char *mh_summary_next_uid_string(CamelFolderSummary *s); - -static void camel_mh_summary_class_init (CamelMhSummaryClass *class); -static void camel_mh_summary_init (CamelMhSummary *gspaper); -static void camel_mh_summary_finalise (CamelObject *obj); - -#define _PRIVATE(x) (((CamelMhSummary *)(x))->priv) - -struct _CamelMhSummaryPrivate { - char *current_uid; -}; - -static CamelLocalSummaryClass *parent_class; - -CamelType -camel_mh_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_local_summary_get_type (), "CamelMhSummary", - sizeof(CamelMhSummary), - sizeof(CamelMhSummaryClass), - (CamelObjectClassInitFunc)camel_mh_summary_class_init, - NULL, - (CamelObjectInitFunc)camel_mh_summary_init, - (CamelObjectFinalizeFunc)camel_mh_summary_finalise); - } - - return type; -} - -static void -camel_mh_summary_class_init (CamelMhSummaryClass *class) -{ - CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) class; - CamelLocalSummaryClass *lklass = (CamelLocalSummaryClass *)class; - - parent_class = (CamelLocalSummaryClass *)camel_type_get_global_classfuncs(camel_local_summary_get_type ()); - - /* override methods */ - sklass->next_uid_string = mh_summary_next_uid_string; - - lklass->check = mh_summary_check; - lklass->sync = mh_summary_sync; - /*lklass->add = mh_summary_add;*/ -} - -static void -camel_mh_summary_init (CamelMhSummary *o) -{ - struct _CamelFolderSummary *s = (CamelFolderSummary *) o; - - o->priv = g_malloc0(sizeof(*o->priv)); - /* set unique file version */ - s->version += CAMEL_MH_SUMMARY_VERSION; -} - -static void -camel_mh_summary_finalise(CamelObject *obj) -{ - CamelMhSummary *o = (CamelMhSummary *)obj; - - g_free(o->priv); -} - -/** - * camel_mh_summary_new: - * - * Create a new CamelMhSummary object. - * - * Return value: A new #CamelMhSummary object. - **/ -CamelMhSummary *camel_mh_summary_new (const char *filename, const char *mhdir, CamelIndex *index) -{ - CamelMhSummary *o = (CamelMhSummary *)camel_object_new(camel_mh_summary_get_type ()); - - camel_local_summary_construct((CamelLocalSummary *)o, filename, mhdir, index); - return o; -} - -static char *mh_summary_next_uid_string(CamelFolderSummary *s) -{ - CamelMhSummary *mhs = (CamelMhSummary *)s; - CamelLocalSummary *cls = (CamelLocalSummary *)s; - int fd = -1; - guint32 uid; - char *name; - char *uidstr; - - /* if we are working to add an existing file, then use current_uid */ - if (mhs->priv->current_uid) { - uidstr = g_strdup(mhs->priv->current_uid); - /* tell the summary of this, so we always append numbers to the end */ - camel_folder_summary_set_uid(s, strtoul(uidstr, NULL, 10)+1); - } else { - /* else scan for one - and create it too, to make sure */ - do { - close(fd); - uid = camel_folder_summary_next_uid(s); - name = g_strdup_printf("%s/%u", cls->folder_path, uid); - /* O_EXCL isn't guaranteed, sigh. Oh well, bad luck, mh has problems anyway */ - fd = open(name, O_WRONLY|O_CREAT|O_EXCL, 0600); - g_free(name); - } while (fd == -1 && errno == EEXIST); - - close(fd); - - uidstr = g_strdup_printf("%u", uid); - } - - return uidstr; -} - -static int camel_mh_summary_add(CamelLocalSummary *cls, const char *name, int forceindex) -{ - CamelMhSummary *mhs = (CamelMhSummary *)cls; - char *filename = g_strdup_printf("%s/%s", cls->folder_path, name); - int fd; - CamelMimeParser *mp; - - d(printf("summarising: %s\n", name)); - - fd = open(filename, O_RDONLY); - if (fd == -1) { - g_warning ("Cannot summarise/index: %s: %s", filename, strerror (errno)); - g_free(filename); - return -1; - } - mp = camel_mime_parser_new(); - camel_mime_parser_scan_from(mp, FALSE); - camel_mime_parser_init_with_fd(mp, fd); - if (cls->index && (forceindex || !camel_index_has_name(cls->index, name))) { - d(printf("forcing indexing of message content\n")); - camel_folder_summary_set_index((CamelFolderSummary *)mhs, cls->index); - } else { - camel_folder_summary_set_index((CamelFolderSummary *)mhs, NULL); - } - mhs->priv->current_uid = (char *)name; - camel_folder_summary_add_from_parser((CamelFolderSummary *)mhs, mp); - camel_object_unref((CamelObject *)mp); - mhs->priv->current_uid = NULL; - camel_folder_summary_set_index((CamelFolderSummary *)mhs, NULL); - g_free(filename); - return 0; -} - -static void -remove_summary(char *key, CamelMessageInfo *info, CamelLocalSummary *cls) -{ - d(printf("removing message %s from summary\n", key)); - if (cls->index) - camel_index_delete_name(cls->index, camel_message_info_uid(info)); - camel_folder_summary_remove((CamelFolderSummary *)cls, info); - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); -} - -static int -sort_uid_cmp(const void *ap, const void *bp) -{ - const CamelMessageInfo - *a = *((CamelMessageInfo **)ap), - *b = *((CamelMessageInfo **)bp); - const char - *auid = camel_message_info_uid(a), - *buid = camel_message_info_uid(b); - int aval = atoi(auid), bval = atoi(buid); - - return (aval < bval) ? -1 : (aval > bval) ? 1 : 0; -} - -static int -mh_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - DIR *dir; - struct dirent *d; - char *p, c; - CamelMessageInfo *info; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - GHashTable *left; - int i, count; - int forceindex; - - /* FIXME: Handle changeinfo */ - - d(printf("checking summary ...\n")); - - /* scan the directory, check for mail files not in the index, or index entries that - no longer exist */ - dir = opendir(cls->folder_path); - if (dir == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot open MH directory path: %s: %s"), - cls->folder_path, g_strerror (errno)); - return -1; - } - - /* keeps track of all uid's that have not been processed */ - left = g_hash_table_new(g_str_hash, g_str_equal); - count = camel_folder_summary_count((CamelFolderSummary *)cls); - forceindex = count == 0; - for (i=0;id_name; - while ( (c = *p++) ) { - if (!isdigit(c)) - break; - } - if (c==0) { - info = camel_folder_summary_uid((CamelFolderSummary *)cls, d->d_name); - if (info == NULL || (cls->index && (!camel_index_has_name(cls->index, d->d_name)))) { - /* need to add this file to the summary */ - if (info != NULL) { - g_hash_table_remove(left, camel_message_info_uid(info)); - camel_folder_summary_remove((CamelFolderSummary *)cls, info); - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); - } - camel_mh_summary_add(cls, d->d_name, forceindex); - } else { - const char *uid = camel_message_info_uid(info); - CamelMessageInfo *old = g_hash_table_lookup(left, uid); - - if (old) { - camel_folder_summary_info_free((CamelFolderSummary *)cls, old); - g_hash_table_remove(left, uid); - } - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); - } - } - } - closedir(dir); - g_hash_table_foreach(left, (GHFunc)remove_summary, cls); - g_hash_table_destroy(left); - - /* sort the summary based on message number (uid), since the directory order is not useful */ - CAMEL_SUMMARY_LOCK(s, summary_lock); - qsort(s->messages->pdata, s->messages->len, sizeof(CamelMessageInfo *), sort_uid_cmp); - CAMEL_SUMMARY_UNLOCK(s, summary_lock); - - return 0; -} - -static int -mh_summary_sync_message(CamelLocalSummary *cls, CamelMessageInfo *info, CamelException *ex) -{ - CamelMimeParser *mp; - const char *xev, *buffer; - int xevoffset; - int fd, outfd, len, outlen, ret=0; - char *name, *tmpname, *xevnew; - - name = g_strdup_printf("%s/%s", cls->folder_path, camel_message_info_uid(info)); - fd = open(name, O_RDWR); - if (fd == -1) - return -1; - - mp = camel_mime_parser_new(); - camel_mime_parser_init_with_fd(mp, fd); - if (camel_mime_parser_step(mp, 0, 0) != CAMEL_MIME_PARSER_STATE_EOF) { - xev = camel_mime_parser_header(mp, "X-Evolution", &xevoffset); - d(printf("xev = '%s'\n", xev)); - xevnew = camel_local_summary_encode_x_evolution(cls, info); - if (xev == NULL - || camel_local_summary_decode_x_evolution(cls, xev, NULL) == -1 - || strlen(xev)-1 != strlen(xevnew)) { - - d(printf("camel local summary_decode_xev = %d\n", camel_local_summary_decode_x_evolution(cls, xev, NULL))); - - /* need to write a new copy/unlink old */ - tmpname = g_strdup_printf("%s/.tmp.%d.%s", cls->folder_path, getpid(), camel_message_info_uid(info)); - d(printf("old xev was %d %s new xev is %d %s\n", strlen(xev), xev, strlen(xevnew), xevnew)); - d(printf("creating new message %s\n", tmpname)); - outfd = open(tmpname, O_CREAT|O_WRONLY|O_TRUNC, 0600); - if (outfd != -1) { - outlen = 0; - len = camel_local_summary_write_headers(outfd, camel_mime_parser_headers_raw(mp), xevnew, NULL, NULL); - if (len != -1) { - while (outlen != -1 && (len = camel_mime_parser_read(mp, &buffer, 10240)) > 0) { - d(printf("camel mime parser read, read %d bytes: %.*s\n", len, len, buffer)); - do { - outlen = write(outfd, buffer, len); - } while (outlen == -1 && errno == EINTR); - } - } - - d(printf("len = %d outlen = %d, renaming/finishing\n", len, outlen)); - if (close(outfd) == -1 - || len == -1 - || outlen == -1 - || rename(tmpname, name) == -1) { - unlink(tmpname); - ret = -1; - } - } else { - g_warning("sync can't create tmp file: %s", strerror (errno)); - } - g_free(tmpname); - } else { - d(printf("stamping in updated X-EV at %d\n", (int)xevoffset)); - /* else, we can just update the flags field */ - lseek(fd, xevoffset+strlen("X-Evolution: "), SEEK_SET); - do { - len = write(fd, xevnew, strlen(xevnew)); - } while (len == -1 && errno == EINTR); - if (len == -1) - ret = -1; - } - - g_free(xevnew); - } - - camel_object_unref((CamelObject *)mp); - g_free(name); - return ret; -} - -/* sync the summary file with the ondisk files */ -static int -mh_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changes, CamelException *ex) -{ - int count, i; - CamelMessageInfo *info; - char *name; - const char *uid; - - d(printf("summary_sync(expunge=%s)\n", expunge?"true":"false")); - - /* we could probably get away without this ... but why not use it, esp if we're going to - be doing any significant io already */ - if (camel_local_summary_check(cls, changes, ex) == -1) - return -1; - - count = camel_folder_summary_count((CamelFolderSummary *)cls); - for (i=count-1;i>=0;i--) { - info = camel_folder_summary_index((CamelFolderSummary *)cls, i); - g_assert(info); - if (expunge && (info->flags & CAMEL_MESSAGE_DELETED)) { - uid = camel_message_info_uid(info); - name = g_strdup_printf("%s/%s", cls->folder_path, uid); - d(printf("deleting %s\n", name)); - if (unlink(name) == 0 || errno==ENOENT) { - - /* FIXME: put this in folder_summary::remove()? */ - if (cls->index) - camel_index_delete_name(cls->index, (char *)uid); - - camel_folder_change_info_remove_uid(changes, uid); - camel_folder_summary_remove((CamelFolderSummary *)cls, info); - } - g_free(name); - } else if (info->flags & (CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_FLAGGED)) { - if (mh_summary_sync_message(cls, info, ex) != -1) { - info->flags &= 0xffff; - } else { - g_warning("Problem occured when trying to expunge, ignored"); - } - } - camel_folder_summary_info_free((CamelFolderSummary *)cls, info); - } - - return ((CamelLocalSummaryClass *)parent_class)->sync(cls, expunge, changes, ex); -} diff --git a/camel/providers/local/camel-mh-summary.h b/camel/providers/local/camel-mh-summary.h deleted file mode 100644 index 4ee30df63b..0000000000 --- a/camel/providers/local/camel-mh-summary.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Not Zed - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_MH_SUMMARY_H -#define _CAMEL_MH_SUMMARY_H - -#include "camel-local-summary.h" -#include -#include -#include - -#define CAMEL_MH_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_mh_summary_get_type (), CamelMhSummary) -#define CAMEL_MH_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_mh_summary_get_type (), CamelMhSummaryClass) -#define CAMEL_IS_MH_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_mh_summary_get_type ()) - -typedef struct _CamelMhSummary CamelMhSummary; -typedef struct _CamelMhSummaryClass CamelMhSummaryClass; - -struct _CamelMhSummary { - CamelLocalSummary parent; - struct _CamelMhSummaryPrivate *priv; -}; - -struct _CamelMhSummaryClass { - CamelLocalSummaryClass parent_class; - - /* virtual methods */ - - /* signals */ -}; - -CamelType camel_mh_summary_get_type (void); -CamelMhSummary *camel_mh_summary_new (const char *filename, const char *mhdir, CamelIndex *index); - -#endif /* ! _CAMEL_MH_SUMMARY_H */ - diff --git a/camel/providers/local/camel-spool-folder.c b/camel/providers/local/camel-spool-folder.c deleted file mode 100644 index 4c4a49fbf9..0000000000 --- a/camel/providers/local/camel-spool-folder.c +++ /dev/null @@ -1,186 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Authors: Michael Zucchi - * - * Copyright (C) 2001-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "camel-spool-folder.h" -#include "camel-spool-store.h" -#include "camel-stream-fs.h" -#include "camel-spool-summary.h" -#include "camel-data-wrapper.h" -#include "camel-mime-message.h" -#include "camel-stream-filter.h" -#include "camel-mime-filter-from.h" -#include "camel-exception.h" - -#include "camel-lock-client.h" - -#include "camel-local-private.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -static CamelFolderClass *parent_class = NULL; - -/* Returns the class for a CamelSpoolFolder */ -#define CSPOOLF_CLASS(so) CAMEL_SPOOL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CSPOOLS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static CamelLocalSummary *spool_create_summary(const char *path, const char *folder, CamelIndex *index); - -static int spool_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex); -static void spool_unlock(CamelLocalFolder *lf); - -static void spool_finalize(CamelObject * object); - -static void -camel_spool_folder_class_init(CamelSpoolFolderClass *klass) -{ - CamelLocalFolderClass *lklass = (CamelLocalFolderClass *)klass; - - parent_class = (CamelFolderClass *)camel_mbox_folder_get_type(); - - /* virtual method overload */ - lklass->create_summary = spool_create_summary; - lklass->lock = spool_lock; - lklass->unlock = spool_unlock; -} - -static void -spool_init(gpointer object, gpointer klass) -{ - CamelSpoolFolder *spool_folder = object; - - spool_folder->lockid = -1; -} - -static void -spool_finalize(CamelObject * object) -{ - /*CamelSpoolFolder *spool_folder = CAMEL_SPOOL_FOLDER(object);*/ -} - -CamelType camel_spool_folder_get_type(void) -{ - static CamelType camel_spool_folder_type = CAMEL_INVALID_TYPE; - - if (camel_spool_folder_type == CAMEL_INVALID_TYPE) { - camel_spool_folder_type = camel_type_register(camel_mbox_folder_get_type(), "CamelSpoolFolder", - sizeof(CamelSpoolFolder), - sizeof(CamelSpoolFolderClass), - (CamelObjectClassInitFunc) camel_spool_folder_class_init, - NULL, - (CamelObjectInitFunc) spool_init, - (CamelObjectFinalizeFunc) spool_finalize); - } - - return camel_spool_folder_type; -} - -CamelFolder * -camel_spool_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) -{ - CamelFolder *folder; - - d(printf("Creating spool folder: %s in %s\n", full_name, camel_local_store_get_toplevel_dir((CamelLocalStore *)parent_store))); - - folder = (CamelFolder *)camel_object_new(CAMEL_SPOOL_FOLDER_TYPE); - - if (parent_store->flags & CAMEL_STORE_FILTER_INBOX - && strcmp(full_name, "INBOX") == 0) - folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT; - flags &= CAMEL_STORE_FOLDER_BODY_INDEX; - - folder = (CamelFolder *)camel_local_folder_construct((CamelLocalFolder *)folder, parent_store, full_name, flags, ex); - if (folder) { - if (camel_url_get_param(((CamelService *)parent_store)->url, "xstatus")) - camel_mbox_summary_xstatus((CamelMboxSummary *)folder->summary, TRUE); - } - - return folder; -} - -static CamelLocalSummary * -spool_create_summary(const char *path, const char *folder, CamelIndex *index) -{ - return (CamelLocalSummary *)camel_spool_summary_new(folder); -} - -static int -spool_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex) -{ - int retry = 0; - CamelMboxFolder *mf = (CamelMboxFolder *)lf; - CamelSpoolFolder *sf = (CamelSpoolFolder *)lf; - - mf->lockfd = open(lf->folder_path, O_RDWR, 0); - if (mf->lockfd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder lock on %s: %s"), - lf->folder_path, g_strerror (errno)); - return -1; - } - - while (retry < CAMEL_LOCK_RETRY) { - if (retry > 0) - sleep(CAMEL_LOCK_DELAY); - - camel_exception_clear(ex); - - if (camel_lock_fcntl(mf->lockfd, type, ex) == 0) { - if (camel_lock_flock(mf->lockfd, type, ex) == 0) { - if ((sf->lockid = camel_lock_helper_lock(lf->folder_path, ex)) != -1) - return 0; - camel_unlock_flock(mf->lockfd); - } - camel_unlock_fcntl(mf->lockfd); - } - retry++; - } - - return -1; -} - -static void -spool_unlock(CamelLocalFolder *lf) -{ - CamelMboxFolder *mf = (CamelMboxFolder *)lf; - CamelSpoolFolder *sf = (CamelSpoolFolder *)lf; - - camel_lock_helper_unlock(sf->lockid); - sf->lockid = -1; - camel_unlock_flock(mf->lockfd); - camel_unlock_fcntl(mf->lockfd); - - close(mf->lockfd); - mf->lockfd = -1; -} diff --git a/camel/providers/local/camel-spool-folder.h b/camel/providers/local/camel-spool-folder.h deleted file mode 100644 index e778cdecf7..0000000000 --- a/camel/providers/local/camel-spool-folder.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Author: Michael Zucchi - * - * Copyright (C) 2001 Ximian Inc (www.ximian.com/) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_SPOOL_FOLDER_H -#define CAMEL_SPOOL_FOLDER_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-mbox-folder.h" -#include -#include -#include "camel-spool-summary.h" -#include "camel-lock.h" - -/* #include "camel-store.h" */ - -#define CAMEL_SPOOL_FOLDER_TYPE (camel_spool_folder_get_type ()) -#define CAMEL_SPOOL_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SPOOL_FOLDER_TYPE, CamelSpoolFolder)) -#define CAMEL_SPOOL_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SPOOL_FOLDER_TYPE, CamelSpoolFolderClass)) -#define CAMEL_IS_SPOOL_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_SPOOL_FOLDER_TYPE)) - -typedef struct { - CamelMboxFolder parent; - - struct _CamelSpoolFolderPrivate *priv; - - int lockid; /* lock id for dot locking */ -} CamelSpoolFolder; - -typedef struct { - CamelMboxFolderClass parent_class; -} CamelSpoolFolderClass; - -/* Standard Camel function */ -CamelType camel_spool_folder_get_type(void); - -CamelFolder *camel_spool_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SPOOL_FOLDER_H */ diff --git a/camel/providers/local/camel-spool-store.c b/camel/providers/local/camel-spool-store.c deleted file mode 100644 index 09720e4a01..0000000000 --- a/camel/providers/local/camel-spool-store.c +++ /dev/null @@ -1,483 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi - * - * Copyright (C) 2001 Ximian Inc (www.ximian.com/) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_ALLOCA_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "camel-spool-store.h" -#include "camel-spool-folder.h" -#include "camel-exception.h" -#include "camel-url.h" -#include "camel-private.h" - -#define d(x) - -/* Returns the class for a CamelSpoolStore */ -#define CSPOOLS_CLASS(so) CAMEL_SPOOL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static void construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex); -static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex); -static char *get_name(CamelService *service, gboolean brief); -static CamelFolder *get_inbox (CamelStore *store, CamelException *ex); -static void rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex); -static CamelFolderInfo *get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); -static void free_folder_info (CamelStore *store, CamelFolderInfo *fi); - -static void delete_folder(CamelStore *store, const char *folder_name, CamelException *ex); -static void rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex); - -static CamelStoreClass *parent_class = NULL; - -static void -camel_spool_store_class_init (CamelSpoolStoreClass *camel_spool_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_spool_store_class); - CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS (camel_spool_store_class); - - parent_class = CAMEL_STORE_CLASS(camel_mbox_store_get_type()); - - /* virtual method overload */ - camel_service_class->construct = construct; - camel_service_class->get_name = get_name; - camel_store_class->get_folder = get_folder; - camel_store_class->get_inbox = get_inbox; - camel_store_class->get_folder_info = get_folder_info; - camel_store_class->free_folder_info = free_folder_info; - - camel_store_class->delete_folder = delete_folder; - camel_store_class->rename_folder = rename_folder; -} - -CamelType -camel_spool_store_get_type (void) -{ - static CamelType camel_spool_store_type = CAMEL_INVALID_TYPE; - - if (camel_spool_store_type == CAMEL_INVALID_TYPE) { - camel_spool_store_type = camel_type_register (camel_mbox_store_get_type(), "CamelSpoolStore", - sizeof (CamelSpoolStore), - sizeof (CamelSpoolStoreClass), - (CamelObjectClassInitFunc) camel_spool_store_class_init, - NULL, - NULL, - NULL); - } - - return camel_spool_store_type; -} - -static void -construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex) -{ - struct stat st; - - d(printf("constructing store of type %s '%s:%s'\n", - camel_type_to_name(((CamelObject *)service)->s.type), url->protocol, url->path)); - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set (ex)) - return; - - if (service->url->path[0] != '/') { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store root %s is not an absolute path"), service->url->path); - return; - } - - if (stat(service->url->path, &st) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Spool `%s' cannot be opened: %s"), - service->url->path, g_strerror (errno)); - return; - } - - if (S_ISREG(st.st_mode)) - ((CamelSpoolStore *)service)->type = CAMEL_SPOOL_STORE_MBOX; - else if (S_ISDIR(st.st_mode)) - /* we could check here for slight variations */ - ((CamelSpoolStore *)service)->type = CAMEL_SPOOL_STORE_ELM; - else { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Spool `%s' is not a regular file or directory"), - service->url->path); - return; - } -} - -static CamelFolder * -get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex) -{ - CamelFolder *folder = NULL; - struct stat st; - char *name; - - d(printf("opening folder %s on path %s\n", folder_name, path)); - - /* we only support an 'INBOX' in mbox mode */ - if (((CamelSpoolStore *)store)->type == CAMEL_SPOOL_STORE_MBOX) { - if (strcmp(folder_name, "INBOX") != 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Folder `%s/%s' does not exist."), - ((CamelService *)store)->url->path, folder_name); - } else { - folder = camel_spool_folder_new(store, folder_name, flags, ex); - } - } else { - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - if (stat(name, &st) == -1) { - if (errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open folder `%s':\n%s"), - folder_name, g_strerror (errno)); - } else if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Folder `%s' does not exist."), - folder_name); - } else { - if (creat (name, 0600) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create folder `%s':\n%s"), - folder_name, g_strerror (errno)); - } else { - folder = camel_spool_folder_new(store, folder_name, flags, ex); - } - } - } else if (!S_ISREG(st.st_mode)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("`%s' is not a mailbox file."), name); - } else { - folder = camel_spool_folder_new(store, folder_name, flags, ex); - } - g_free(name); - } - - return folder; -} - -static CamelFolder * -get_inbox(CamelStore *store, CamelException *ex) -{ - if (((CamelSpoolStore *)store)->type == CAMEL_SPOOL_STORE_MBOX) - return get_folder (store, "INBOX", CAMEL_STORE_FOLDER_CREATE, ex); - else { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store does not support an INBOX")); - return NULL; - } -} - -static char * -get_name (CamelService *service, gboolean brief) -{ - if (brief) - return g_strdup(service->url->path); - else - return g_strdup_printf(((CamelSpoolStore *)service)->type == CAMEL_SPOOL_STORE_MBOX? - _("Spool mail file %s"):_("Spool folder tree %s"), service->url->path); -} - -/* default implementation, rename all */ -static void -rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex) -{ - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Spool folders cannot be renamed")); -} - -/* default implementation, only delete metadata */ -static void -delete_folder(CamelStore *store, const char *folder_name, CamelException *ex) -{ - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Spool folders cannot be deleted")); -} - -static void free_folder_info (CamelStore *store, CamelFolderInfo *fi) -{ - if (fi) { - g_free(fi->url); - g_free(fi->name); - g_free(fi->full_name); - g_free(fi->path); - g_free(fi); - } -} - -static CamelFolderInfo * -camel_folder_info_new(const char *url, const char *full, const char *name, int unread) -{ - CamelFolderInfo *fi; - - fi = g_malloc0(sizeof(*fi)); - fi->url = g_strdup(url); - fi->full_name = g_strdup(full); - fi->name = g_strdup(name); - fi->unread_message_count = unread; - camel_folder_info_build_path(fi, '/'); - - d(printf("Adding spoold info: '%s' '%s' '%s' '%s'\n", fi->path, fi->name, fi->full_name, fi->url)); - - return fi; -} - -/* used to find out where we've visited already */ -struct _inode { - dev_t dnode; - ino_t inode; -}; - -/* returns number of records found at or below this level */ -static int scan_dir(CamelStore *store, GHashTable *visited, char *root, const char *path, guint32 flags, CamelFolderInfo *parent, CamelFolderInfo **fip, CamelException *ex) -{ - DIR *dir; - struct dirent *d; - char *name, *uri, *tmp, *fname; - CamelFolderInfo *fi = NULL; - struct stat st; - CamelFolder *folder; - int unread; - char from[80]; - FILE *fp; - - d(printf("checking dir '%s' part '%s' for mbox content\n", root, path)); - - /* look for folders matching the right structure, recursively */ - if (path) { - name = alloca(strlen(root) + strlen(path) + 2); - sprintf(name, "%s/%s", root, path); - } else - name = root; - - if (stat(name, &st) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not scan folder `%s': %s"), - name, g_strerror (errno)); - } else if (S_ISREG(st.st_mode)) { - /* incase we start scanning from a file. messy duplication :-/ */ - if (path) { - folder = camel_object_bag_get(store->folders, path); - if (folder) { - /* should this refresh if ! FAST? */ - unread = camel_folder_get_unread_message_count(folder); - camel_object_unref(folder); - } else - unread = -1; - tmp = strrchr(path, '/'); - if (tmp) - tmp++; - else - tmp = (char *)path; - uri = g_strdup_printf("%s:%s#%s", ((CamelService *)store)->url->protocol, root, path); - fi = camel_folder_info_new(uri, path, tmp, unread); - fi->parent = parent; - fi->sibling = *fip; - *fip = fi; - g_free(uri); - } - return 0; - } - - dir = opendir(name); - if (dir == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not scan folder `%s': %s"), - name, g_strerror (errno)); - return -1; - } - - if (path != NULL) { - uri = g_strdup_printf("%s:%s;noselect=yes#%s", ((CamelService *)store)->url->protocol, root, path); - tmp = strrchr(path, '/'); - if (tmp == NULL) - tmp = (char *)path; - else - tmp++; - fi = camel_folder_info_new(uri, path, tmp, -1); - fi->parent = parent; - fi->sibling = *fip; - *fip = fi; - g_free(uri); - - fip = &fi->child; - parent = fi; - } - - while ( (d = readdir(dir)) ) { - if (strcmp(d->d_name, ".") == 0 - || strcmp(d->d_name, "..") == 0) - continue; - - tmp = g_strdup_printf("%s/%s", name, d->d_name); - if (stat(tmp, &st) == 0) { - if (path) - fname = g_strdup_printf("%s/%s", path, d->d_name); - else - fname = g_strdup(d->d_name); - - if (S_ISREG(st.st_mode)) { - /* first, see if we already have it open */ - folder = camel_object_bag_get(store->folders, fname); - if (folder) { - /* should this refresh if ! FAST? */ - unread = camel_folder_get_unread_message_count(folder); - camel_object_unref(folder); - } else - unread = -1; - - /* no? check its content to see if its a folder or not */ - if (folder == NULL) { - fp = fopen(tmp, "r"); - if (fp != NULL) { - if (st.st_size == 0 - || (fgets(from, sizeof(from), fp) != NULL - && strncmp(from, "From ", 5) == 0)) { - folder = (CamelFolder *)1; - /* TODO: if slow mode selected, we could look up unread counts here - - but its pretty expensive */ - } - fclose(fp); - } - } - - if (folder != NULL) { - uri = g_strdup_printf("%s:%s#%s", ((CamelService *)store)->url->protocol, root, fname); - fi = camel_folder_info_new(uri, fname, d->d_name, unread); - fi->parent = parent; - fi->sibling = *fip; - *fip = fi; - g_free(uri); - } - - } else if (S_ISDIR(st.st_mode)) { - struct _inode in = { st.st_dev, st.st_ino }; - - /* see if we've visited already */ - if (g_hash_table_lookup(visited, &in) == NULL) { - struct _inode *inew = g_malloc(sizeof(*inew)); - - *inew = in; - g_hash_table_insert(visited, inew, inew); - - if (scan_dir(store, visited, root, fname, flags, parent, fip, ex) == -1) { - g_free(tmp); - g_free(fname); - closedir(dir); - return -1; - } - } - } - g_free(fname); - - } - g_free(tmp); - } - closedir(dir); - - return 0; -} - -static guint inode_hash(const void *d) -{ - const struct _inode *v = d; - - return v->inode ^ v->dnode; -} - -static gboolean inode_equal(const void *a, const void *b) -{ - const struct _inode *v1 = a, *v2 = b; - - return v1->inode == v2->inode && v1->dnode == v2->dnode; -} - -static void inode_free(void *k, void *v, void *d) -{ - g_free(k); -} - -static CamelFolderInfo * -get_folder_info_elm(CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *fi = NULL; - GHashTable *visited; - - visited = g_hash_table_new(inode_hash, inode_equal); - - if (scan_dir(store, visited, ((CamelService *)store)->url->path, top, flags, NULL, &fi, ex) == -1 && fi != NULL) { - camel_store_free_folder_info_full(store, fi); - fi = NULL; - } - - g_hash_table_foreach(visited, inode_free, NULL); - g_hash_table_destroy(visited); - - return fi; -} - -static CamelFolderInfo * -get_folder_info_mbox(CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *fi = NULL; - CamelService *service = (CamelService *)store; - CamelFolder *folder; - - if (top == NULL || strcmp(top, "INBOX") == 0) { - fi = g_malloc0(sizeof(*fi)); - fi->full_name = g_strdup("INBOX"); - fi->name = g_strdup("INBOX"); - fi->url = g_strdup_printf("%s:%s#%s", service->url->protocol, service->url->path, fi->name); - - folder = camel_object_bag_get(store->folders, fi->full_name); - if (folder) { - fi->unread_message_count = camel_folder_get_unread_message_count(folder); - camel_object_unref(folder); - } else - fi->unread_message_count = -1; - - camel_folder_info_build_path(fi, '/'); - } - - return fi; -} - -static CamelFolderInfo * -get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - if (((CamelSpoolStore *)store)->type == CAMEL_SPOOL_STORE_MBOX) - return get_folder_info_mbox(store, top, flags, ex); - else - return get_folder_info_elm(store, top, flags, ex); -} diff --git a/camel/providers/local/camel-spool-store.h b/camel/providers/local/camel-spool-store.h deleted file mode 100644 index 1e1753481b..0000000000 --- a/camel/providers/local/camel-spool-store.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi - * - * Copyright (C) 2001 Ximian Inc (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_SPOOL_STORE_H -#define CAMEL_SPOOL_STORE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-mbox-store.h" - -#define CAMEL_SPOOL_STORE_TYPE (camel_spool_store_get_type ()) -#define CAMEL_SPOOL_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SPOOL_STORE_TYPE, CamelSpoolStore)) -#define CAMEL_SPOOL_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SPOOL_STORE_TYPE, CamelSpoolStoreClass)) -#define CAMEL_IS_SPOOL_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_SPOOL_STORE_TYPE)) - -typedef enum _camel_spool_store_t { - CAMEL_SPOOL_STORE_MBOX, /* a single mbox */ - CAMEL_SPOOL_STORE_ELM, /* elm/pine/etc tree of mbox files in folders */ -} camel_spool_store_t; - -typedef struct { - CamelMboxStore parent_object; - - camel_spool_store_t type; -} CamelSpoolStore; - - - -typedef struct { - CamelMboxStoreClass parent_class; - -} CamelSpoolStoreClass; - - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_spool_store_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SPOOL_STORE_H */ - - diff --git a/camel/providers/local/camel-spool-summary.c b/camel/providers/local/camel-spool-summary.c deleted file mode 100644 index 7991a881cc..0000000000 --- a/camel/providers/local/camel-spool-summary.c +++ /dev/null @@ -1,344 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Copyright (C) 2001 Ximian Inc. (www.ximian.com) - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "camel-spool-summary.h" -#include "camel-mime-message.h" -#include "camel-file-utils.h" -#include "camel-operation.h" - -#define io(x) -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#define CAMEL_SPOOL_SUMMARY_VERSION (0x400) - -static int spool_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex); -static int spool_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); - -static int spool_summary_sync_full(CamelMboxSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); - -static void camel_spool_summary_class_init (CamelSpoolSummaryClass *klass); -static void camel_spool_summary_init (CamelSpoolSummary *obj); -static void camel_spool_summary_finalise (CamelObject *obj); - -static CamelFolderSummaryClass *camel_spool_summary_parent; - -CamelType -camel_spool_summary_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_mbox_summary_get_type(), "CamelSpoolSummary", - sizeof (CamelSpoolSummary), - sizeof (CamelSpoolSummaryClass), - (CamelObjectClassInitFunc) camel_spool_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_spool_summary_init, - (CamelObjectFinalizeFunc) camel_spool_summary_finalise); - } - - return type; -} - -static void -camel_spool_summary_class_init(CamelSpoolSummaryClass *klass) -{ - CamelLocalSummaryClass *lklass = (CamelLocalSummaryClass *)klass; - CamelMboxSummaryClass *mklass = (CamelMboxSummaryClass *)klass; - - camel_spool_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_mbox_summary_get_type()); - - lklass->load = spool_summary_load; - lklass->check = spool_summary_check; - - mklass->sync_full = spool_summary_sync_full; -} - -static void -camel_spool_summary_init(CamelSpoolSummary *obj) -{ - struct _CamelFolderSummary *s = (CamelFolderSummary *)obj; - - /* message info size is from mbox parent */ - - /* and a unique file version */ - s->version += CAMEL_SPOOL_SUMMARY_VERSION; -} - -static void -camel_spool_summary_finalise(CamelObject *obj) -{ - /*CamelSpoolSummary *mbs = CAMEL_SPOOL_SUMMARY(obj);*/ -} - -CamelSpoolSummary * -camel_spool_summary_new(const char *mbox_name) -{ - CamelSpoolSummary *new = (CamelSpoolSummary *)camel_object_new(camel_spool_summary_get_type()); - - camel_local_summary_construct((CamelLocalSummary *)new, NULL, mbox_name, NULL); - return new; -} - -static int -spool_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex) -{ - g_warning("spool summary - not loading anything\n"); - return 0; -} - -/* perform a full sync */ -static int -spool_summary_sync_full(CamelMboxSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int fd = -1, fdout = -1; - char *tmpname = NULL; - char *buffer, *p; - off_t spoollen, outlen; - int size, sizeout; - struct stat st; - guint32 flags = (expunge?1:0); - - d(printf("performing full summary/sync\n")); - - camel_operation_start(NULL, _("Storing folder")); - - fd = open(((CamelLocalSummary *)cls)->folder_path, O_RDWR); - if (fd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open file: %s: %s"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno)); - camel_operation_end(NULL); - return -1; - } - -#ifdef HAVE_MKSTEMP - tmpname = alloca (64); - sprintf (tmpname, "/tmp/spool.camel.XXXXXX"); - fdout = mkstemp (tmpname); -#else -#warning "Your system has no mkstemp(3), spool updating may be insecure" - tmpname = alloca (L_tmpnam); - tmpnam (tmpname); - fdout = open (tmpname, O_RDWR|O_CREAT|O_EXCL, 0600); -#endif - d(printf("Writing tmp file to %s\n", tmpname)); - if (fdout == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot open temporary mailbox: %s"), - g_strerror (errno)); - goto error; - } - - if (camel_mbox_summary_sync_mbox((CamelMboxSummary *)cls, flags, changeinfo, fd, fdout, ex) == -1) - goto error; - - - /* sync out content */ - if (fsync(fdout) == -1) { - g_warning("Cannot sync temporary folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync temporary folder %s: %s"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno)); - goto error; - } - - /* see if we can write this much to the spool file */ - if (fstat(fd, &st) == -1) { - g_warning("Cannot sync temporary folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync temporary folder %s: %s"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno)); - goto error; - } - spoollen = st.st_size; - - if (fstat(fdout, &st) == -1) { - g_warning("Cannot sync temporary folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync temporary folder %s: %s"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno)); - goto error; - } - outlen = st.st_size; - - /* I think this is the right way to do this - checking that the file will fit the new data */ - if (outlen>0 - && (lseek(fd, outlen-1, SEEK_SET) == -1 - || write(fd, "", 1) != 1 - || fsync(fd) == -1 - || lseek(fd, 0, SEEK_SET) == -1 - || lseek(fdout, 0, SEEK_SET) == -1)) { - g_warning("Cannot sync spool folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync spool folder %s: %s"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno)); - /* incase we ran out of room, remove any trailing space first */ - ftruncate(fd, spoollen); - goto error; - } - - - /* now copy content back */ - buffer = g_malloc(8192); - size = 1; - while (size>0) { - do { - size = read(fdout, buffer, 8192); - } while (size == -1 && errno == EINTR); - - if (size > 0) { - p = buffer; - do { - sizeout = write(fd, p, size); - if (sizeout > 0) { - p+= sizeout; - size -= sizeout; - } - } while ((sizeout == -1 && errno == EINTR) && size > 0); - size = sizeout; - } - - if (size == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync spool folder %s: %s\n" - "Folder may be corrupt, copy saved in `%s'"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno), tmpnam); - /* so we dont delete it */ - close(fdout); - tmpname = NULL; - fdout = -1; - g_free(buffer); - goto error; - } - } - - g_free(buffer); - - d(printf("Closing folders\n")); - - if (ftruncate(fd, outlen) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync spool folder %s: %s\n" - "Folder may be corrupt, copy saved in `%s'"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno), tmpnam); - close(fdout); - tmpname = NULL; - fdout = -1; - goto error; - } - - if (close(fd) == -1) { - g_warning("Cannot close source folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync spool folder %s: %s\n" - "Folder may be corrupt, copy saved in `%s'"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno), tmpnam); - close(fdout); - tmpname = NULL; - fdout = -1; - fd = -1; - goto error; - } - - close(fdout); - unlink(tmpname); - - camel_operation_end(NULL); - - return 0; - error: - if (fd != -1) - close(fd); - - if (fdout != -1) - close(fdout); - - if (tmpname) - unlink(tmpname); - - camel_operation_end(NULL); - - return -1; -} - -static int -spool_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int i, work, count; - struct stat st; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - - if (((CamelLocalSummaryClass *)camel_spool_summary_parent)->check(cls, changeinfo, ex) == -1) - return -1; - - /* check to see if we need to copy/update the file; missing xev headers prompt this */ - work = FALSE; - count = camel_folder_summary_count(s); - for (i=0;!work && iflags & (CAMEL_MESSAGE_FOLDER_NOXEV)) != 0; - camel_folder_summary_info_free(s, info); - } - - /* if we do, then write out the headers using sync_full, etc */ - if (work) { - d(printf("Have to add new headers, re-syncing from the start to accomplish this\n")); - if (((CamelMboxSummaryClass *)((CamelObject *)cls)->klass)->sync_full((CamelMboxSummary *)cls, FALSE, changeinfo, ex) == -1) - return -1; - - if (stat(cls->folder_path, &st) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unknown error: %s"), - g_strerror (errno)); - return -1; - } - - ((CamelMboxSummary *)cls)->folder_size = st.st_size; - ((CamelFolderSummary *)cls)->time = st.st_mtime; - } - - return 0; -} diff --git a/camel/providers/local/camel-spool-summary.h b/camel/providers/local/camel-spool-summary.h deleted file mode 100644 index b72aeda527..0000000000 --- a/camel/providers/local/camel-spool-summary.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2001 Ximian Inc. (www.ximian.com) - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_SPOOL_SUMMARY_H -#define _CAMEL_SPOOL_SUMMARY_H - -#include -#include -#include -#include -#include "camel-mbox-summary.h" - -#define CAMEL_SPOOL_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_spool_summary_get_type (), CamelSpoolSummary) -#define CAMEL_SPOOL_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_spool_summary_get_type (), CamelSpoolSummaryClass) -#define CAMEL_IS_SPOOL_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_spool_summary_get_type ()) - -typedef struct _CamelSpoolSummary CamelSpoolSummary; -typedef struct _CamelSpoolSummaryClass CamelSpoolSummaryClass; - -struct _CamelSpoolSummary { - CamelMboxSummary parent; - -}; - -struct _CamelSpoolSummaryClass { - CamelMboxSummaryClass parent_class; -}; - -CamelType camel_spool_summary_get_type (void); -void camel_spool_summary_construct (CamelSpoolSummary *new, const char *filename, const char *spool_name, CamelIndex *index); - -/* create the summary, in-memory only */ -CamelSpoolSummary *camel_spool_summary_new(const char *filename); - -/* load/check the summary */ -int camel_spool_summary_load(CamelSpoolSummary *cls, int forceindex, CamelException *ex); -/* check for new/removed messages */ -int camel_spool_summary_check(CamelSpoolSummary *cls, CamelFolderChangeInfo *, CamelException *ex); -/* perform a folder sync or expunge, if needed */ -int camel_spool_summary_sync(CamelSpoolSummary *cls, gboolean expunge, CamelFolderChangeInfo *, CamelException *ex); -/* add a new message to the summary */ -CamelMessageInfo *camel_spool_summary_add(CamelSpoolSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - -/* generate an X-Evolution header line */ -char *camel_spool_summary_encode_x_evolution(CamelSpoolSummary *cls, const CamelMessageInfo *info); -int camel_spool_summary_decode_x_evolution(CamelSpoolSummary *cls, const char *xev, CamelMessageInfo *info); - -/* utility functions - write headers to a file with optional X-Evolution header */ -int camel_spool_summary_write_headers(int fd, struct _camel_header_raw *header, char *xevline); - -#endif /* ! _CAMEL_SPOOL_SUMMARY_H */ - diff --git a/camel/providers/local/libcamellocal.urls b/camel/providers/local/libcamellocal.urls deleted file mode 100644 index e2279ed72a..0000000000 --- a/camel/providers/local/libcamellocal.urls +++ /dev/null @@ -1,5 +0,0 @@ -mh -mbox -maildir -spool -spoold diff --git a/camel/providers/nntp/.cvsignore b/camel/providers/nntp/.cvsignore deleted file mode 100644 index 2fbeab8712..0000000000 --- a/camel/providers/nntp/.cvsignore +++ /dev/null @@ -1,12 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -test-newsrc -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/nntp/Makefile.am b/camel/providers/nntp/Makefile.am deleted file mode 100644 index 464624b82d..0000000000 --- a/camel/providers/nntp/Makefile.am +++ /dev/null @@ -1,36 +0,0 @@ -## Process this file with automake to produce Makefile.in - -libcamelnntpincludedir = $(privincludedir)/camel - -camel_provider_LTLIBRARIES = libcamelnntp.la -camel_provider_DATA = libcamelnntp.urls - -INCLUDES = -I../.. \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir) \ - $(CAMEL_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(GTK_INCLUDEDIR) \ - -DG_LOG_DOMAIN=\"camel-nntp-provider\" - -libcamelnntp_la_SOURCES = \ - camel-nntp-provider.c \ - camel-nntp-store.c \ - camel-nntp-folder.c \ - camel-nntp-stream.c \ - camel-nntp-summary.c - -libcamelnntpinclude_HEADERS = \ - camel-nntp-store.h \ - camel-nntp-folder.h \ - camel-nntp-stream.h \ - camel-nntp-summary.h - -noinst_HEADERS = \ - camel-nntp-private.h - -libcamelnntp_la_LDFLAGS = -avoid-version -module - -EXTRA_DIST = libcamelnntp.urls diff --git a/camel/providers/nntp/camel-nntp-auth.c b/camel/providers/nntp/camel-nntp-auth.c deleted file mode 100644 index f8d3a62e27..0000000000 --- a/camel/providers/nntp/camel-nntp-auth.c +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-auth.c : authentication for nntp */ - -/* - * - * Copyright (C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -int -camel_nntp_auth_authenticate (CamelNNTPStore *store, CamelException *ex) -{ - CamelService *service = CAMEL_SERVICE (store); - CamelSession *session = camel_service_get_session (service); - int resp; - - if (!service->url->authmech && !service->url->passwd) { - gchar *prompt; - - prompt = g_strdup_printf (_("Please enter the NNTP password for %s@%s"), - service->url->user, service->url->host); - service->url->passwd = - camel_session_get_password (session, prompt, - TRUE, service, "password", ex); - g_free (prompt); - - if (!service->url->passwd) { - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - "You didn\'t enter a password."); - resp = 666; - goto done; - } - } - - /* first send username */ - resp = camel_nntp_command (store, ex, NULL, "AUTHINFO USER %s", service->url->user); - - if (resp == NNTP_AUTH_REJECTED) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Server rejected username")); - goto done; - - } - else if (resp != NNTP_AUTH_CONTINUE) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Failed to send username to server")); - goto done; - } - - /* then send the username if the server asks for it */ - resp = camel_nntp_command (store, ex, NULL, "AUTHINFO PASS %s", service->url->passwd); - - if (resp == NNTP_AUTH_REJECTED) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Server rejected username/password")); - goto done; - } - - done: - - if (service->url->passwd) { - /* let's be paranoid */ - memset (service->url->passwd, 0, strlen (service->url->passwd)); - g_free (service->url->passwd); - service->url->passwd = NULL; - } - return resp; -} diff --git a/camel/providers/nntp/camel-nntp-auth.h b/camel/providers/nntp/camel-nntp-auth.h deleted file mode 100644 index fc96cf6a4e..0000000000 --- a/camel/providers/nntp/camel-nntp-auth.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-auth.h : authentication for nntp */ - -/* - * - * Author : Chris Toshok - * - * Copyright (C) 1999 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_NNTP_AUTH_H -#define CAMEL_NNTP_AUTH_H 1 - -#include - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -int camel_nntp_auth_authenticate (CamelNNTPStore *store, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_NNTP_AUTH_H */ diff --git a/camel/providers/nntp/camel-nntp-folder.c b/camel/providers/nntp/camel-nntp-folder.c deleted file mode 100644 index 9f0832bc33..0000000000 --- a/camel/providers/nntp/camel-nntp-folder.c +++ /dev/null @@ -1,405 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-folder.c : Class for a news folder - * - * Authors : Chris Toshok - * Michael Zucchi - * - * Copyright (C) 2001-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "camel/camel-file-utils.h" -#include "camel/camel-stream-mem.h" -#include "camel/camel-data-wrapper.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-folder-search.h" -#include "camel/camel-exception.h" -#include "camel/camel-session.h" -#include "camel/camel-data-cache.h" - -#include "camel-nntp-summary.h" -#include "camel-nntp-store.h" -#include "camel-nntp-folder.h" -#include "camel-nntp-store.h" -#include "camel-nntp-private.h" - -static CamelFolderClass *parent_class = NULL; - -/* Returns the class for a CamelNNTPFolder */ -#define CNNTPF_CLASS(so) CAMEL_NNTP_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CNNTPS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static void -nntp_folder_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - CamelNNTPStore *nntp_store; - CamelFolderChangeInfo *changes = NULL; - CamelNNTPFolder *nntp_folder; - - nntp_store = (CamelNNTPStore *)folder->parent_store; - nntp_folder = (CamelNNTPFolder *)folder; - - CAMEL_NNTP_STORE_LOCK(nntp_store, command_lock); - - if (camel_nntp_summary_check((CamelNNTPSummary *)folder->summary, nntp_folder->changes, ex) != -1) - camel_folder_summary_save (folder->summary); - - if (camel_folder_change_info_changed(nntp_folder->changes)) { - changes = nntp_folder->changes; - nntp_folder->changes = camel_folder_change_info_new(); - } - - CAMEL_NNTP_STORE_UNLOCK(nntp_store, command_lock); - - if (changes) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", changes); - camel_folder_change_info_free(changes); - } -} - -static void -nntp_folder_set_message_flags(CamelFolder *folder, const char *uid, guint32 flags, guint32 set) -{ - ((CamelFolderClass *)parent_class)->set_message_flags(folder, uid, flags, set); -} - -static CamelMimeMessage * -nntp_folder_get_message (CamelFolder *folder, const char *uid, CamelException *ex) -{ - CamelMimeMessage *message = NULL; - CamelNNTPStore *nntp_store; - CamelFolderChangeInfo *changes; - CamelNNTPFolder *nntp_folder; - CamelStream *stream = NULL; - int ret; - char *line; - const char *msgid; - - nntp_store = (CamelNNTPStore *)folder->parent_store; - nntp_folder = (CamelNNTPFolder *)folder; - - CAMEL_NNTP_STORE_LOCK(nntp_store, command_lock); - - msgid = strchr(uid, ','); - if (msgid == 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Internal error: uid in invalid format: %s"), uid); - goto fail; - } - msgid++; - - /* Lookup in cache, NEWS is global messageid's so use a global cache path */ - stream = camel_data_cache_get(nntp_store->cache, "cache", msgid, NULL); - if (stream == NULL) { - /* Not in cache, retrieve and put in cache */ - if (camel_nntp_store_set_folder(nntp_store, folder, nntp_folder->changes, ex) == -1) - goto fail; - - ret = camel_nntp_command(nntp_store, &line, "article %s", msgid); - if (ret == -1) - goto error; - - if (ret == 220) { - stream = camel_data_cache_add(nntp_store->cache, "cache", msgid, NULL); - if (stream) { - if (camel_stream_write_to_stream((CamelStream *)nntp_store->stream, stream) == -1) - goto error; - if (camel_stream_reset(stream) == -1) - goto error; - } else { - stream = (CamelStream *)nntp_store->stream; - camel_object_ref((CamelObject *)stream); - } - } - } - - if (stream) { - message = camel_mime_message_new(); - if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, stream) == -1) - goto error; - - CAMEL_NNTP_STORE_UNLOCK(nntp_store, command_lock); - - camel_object_unref((CamelObject *)stream); - return message; - } - - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"), uid, line); - -error: - if (errno == EINTR) - camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); - else - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"), uid, strerror(errno)); - -fail: - if (message) - camel_object_unref((CamelObject *)message); - - if (stream) - camel_object_unref((CamelObject *)stream); - - if (camel_folder_change_info_changed(nntp_folder->changes)) { - changes = nntp_folder->changes; - nntp_folder->changes = camel_folder_change_info_new(); - } else { - changes = NULL; - } - - CAMEL_NNTP_STORE_UNLOCK(nntp_store, command_lock); - - if (changes) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", changes); - camel_folder_change_info_free(changes); - } - - return NULL; -} - -static GPtrArray* -nntp_folder_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex) -{ - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - GPtrArray *matches, *summary; - - CAMEL_NNTP_FOLDER_LOCK(nntp_folder, search_lock); - - if(nntp_folder->search == NULL) - nntp_folder->search = camel_folder_search_new(); - - camel_folder_search_set_folder(nntp_folder->search, folder); - summary = camel_folder_get_summary(folder); - camel_folder_search_set_summary(nntp_folder->search, summary); - - matches = camel_folder_search_execute_expression(nntp_folder->search, expression, ex); - - CAMEL_NNTP_FOLDER_UNLOCK(nntp_folder, search_lock); - - camel_folder_free_summary(folder, summary); - - return matches; -} - -static GPtrArray * -nntp_folder_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex) -{ - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER(folder); - GPtrArray *summary, *matches; - int i; - - /* NOTE: could get away without the search lock by creating a new - search object each time */ - - summary = g_ptr_array_new(); - for (i=0;ilen;i++) { - CamelMessageInfo *info; - - info = camel_folder_get_message_info(folder, uids->pdata[i]); - if (info) - g_ptr_array_add(summary, info); - } - - if (summary->len == 0) - return summary; - - CAMEL_NNTP_FOLDER_LOCK(folder, search_lock); - - if (nntp_folder->search == NULL) - nntp_folder->search = camel_folder_search_new(); - - camel_folder_search_set_folder(nntp_folder->search, folder); - camel_folder_search_set_summary(nntp_folder->search, summary); - - matches = camel_folder_search_execute_expression(nntp_folder->search, expression, ex); - - CAMEL_NNTP_FOLDER_UNLOCK(folder, search_lock); - - for (i=0;ilen;i++) - camel_folder_free_message_info(folder, summary->pdata[i]); - g_ptr_array_free(summary, TRUE); - - return matches; -} - -static void -nntp_folder_search_free(CamelFolder *folder, GPtrArray *result) -{ - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - - camel_folder_search_free_result(nntp_folder->search, result); - -} - -static void -nntp_folder_init(CamelNNTPFolder *nntp_folder, CamelNNTPFolderClass *klass) -{ - struct _CamelNNTPFolderPrivate *p; - - nntp_folder->changes = camel_folder_change_info_new(); - p = nntp_folder->priv = g_malloc0(sizeof(*nntp_folder->priv)); - p->search_lock = g_mutex_new(); - p->cache_lock = g_mutex_new(); -} - -static void -nntp_folder_finalise (CamelNNTPFolder *nntp_folder) -{ - struct _CamelNNTPFolderPrivate *p; - - g_free(nntp_folder->storage_path); - - p = nntp_folder->priv; - g_mutex_free(p->search_lock); - g_mutex_free(p->cache_lock); - g_free(p); -} - -static void -nntp_folder_class_init (CamelNNTPFolderClass *camel_nntp_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_nntp_folder_class); - - parent_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_folder_get_type ())); - - /* virtual method definition */ - - /* virtual method overload */ - camel_folder_class->sync = nntp_folder_sync; - camel_folder_class->set_message_flags = nntp_folder_set_message_flags; - camel_folder_class->get_message = nntp_folder_get_message; - camel_folder_class->search_by_expression = nntp_folder_search_by_expression; - camel_folder_class->search_by_uids = nntp_folder_search_by_uids; - camel_folder_class->search_free = nntp_folder_search_free; -} - -CamelType -camel_nntp_folder_get_type (void) -{ - static CamelType camel_nntp_folder_type = CAMEL_INVALID_TYPE; - - if (camel_nntp_folder_type == CAMEL_INVALID_TYPE) { - camel_nntp_folder_type = camel_type_register (CAMEL_FOLDER_TYPE, "CamelNNTPFolder", - sizeof (CamelNNTPFolder), - sizeof (CamelNNTPFolderClass), - (CamelObjectClassInitFunc) nntp_folder_class_init, - NULL, - (CamelObjectInitFunc) nntp_folder_init, - (CamelObjectFinalizeFunc) nntp_folder_finalise); - } - - return camel_nntp_folder_type; -} - - -/* not yet */ -/* Idea is we update in stages, but this requires a different xover command, etc */ -#ifdef ASYNC_SUMMARY -struct _folder_check_msg { - CamelSessionThreadMsg msg; - CamelNNTPFolder *folder; -}; - -static void -folder_check(CamelSession *session, CamelSessionThreadMsg *msg) -{ - struct _folder_check_msg *m = (struct _folder_check_msg *)msg; - CamelException *ex; - CamelNNTPStore *nntp_store; - - nntp_store = (CamelNNTPStore *)m->folder->parent.parent_store; - - CAMEL_NNTP_STORE_LOCK(nntp_store, command_lock); - - ex = camel_exception_new(); - camel_nntp_summary_check((CamelNNTPSummary *)m->folder->parent.summary, m->folder->changes, ex); - camel_exception_free(ex); - - CAMEL_NNTP_STORE_UNLOCK(nntp_store, command_lock); -} - -static void -folder_check_free(CamelSession *session, CamelSessionThreadMsg *msg) -{ - struct _folder_check_msg *m = (struct _folder_check_msg *)msg; - - camel_object_unref((CamelObject *)m->folder); -} - -static CamelSessionThreadOps folder_check_ops = { - folder_check, - folder_check_free, -}; -#endif - -CamelFolder * -camel_nntp_folder_new (CamelStore *parent, const char *folder_name, CamelException *ex) -{ - CamelFolder *folder; - CamelNNTPFolder *nntp_folder; - char *root; - CamelService *service; -#ifdef ASYNC_SUMMARY - struct _folder_check_msg *m; -#endif - - service = (CamelService *)parent; - root = camel_session_get_storage_path(service->session, service, ex); - if (root == NULL) - return NULL; - - /* If this doesn't work, stuff wont save, but let it continue anyway */ - camel_mkdir (root, 0777); - - folder = (CamelFolder *) camel_object_new (CAMEL_NNTP_FOLDER_TYPE); - nntp_folder = (CamelNNTPFolder *)folder; - - camel_folder_construct (folder, parent, folder_name, folder_name); - folder->folder_flags |= CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY|CAMEL_FOLDER_HAS_SEARCH_CAPABILITY; - - nntp_folder->storage_path = g_strdup_printf("%s/%s", root, folder->full_name); - g_free(root); - - folder->summary = (CamelFolderSummary *)camel_nntp_summary_new(nntp_folder); - camel_folder_summary_load (folder->summary); -#ifdef ASYNC_SUMMARY - m = camel_session_thread_msg_new(service->session, &folder_check_ops, sizeof(*m)); - m->folder = nntp_folder; - camel_object_ref((CamelObject *)folder); - camel_session_thread_queue(service->session, &m->msg, 0); -#else - if (camel_nntp_summary_check((CamelNNTPSummary *)folder->summary, nntp_folder->changes, ex) == -1) { - camel_object_unref((CamelObject *)folder); - folder = NULL; - } -#endif - - return folder; -} diff --git a/camel/providers/nntp/camel-nntp-folder.h b/camel/providers/nntp/camel-nntp-folder.h deleted file mode 100644 index 300d61762d..0000000000 --- a/camel/providers/nntp/camel-nntp-folder.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-folder.h : NNTP group (folder) support. */ - -/* - * - * Author : Chris Toshok - * - * Copyright (C) 2000 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_NNTP_FOLDER_H -#define CAMEL_NNTP_FOLDER_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel/camel-folder.h" - -/* #include "camel-store.h" */ - -#define CAMEL_NNTP_FOLDER_TYPE (camel_nntp_folder_get_type ()) -#define CAMEL_NNTP_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_NNTP_FOLDER_TYPE, CamelNNTPFolder)) -#define CAMEL_NNTP_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_NNTP_FOLDER_TYPE, CamelNNTPFolderClass)) -#define CAMEL_IS_NNTP_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_NNTP_FOLDER_TYPE)) - -typedef struct _CamelNNTPFolder { - CamelFolder parent; - - struct _CamelNNTPFolderPrivate *priv; - - struct _CamelFolderChangeInfo *changes; - char *storage_path; - CamelFolderSearch *search; -} CamelNNTPFolder; - -typedef struct _CamelNNTPFolderClass { - CamelFolderClass parent; - - /* Virtual methods */ - -} CamelNNTPFolderClass; - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_nntp_folder_get_type (void); - -CamelFolder *camel_nntp_folder_new (CamelStore *parent, const char *folder_name, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_NNTP_FOLDER_H */ diff --git a/camel/providers/nntp/camel-nntp-grouplist.c b/camel/providers/nntp/camel-nntp-grouplist.c deleted file mode 100644 index 7f3850f9c1..0000000000 --- a/camel/providers/nntp/camel-nntp-grouplist.c +++ /dev/null @@ -1,219 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-grouplist.c : getting/updating the list of newsgroups on the server. */ - -/* - * Author : Chris Toshok - * - * Copyright (C) 2000 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include -#include -#include - -#include "camel-exception.h" -#include "camel-nntp-grouplist.h" -#include "camel-nntp-resp-codes.h" - -static CamelNNTPGroupList * -camel_nntp_get_grouplist_from_server (CamelNNTPStore *store, CamelException *ex) -{ - int status; - gboolean done = FALSE; - CamelNNTPGroupList *list; - - CAMEL_NNTP_STORE_LOCK(store); - status = camel_nntp_command (store, ex, NULL, - "LIST"); - - if (status != NNTP_LIST_FOLLOWS) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not get group list from server.")); - return NULL; - } - - list = g_new0 (CamelNNTPGroupList, 1); - list->time = time (NULL); - - while (!done) { - char *line; - - if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &line, ex) < 0) { - list->group_list = g_list_reverse(list->group_list); - return list; - } - - if (*line == '.') { - done = TRUE; - } - else { - CamelNNTPGroupListEntry *entry = g_new (CamelNNTPGroupListEntry, 1); - char **split_line = g_strsplit (line, " ", 4); - - entry->group_name = g_strdup (split_line[0]); - entry->high = atoi (split_line[1]); - entry->low = atoi (split_line[2]); - - g_strfreev (split_line); - - list->group_list = g_list_prepend (list->group_list, entry); - } - } - CAMEL_NNTP_STORE_UNLOCK(store); - - list->group_list = g_list_reverse(list->group_list); - return list; -} - -static CamelNNTPGroupList* -camel_nntp_get_grouplist_from_file (CamelNNTPStore *store, CamelException *ex) -{ - gchar *root_dir = camel_nntp_store_get_toplevel_dir(CAMEL_NNTP_STORE(store)); - gchar *grouplist_file = g_strdup_printf ("%s/grouplist", root_dir); - CamelNNTPGroupList *list; - FILE *fp; - char buf[300]; - unsigned long time; - - g_free (root_dir); - fp = fopen (grouplist_file, "r"); - g_free (grouplist_file); - - if (fp == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Unable to load grouplist file for %s: %s"), - CAMEL_SERVICE(store)->url->host, - strerror(errno)); - return NULL; - } - - /* read the time */ - if (!fgets (buf, sizeof (buf), fp)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Unable to load grouplist file for %s: %s"), - CAMEL_SERVICE(store)->url->host, - strerror(errno)); - fclose (fp); - return NULL; - } - - - list = g_new0 (CamelNNTPGroupList, 1); - list->store = store; - sscanf (buf, "%lu", &time); - list->time = time; - - while (fgets (buf, sizeof (buf), fp)) { - CamelNNTPGroupListEntry *entry = g_new (CamelNNTPGroupListEntry, 1); - char **split_line = g_strsplit (buf, " ", 4); - - entry->group_name = g_strdup (split_line[0]); - entry->high = atoi (split_line[1]); - entry->low = atoi (split_line[2]); - - g_strfreev (split_line); - - list->group_list = g_list_prepend (list->group_list, entry); - } - - fclose (fp); - - list->group_list = g_list_reverse(list->group_list); - return list; -} - -static void -save_entry (CamelNNTPGroupListEntry *entry, FILE *fp) -{ - fprintf (fp, "%s %d %d\n", entry->group_name, entry->low, entry->high); -} - -void -camel_nntp_grouplist_save (CamelNNTPGroupList *group_list, CamelException *ex) -{ - FILE *fp; - gchar *root_dir = camel_nntp_store_get_toplevel_dir(CAMEL_NNTP_STORE(group_list->store)); - gchar *grouplist_file = g_strdup_printf ("%s/grouplist", root_dir); - - g_free (root_dir); - fp = fopen (grouplist_file, "w"); - g_free (grouplist_file); - - if (fp == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Unable to save grouplist file for %s: %s"), - CAMEL_SERVICE(group_list->store)->url->host, - strerror(errno)); - return; - } - - fprintf (fp, "%lu\n", (long)group_list->time); - - g_list_foreach (group_list->group_list, (GFunc)save_entry, fp); - - fclose (fp); -} - -static void -free_entry (CamelNNTPGroupListEntry *entry, void *data) -{ - g_free (entry->group_name); - g_free (entry); -} - -void -camel_nntp_grouplist_free (CamelNNTPGroupList *group_list) -{ - g_return_if_fail (group_list); - - g_list_foreach (group_list->group_list, (GFunc)free_entry, NULL); - - g_free (group_list); -} - -CamelNNTPGroupList* -camel_nntp_grouplist_fetch (CamelNNTPStore *store, CamelException *ex) -{ - CamelNNTPGroupList *list; - - list = camel_nntp_get_grouplist_from_file (store, ex); - - printf ("camel_nntp_get_grouplist_from_file returned %p\n", list); - - if (!list) { - camel_exception_clear (ex); - - list = camel_nntp_get_grouplist_from_server (store, ex); - - if (!list) { - camel_nntp_grouplist_free (list); - } - else { - list->store = store; - camel_nntp_grouplist_save (list, ex); - return list; - } - } - - return list; -} - -gint -camel_nntp_grouplist_update (CamelNNTPGroupList *group_list, CamelException *ex) -{ - return 0; -} diff --git a/camel/providers/nntp/camel-nntp-grouplist.h b/camel/providers/nntp/camel-nntp-grouplist.h deleted file mode 100644 index edd1e64cb9..0000000000 --- a/camel/providers/nntp/camel-nntp-grouplist.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-grouplist.h : getting/updating the list of newsgroups on the server. */ - -/* - * Author : Chris Toshok - * - * Copyright (C) 2000 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_NNTP_GROUPLIST_H -#define CAMEL_NNTP_GROUPLIST_H 1 - -#include -#include "camel-nntp-store.h" - -struct CamelNNTPGroupListEntry { - char *group_name; - guint32 low; - guint32 high; - guint32 flags; -}; - -struct CamelNNTPGroupList { - CamelNNTPStore *store; - time_t time; - GList *group_list; -}; - -CamelNNTPGroupList* camel_nntp_grouplist_fetch (CamelNNTPStore *store, CamelException *ex); -gint camel_nntp_grouplist_update (CamelNNTPGroupList *group_list, CamelException *ex); -void camel_nntp_grouplist_save (CamelNNTPGroupList *group_list, CamelException *ex); -void camel_nntp_grouplist_free (CamelNNTPGroupList *group_list); - -#endif /* CAMEL_NNTP_GROUPLIST_H */ diff --git a/camel/providers/nntp/camel-nntp-newsrc.c b/camel/providers/nntp/camel-nntp-newsrc.c deleted file mode 100644 index 309e1f45c8..0000000000 --- a/camel/providers/nntp/camel-nntp-newsrc.c +++ /dev/null @@ -1,651 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Chris Toshok - * - * Copyright 2000-2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "camel-nntp-newsrc.h" -#include - -#define NEWSRC_LOCK(f, l) (g_mutex_lock(((CamelNNTPNewsrc *)f)->l)) -#define NEWSRC_UNLOCK(f, l) (g_mutex_unlock(((CamelNNTPNewsrc *)f)->l)) - -typedef struct { - guint low; - guint high; -} ArticleRange; - -typedef struct { - char *name; - GArray *ranges; - gboolean subscribed; -} NewsrcGroup; - -struct CamelNNTPNewsrc { - gchar *filename; - GHashTable *groups; - gboolean dirty; - GMutex *lock; -}; - - -static NewsrcGroup * -camel_nntp_newsrc_group_add (CamelNNTPNewsrc *newsrc, const char *group_name, gboolean subscribed) -{ - NewsrcGroup *new_group = g_malloc(sizeof(NewsrcGroup)); - - new_group->name = g_strdup(group_name); - new_group->subscribed = subscribed; - new_group->ranges = g_array_new (FALSE, FALSE, sizeof (ArticleRange)); - - g_hash_table_insert (newsrc->groups, new_group->name, new_group); - - newsrc->dirty = TRUE; - - return new_group; -} - -static int -camel_nntp_newsrc_group_get_highest_article_read(CamelNNTPNewsrc *newsrc, NewsrcGroup *group) -{ - if (!group || group->ranges->len == 0) - return 0; - - return g_array_index(group->ranges, ArticleRange, group->ranges->len - 1).high; -} - -static int -camel_nntp_newsrc_group_get_num_articles_read(CamelNNTPNewsrc *newsrc, NewsrcGroup *group) -{ - int i; - int count = 0; - - if (group == NULL) - return 0; - - for (i = 0; i < group->ranges->len; i ++) - count += (g_array_index(group->ranges, ArticleRange, i).high - - g_array_index(group->ranges, ArticleRange, i).low) + 1; - - return count; -} - - -static void -camel_nntp_newsrc_group_mark_range_read(CamelNNTPNewsrc *newsrc, NewsrcGroup *group, long low, long high) -{ - int i; - - if (group->ranges->len == 1 - && g_array_index (group->ranges, ArticleRange, 0).low == 0 - && g_array_index (group->ranges, ArticleRange, 0).high == 0) { - g_array_index (group->ranges, ArticleRange, 0).low = low; - g_array_index (group->ranges, ArticleRange, 0).high = high; - - newsrc->dirty = TRUE; - } - else { - ArticleRange tmp_range; - - for (i = 0; i < group->ranges->len; i ++) { - guint range_low = g_array_index (group->ranges, ArticleRange, i).low; - guint range_high = g_array_index (group->ranges, ArticleRange, i).high; - - /* if it's already part of a range, return immediately. */ - if (low >= range_low && - low <= range_high && - high >= range_low && - high <= range_high) { - return; - } - /* if we have a new lower bound for this range, set it. */ - else if (low <= range_low - && high >= range_low - && high <= range_high) { - g_array_index (group->ranges, ArticleRange, i).low = low; - newsrc->dirty = TRUE; - return; - } - /* if we have a new upper bound for this range, set it. */ - else if (high >= range_high - && low >= range_low - && low <= range_high) { - g_array_index (group->ranges, ArticleRange, i).high = high; - newsrc->dirty = TRUE; - return; - } - /* if we would be inserting another range that - starts one index higher than an existing - one, make the upper value of the existing - range the upper value of the new one. */ - else if (low == range_high + 1) { - g_array_index (group->ranges, ArticleRange, i).high = high; - newsrc->dirty = TRUE; - return; - } - /* if we would be inserting another range that - ends one index lower than an existing one, - group the existing range by setting its low - to the new low */ - else if (high == range_low - 1) { - g_array_index (group->ranges, ArticleRange, i).low = low; - newsrc->dirty = TRUE; - return; - } - /* if the range lies entirely outside another - range, doesn't coincide with it's - endpoints, and has lower values, insert it - into the middle of the list. */ - else if (low < range_low - && high < range_low) { - tmp_range.low = low; - tmp_range.high = high; - - group->ranges = g_array_insert_val (group->ranges, i, tmp_range); - newsrc->dirty = TRUE; - - return; - } - } - - /* if we made it here, the range needs to go at the end */ - tmp_range.low = low; - tmp_range.high = high; - group->ranges = g_array_append_val (group->ranges, tmp_range); - newsrc->dirty = TRUE; - } -} - -int -camel_nntp_newsrc_get_highest_article_read (CamelNNTPNewsrc *newsrc, const char *group_name) -{ - NewsrcGroup *group; - int ret; - - NEWSRC_LOCK(newsrc, lock); - - group = g_hash_table_lookup (newsrc->groups, group_name); - - if (group) - ret = camel_nntp_newsrc_group_get_highest_article_read (newsrc, group); - else - ret = 0; - - NEWSRC_UNLOCK(newsrc, lock); - - return ret; -} - -int -camel_nntp_newsrc_get_num_articles_read (CamelNNTPNewsrc *newsrc, const char *group_name) -{ - NewsrcGroup *group; - int ret; - - NEWSRC_LOCK(newsrc, lock); - - group = g_hash_table_lookup (newsrc->groups, group_name); - - if (group) - ret = camel_nntp_newsrc_group_get_num_articles_read (newsrc, group); - else - ret = 0; - - NEWSRC_UNLOCK(newsrc, lock); - - return ret; -} - -void -camel_nntp_newsrc_mark_article_read (CamelNNTPNewsrc *newsrc, const char *group_name, int num) -{ - camel_nntp_newsrc_mark_range_read (newsrc, group_name, num, num); -} - -void -camel_nntp_newsrc_mark_range_read(CamelNNTPNewsrc *newsrc, const char *group_name, long low, long high) -{ - NewsrcGroup *group; - - /* swap them if they're in the wrong order. */ - if (low > high) { - long tmp; - - tmp = high; - high = low; - low = tmp; - } - - NEWSRC_LOCK(newsrc, lock); - group = g_hash_table_lookup (newsrc->groups, group_name); - - if (group) - camel_nntp_newsrc_group_mark_range_read (newsrc, group, low, high); - NEWSRC_UNLOCK(newsrc, lock); -} - -gboolean -camel_nntp_newsrc_article_is_read (CamelNNTPNewsrc *newsrc, const char *group_name, long num) -{ - int i; - NewsrcGroup *group; - int ret = FALSE; - - NEWSRC_LOCK(newsrc, lock); - group = g_hash_table_lookup (newsrc->groups, group_name); - - if (group) { - for (i = 0; i < group->ranges->len; i++) { - if (num >= g_array_index (group->ranges, ArticleRange, i).low && - num <= g_array_index (group->ranges, ArticleRange, i).high) { - ret = TRUE; - break; - } - } - } - - NEWSRC_UNLOCK(newsrc, lock); - - return FALSE; -} - -gboolean -camel_nntp_newsrc_group_is_subscribed (CamelNNTPNewsrc *newsrc, const char *group_name) -{ - NewsrcGroup *group; - int ret = FALSE; - - NEWSRC_LOCK(newsrc, lock); - - group = g_hash_table_lookup (newsrc->groups, group_name); - - if (group) { - ret = group->subscribed; - } - - NEWSRC_UNLOCK(newsrc, lock); - - return ret; -} - -void -camel_nntp_newsrc_subscribe_group (CamelNNTPNewsrc *newsrc, const char *group_name) -{ - NewsrcGroup *group; - - NEWSRC_LOCK(newsrc, lock); - - group = g_hash_table_lookup (newsrc->groups, group_name); - - if (group) { - if (!group->subscribed) - newsrc->dirty = TRUE; - group->subscribed = TRUE; - } - else { - camel_nntp_newsrc_group_add (newsrc, group_name, TRUE); - } - - NEWSRC_UNLOCK(newsrc, lock); -} - -void -camel_nntp_newsrc_unsubscribe_group (CamelNNTPNewsrc *newsrc, const char *group_name) -{ - NewsrcGroup *group; - - NEWSRC_LOCK(newsrc, lock); - - group = g_hash_table_lookup (newsrc->groups, group_name); - if (group) { - if (group->subscribed) - newsrc->dirty = TRUE; - group->subscribed = FALSE; - } - else { - camel_nntp_newsrc_group_add (newsrc, group_name, FALSE); - } - - NEWSRC_UNLOCK(newsrc, lock); -} - -struct newsrc_ptr_array { - GPtrArray *ptr_array; - gboolean subscribed_only; -}; - -/* this needs to strdup the grup_name, if the group array is likely to change */ -static void -get_group_foreach (char *group_name, NewsrcGroup *group, struct newsrc_ptr_array *npa) -{ - if (group->subscribed || !npa->subscribed_only) { - g_ptr_array_add (npa->ptr_array, group_name); - } -} - -GPtrArray * -camel_nntp_newsrc_get_subscribed_group_names (CamelNNTPNewsrc *newsrc) -{ - struct newsrc_ptr_array npa; - - g_return_val_if_fail (newsrc, NULL); - - NEWSRC_LOCK(newsrc, lock); - - npa.ptr_array = g_ptr_array_new(); - npa.subscribed_only = TRUE; - - g_hash_table_foreach (newsrc->groups, - (GHFunc)get_group_foreach, &npa); - - NEWSRC_UNLOCK(newsrc, lock); - - return npa.ptr_array; -} - -GPtrArray * -camel_nntp_newsrc_get_all_group_names (CamelNNTPNewsrc *newsrc) -{ - struct newsrc_ptr_array npa; - - g_return_val_if_fail (newsrc, NULL); - - NEWSRC_LOCK(newsrc, lock); - - npa.ptr_array = g_ptr_array_new(); - npa.subscribed_only = FALSE; - - g_hash_table_foreach (newsrc->groups, - (GHFunc)get_group_foreach, &npa); - - NEWSRC_UNLOCK(newsrc, lock); - - return npa.ptr_array; -} - -void -camel_nntp_newsrc_free_group_names (CamelNNTPNewsrc *newsrc, GPtrArray *group_names) -{ - g_ptr_array_free (group_names, TRUE); -} - -struct newsrc_fp { - CamelNNTPNewsrc *newsrc; - FILE *fp; -}; - -static void -camel_nntp_newsrc_write_group_line(gpointer key, NewsrcGroup *group, struct newsrc_fp *newsrc_fp) -{ - CamelNNTPNewsrc *newsrc; - FILE *fp; - int i; - - fp = newsrc_fp->fp; - newsrc = newsrc_fp->newsrc; - - fprintf (fp, "%s%c", group->name, group->subscribed ? ':' : '!'); - - if (group->ranges->len == 1 - && g_array_index (group->ranges, ArticleRange, 0).low == 0 - && g_array_index (group->ranges, ArticleRange, 0).high == 0) { - fprintf (fp, "\n"); - - return; /* special case since our parsing code will insert this - bogus range if there were no read articles. The code - to add a range is smart enough to remove this one if we - ever mark an article read, but we still need to deal with - it if that code doesn't get hit. */ - } - - fprintf (fp, " "); - - for (i = 0; i < group->ranges->len; i ++) { - char range_buffer[100]; - guint low = g_array_index (group->ranges, ArticleRange, i).low; - guint high = g_array_index (group->ranges, ArticleRange, i).high; - - if (low == high) - sprintf(range_buffer, "%d", low); - else if (low == high - 1) - sprintf(range_buffer, "%d,%d", low, high); - else - sprintf(range_buffer, "%d-%d", low, high); - - if (i != group->ranges->len - 1) - strcat(range_buffer, ","); - - fprintf (fp, range_buffer); - } - - fprintf (fp, "\n"); -} - -void -camel_nntp_newsrc_write_to_file(CamelNNTPNewsrc *newsrc, FILE *fp) -{ - struct newsrc_fp newsrc_fp; - - g_return_if_fail (newsrc); - - newsrc_fp.newsrc = newsrc; - newsrc_fp.fp = fp; - - NEWSRC_LOCK(newsrc, lock); - - g_hash_table_foreach (newsrc->groups, - (GHFunc)camel_nntp_newsrc_write_group_line, - &newsrc_fp); - - NEWSRC_UNLOCK(newsrc, lock); -} - -void -camel_nntp_newsrc_write(CamelNNTPNewsrc *newsrc) -{ - FILE *fp; - - g_return_if_fail (newsrc); - - NEWSRC_LOCK(newsrc, lock); - - if (!newsrc->dirty) { - NEWSRC_UNLOCK(newsrc, lock); - return; - } - - if ((fp = fopen(newsrc->filename, "w")) == NULL) { - g_warning ("Couldn't open newsrc file '%s'.\n", newsrc->filename); - NEWSRC_UNLOCK(newsrc, lock); - return; - } - - newsrc->dirty = FALSE; - NEWSRC_UNLOCK(newsrc, lock); - - camel_nntp_newsrc_write_to_file(newsrc, fp); - - fclose(fp); -} - -static void -camel_nntp_newsrc_parse_line(CamelNNTPNewsrc *newsrc, char *line) -{ - char *p, *comma, *dash; - gboolean is_subscribed; - NewsrcGroup *group; - - p = strchr(line, ':'); - - if (p) { - is_subscribed = TRUE; - } - else { - p = strchr(line, '!'); - if (p) - is_subscribed = FALSE; - else - return; /* bogus line. */ - } - - *p++ = '\0'; - - group = camel_nntp_newsrc_group_add (newsrc, line, is_subscribed); - - do { - guint high, low; - - comma = strchr(p, ','); - - if (comma) - *comma = '\0'; - - dash = strchr(p, '-'); - - if (!dash) { /* there wasn't a dash. must be just one number */ - high = low = atol(p); - } - else { /* there was a dash. */ - *dash = '\0'; - low = atol(p); - *dash = '-'; - p = dash + 1; - high = atol(p); - } - - camel_nntp_newsrc_group_mark_range_read (newsrc, group, low, high); - - if (comma) { - *comma = ','; - p = comma + 1; - } - - } while(comma); -} - -static char* -get_line (char *buf, char **p) -{ - char *l; - char *line; - - g_assert (*p == NULL || **p == '\n' || **p == '\0'); - - if (*p == NULL) { - *p = buf; - - if (**p == '\0') - return NULL; - } - else { - if (**p == '\0') - return NULL; - - (*p) ++; - - /* if we just incremented to the end of the buffer, return NULL */ - if (**p == '\0') - return NULL; - } - - l = strchr (*p, '\n'); - if (l) { - *l = '\0'; - line = g_strdup (*p); - *l = '\n'; - *p = l; - } - else { - /* we're at the last line (which isn't terminated by a \n, btw) */ - line = g_strdup (*p); - (*p) += strlen (*p); - } - - return line; -} - -CamelNNTPNewsrc * -camel_nntp_newsrc_read_for_server (const char *server) -{ - int fd; - char buf[1024]; - char *file_contents, *line, *p; - char *filename; - CamelNNTPNewsrc *newsrc; - int newsrc_len; - int len_read = 0; - struct stat sb; - - filename = g_strdup_printf ("%s/.newsrc-%s", g_get_home_dir(), server); - - newsrc = g_new0(CamelNNTPNewsrc, 1); - newsrc->filename = filename; - newsrc->groups = g_hash_table_new (g_str_hash, g_str_equal); - newsrc->lock = g_mutex_new(); - - if ((fd = open(filename, O_RDONLY)) == -1) { - g_warning ("~/.newsrc-%s not present.\n", server); - return newsrc; - } - - if (fstat (fd, &sb) == -1) { - g_warning ("failed fstat on ~/.newsrc-%s: %s\n", server, strerror(errno)); - return newsrc; - } - newsrc_len = sb.st_size; - - file_contents = g_malloc (newsrc_len + 1); - - while (len_read < newsrc_len) { - int c = read (fd, buf, sizeof (buf)); - - if (c == -1) - break; - - memcpy (&file_contents[len_read], buf, c); - len_read += c; - } - file_contents [len_read] = 0; - - p = NULL; - while ((line = get_line (file_contents, &p))) { - camel_nntp_newsrc_parse_line(newsrc, line); - g_free (line); - } - - close (fd); - g_free (file_contents); - - return newsrc; -} diff --git a/camel/providers/nntp/camel-nntp-newsrc.h b/camel/providers/nntp/camel-nntp-newsrc.h deleted file mode 100644 index 652e3edbce..0000000000 --- a/camel/providers/nntp/camel-nntp-newsrc.h +++ /dev/null @@ -1,34 +0,0 @@ - -#ifndef _CAMEL_NNTP_NEWSRC_H_ -#define _CAMEL_NNTP_NEWSRC_H_ - -#include -#include "glib.h" - -typedef struct CamelNNTPNewsrc CamelNNTPNewsrc; - -int camel_nntp_newsrc_get_highest_article_read (CamelNNTPNewsrc *newsrc, const char *group_name); -int camel_nntp_newsrc_get_num_articles_read (CamelNNTPNewsrc *newsrc, const char *group_name); -void camel_nntp_newsrc_mark_article_read (CamelNNTPNewsrc *newsrc, - const char *group_name, int num); -void camel_nntp_newsrc_mark_range_read (CamelNNTPNewsrc *newsrc, - const char *group_name, long low, long high); - -gboolean camel_nntp_newsrc_article_is_read (CamelNNTPNewsrc *newsrc, - const char *group_name, long num); - -gboolean camel_nntp_newsrc_group_is_subscribed (CamelNNTPNewsrc *newsrc, const char *group_name); -void camel_nntp_newsrc_subscribe_group (CamelNNTPNewsrc *newsrc, const char *group_name); -void camel_nntp_newsrc_unsubscribe_group (CamelNNTPNewsrc *newsrc, const char *group_name); - -GPtrArray* camel_nntp_newsrc_get_subscribed_group_names (CamelNNTPNewsrc *newsrc); -GPtrArray* camel_nntp_newsrc_get_all_group_names (CamelNNTPNewsrc *newsrc); -void camel_nntp_newsrc_free_group_names (CamelNNTPNewsrc *newsrc, GPtrArray *group_names); - -void camel_nntp_newsrc_write_to_file (CamelNNTPNewsrc *newsrc, FILE *fp); -void camel_nntp_newsrc_write (CamelNNTPNewsrc *newsrc); -CamelNNTPNewsrc *camel_nntp_newsrc_read_for_server (const char *server); - -#endif /* _CAMEL_NNTP_NEWSRC_H_ */ - - diff --git a/camel/providers/nntp/camel-nntp-private.h b/camel/providers/nntp/camel-nntp-private.h deleted file mode 100644 index f2cca4e187..0000000000 --- a/camel/providers/nntp/camel-nntp-private.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * camel-nntp-private.h: Private info for nntp. - * - * Authors: Michael Zucchi - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_NNTP_PRIVATE_H -#define CAMEL_NNTP_PRIVATE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* need a way to configure and save this data, if this header is to - be installed. For now, dont install it */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "e-util/e-msgport.h" - -struct _CamelNNTPStorePrivate { - EMutex *command_lock; /* for locking the command stream for a complete operation */ -}; - -#define CAMEL_NNTP_STORE_LOCK(f, l) (e_mutex_lock(((CamelNNTPStore *)f)->priv->l)) -#define CAMEL_NNTP_STORE_UNLOCK(f, l) (e_mutex_unlock(((CamelNNTPStore *)f)->priv->l)) - - -struct _CamelNNTPFolderPrivate { - GMutex *search_lock; /* for locking the search object */ - GMutex *cache_lock; /* for locking the cache object */ -}; - -#define CAMEL_NNTP_FOLDER_LOCK(f, l) (g_mutex_lock(((CamelNNTPFolder *)f)->priv->l)) -#define CAMEL_NNTP_FOLDER_UNLOCK(f, l) (g_mutex_unlock(((CamelNNTPFolder *)f)->priv->l)) -#else -#define CAMEL_NNTP_FOLDER_LOCK(f, l) -#define CAMEL_NNTP_FOLDER_UNLOCK(f, l) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_NNTP_PRIVATE_H */ - diff --git a/camel/providers/nntp/camel-nntp-provider.c b/camel/providers/nntp/camel-nntp-provider.c deleted file mode 100644 index 8f54b3ee98..0000000000 --- a/camel/providers/nntp/camel-nntp-provider.c +++ /dev/null @@ -1,113 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-provider.c: nntp provider registration code */ - -/* - * Authors : - * Chris Toshok - * - * Copyright (C) 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "camel-nntp-store.h" -#include "camel-provider.h" -#include "camel-session.h" - -static void add_hash (guint *hash, char *s); -static guint nntp_url_hash (gconstpointer key); -static gint check_equal (char *s1, char *s2); -static gint nntp_url_equal (gconstpointer a, gconstpointer b); - -static CamelProvider news_provider = { - "nntp", - N_("USENET news"), - - N_("This is a provider for reading from and posting to" - "USENET newsgroups."), - - "news", - - CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE | - CAMEL_PROVIDER_IS_STORAGE, - - CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_USER | - CAMEL_URL_ALLOW_PASSWORD | CAMEL_URL_ALLOW_AUTH, - - /* ... */ -}; - -void -camel_provider_module_init (CamelSession *session) -{ - news_provider.object_types[CAMEL_PROVIDER_STORE] = - camel_nntp_store_get_type(); - - news_provider.url_hash = nntp_url_hash; - news_provider.url_equal = nntp_url_equal; - - camel_session_register_provider (session, &news_provider); -} - -static void -add_hash (guint *hash, char *s) -{ - if (s) - *hash ^= g_str_hash(s); -} - -static guint -nntp_url_hash (gconstpointer key) -{ - const CamelURL *u = (CamelURL *)key; - guint hash = 0; - - add_hash (&hash, u->user); - add_hash (&hash, u->host); - hash ^= u->port; - - return hash; -} - -static gint -check_equal (char *s1, char *s2) -{ - if (s1 == NULL) { - if (s2 == NULL) - return TRUE; - else - return FALSE; - } - - if (s2 == NULL) - return FALSE; - - return strcmp (s1, s2) == 0; -} - -static gint -nntp_url_equal (gconstpointer a, gconstpointer b) -{ - const CamelURL *u1 = a, *u2 = b; - - return check_equal (u1->user, u2->user) - && check_equal (u1->host, u2->host) - && u1->port == u2->port; -} diff --git a/camel/providers/nntp/camel-nntp-resp-codes.h b/camel/providers/nntp/camel-nntp-resp-codes.h deleted file mode 100644 index d9aace81ef..0000000000 --- a/camel/providers/nntp/camel-nntp-resp-codes.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-resp-codes.h : #defines for all the response codes we care about */ - -/* - * - * Copyright (C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_NNTP_RESP_CODES_H -#define CAMEL_NNTP_RESP_CODES_H 1 - -#define CAMEL_NNTP_OK(x) ((x) < 400) -#define CAMEL_NNTP_ERR(x) (!CAMEL_NNTP_OK(x) && (x) < 500) -#define CAMEL_NNTP_FAIL(x) (!CAMEL_NNTP_OK(x) && !CAMEL_NNTP_ERR(x)) - -#define NNTP_GREETING_POSTING_OK 200 -#define NNTP_GREETING_NO_POSTING 201 - -#define NNTP_EXTENSIONS_SUPPORTED 202 -#define NNTP_GROUP_SELECTED 211 -#define NNTP_LIST_FOLLOWS 215 -#define NNTP_ARTICLE_FOLLOWS 220 -#define NNTP_HEAD_FOLLOWS 221 -#define NNTP_DATA_FOLLOWS 224 -#define NNTP_NEW_ARTICLE_LIST_FOLLOWS 230 -#define NNTP_NEW_GROUP_LIST_FOLLOWS 231 - -#define NNTP_NO_SUCH_GROUP 411 -#define NNTP_NO_SUCH_ARTICLE 430 - -#define NNTP_NO_PERMISSION 502 - -/* authentication */ -#define NNTP_AUTH_ACCEPTED 281 -#define NNTP_AUTH_CONTINUE 381 -#define NNTP_AUTH_REQUIRED 480 -#define NNTP_AUTH_REJECTED 482 - -#define NNTP_PROTOCOL_ERROR 666 - -#endif /* CAMEL_NNTP_RESP_CODES_H */ diff --git a/camel/providers/nntp/camel-nntp-store.c b/camel/providers/nntp/camel-nntp-store.c deleted file mode 100644 index 531d4aefdf..0000000000 --- a/camel/providers/nntp/camel-nntp-store.c +++ /dev/null @@ -1,576 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * - * Copyright (C) 2001-2003 Ximian, Inc. - * - * Authors: Christopher Toshok - * Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "camel-nntp-summary.h" -#include "camel-nntp-store.h" -#include "camel-nntp-folder.h" -#include "camel-nntp-private.h" - -#define w(x) -extern int camel_verbose_debug; -#define dd(x) (camel_verbose_debug?(x):0) - -#define NNTP_PORT 119 -#define NNTPS_PORT 563 - -#define DUMP_EXTENSIONS - -/* define if you want the subscribe ui to show folders in tree form */ -/* #define INFO_AS_TREE */ - -static CamelStoreClass *parent_class = NULL; -static CamelServiceClass *service_class = NULL; - -/* Returns the class for a CamelNNTPStore */ -#define CNNTPS_CLASS(so) CAMEL_NNTP_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CNNTPF_CLASS(so) CAMEL_NNTP_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - - -enum { - USE_SSL_NEVER, - USE_SSL_ALWAYS, - USE_SSL_WHEN_POSSIBLE -}; - -static gboolean -connect_to_server (CamelService *service, int ssl_mode, CamelException *ex) -{ - CamelNNTPStore *store = (CamelNNTPStore *) service; - CamelStream *tcp_stream; - gboolean retval = FALSE; - unsigned char *buf; - unsigned int len; - struct hostent *h; - int port, ret; - - CAMEL_NNTP_STORE_LOCK(store, command_lock); - - /* setup store-wide cache */ - if (store->cache == NULL) { - char *root; - - root = camel_session_get_storage_path (service->session, service, ex); - if (root == NULL) - goto fail; - - store->cache = camel_data_cache_new (root, 0, ex); - g_free (root); - if (store->cache == NULL) - goto fail; - - /* Default cache expiry - 2 weeks old, or not visited in 5 days */ - camel_data_cache_set_expire_age (store->cache, 60*60*24*14); - camel_data_cache_set_expire_access (store->cache, 60*60*24*5); - } - - h = camel_service_gethost (service, ex); - if (!h) - goto fail; - - port = service->url->port ? service->url->port : NNTP_PORT; - -#ifdef HAVE_SSL - if (ssl_mode != USE_SSL_NEVER) { - port = service->url->port ? service->url->port : NNTPS_PORT; - tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3); - } else { - tcp_stream = camel_tcp_stream_raw_new (); - } -#else - tcp_stream = camel_tcp_stream_raw_new (); -#endif /* HAVE_SSL */ - - ret = camel_tcp_stream_connect (CAMEL_TCP_STREAM (tcp_stream), h, port); - camel_free_host (h); - if (ret == -1) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Connection cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s (port %d): %s"), - service->url->host, port, g_strerror (errno)); - - camel_object_unref (CAMEL_OBJECT (tcp_stream)); - - goto fail; - } - - store->stream = (CamelNNTPStream *) camel_nntp_stream_new (tcp_stream); - camel_object_unref (CAMEL_OBJECT (tcp_stream)); - - /* Read the greeting, if any. */ - if (camel_nntp_stream_line (store->stream, &buf, &len) == -1) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Connection cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not read greeting from %s: %s"), - service->url->host, g_strerror (errno)); - - camel_object_unref (CAMEL_OBJECT (store->stream)); - store->stream = NULL; - - goto fail; - } - - len = strtoul (buf, (char **) &buf, 10); - if (len != 200 && len != 201) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("NNTP server %s returned error code %d: %s"), - service->url->host, len, buf); - - camel_object_unref (CAMEL_OBJECT (store->stream)); - store->stream = NULL; - - goto fail; - } - - /* set 'reader' mode & ignore return code */ - camel_nntp_command (store, (char **) &buf, "mode reader"); - retval = TRUE; - - fail: - CAMEL_NNTP_STORE_UNLOCK(store, command_lock); - - return retval; -} - -static struct { - char *value; - int mode; -} ssl_options[] = { - { "", USE_SSL_ALWAYS }, - { "always", USE_SSL_ALWAYS }, - { "when-possible", USE_SSL_WHEN_POSSIBLE }, - { "never", USE_SSL_NEVER }, - { NULL, USE_SSL_NEVER }, -}; - -static gboolean -nntp_connect (CamelService *service, CamelException *ex) -{ -#ifdef HAVE_SSL - const char *use_ssl; - int i, ssl_mode; - - use_ssl = camel_url_get_param (service->url, "use_ssl"); - if (use_ssl) { - for (i = 0; ssl_options[i].value; i++) - if (!strcmp (ssl_options[i].value, use_ssl)) - break; - ssl_mode = ssl_options[i].mode; - } else - ssl_mode = USE_SSL_NEVER; - - if (ssl_mode == USE_SSL_ALWAYS) { - /* Connect via SSL */ - return connect_to_server (service, ssl_mode, ex); - } else if (ssl_mode == USE_SSL_WHEN_POSSIBLE) { - /* If the server supports SSL, use it */ - if (!connect_to_server (service, ssl_mode, ex)) { - if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE) { - /* The ssl port seems to be unavailable, fall back to plain NNTP */ - camel_exception_clear (ex); - return connect_to_server (service, USE_SSL_NEVER, ex); - } else { - return FALSE; - } - } - - return TRUE; - } else { - /* User doesn't care about SSL */ - return connect_to_server (service, ssl_mode, ex); - } -#else - return connect_to_server (service, USE_SSL_NEVER, ex); -#endif -} - -static gboolean -nntp_disconnect (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelNNTPStore *store = CAMEL_NNTP_STORE (service); - char *line; - - CAMEL_NNTP_STORE_LOCK(store, command_lock); - - if (clean) - camel_nntp_command (store, &line, "quit"); - - if (!service_class->disconnect (service, clean, ex)) - return FALSE; - - camel_object_unref((CamelObject *)store->stream); - store->stream = NULL; - - CAMEL_NNTP_STORE_UNLOCK(store, command_lock); - - return TRUE; -} - -static char * -nntp_store_get_name (CamelService *service, gboolean brief) -{ - if (brief) - return g_strdup_printf ("%s", service->url->host); - else - return g_strdup_printf (_("USENET News via %s"), service->url->host); - -} - -static CamelServiceAuthType password_authtype = { - N_("Password"), - - N_("This option will authenticate with the NNTP server using a " - "plaintext password."), - - "", - TRUE -}; - -static GList * -nntp_store_query_auth_types (CamelService *service, CamelException *ex) -{ - g_warning ("nntp::query_auth_types: not implemented. Defaulting."); - - return g_list_append (NULL, &password_authtype); -} - -static CamelFolder * -nntp_store_get_folder(CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store); - CamelFolder *folder; - - CAMEL_NNTP_STORE_LOCK(nntp_store, command_lock); - - folder = camel_nntp_folder_new(store, folder_name, ex); - - CAMEL_NNTP_STORE_UNLOCK(nntp_store, command_lock); - - return folder; -} - -static CamelFolderInfo * -nntp_store_get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelURL *url = CAMEL_SERVICE (store)->url; - CamelNNTPStore *nntp_store = (CamelNNTPStore *)store; - CamelFolderInfo *groups = NULL, *last = NULL, *fi; - unsigned int len; - unsigned char *line, *space; - int ret = -1; - - CAMEL_NNTP_STORE_LOCK(nntp_store, command_lock); - - ret = camel_nntp_command(nntp_store, (char **)&line, "list"); - if (ret != 215) { - ret = -1; - goto error; - } - - while ( (ret = camel_nntp_stream_line(nntp_store->stream, &line, &len)) > 0) { - space = strchr(line, ' '); - if (space) - *space = 0; - - if (top == NULL || top[0] == 0 || strcmp(top, line) == 0) { - fi = g_malloc0(sizeof(*fi)); - fi->name = g_strdup(line); - fi->full_name = g_strdup(line); - if (url->user) - fi->url = g_strdup_printf ("nntp://%s@%s/%s", url->user, url->host, line); - else - fi->url = g_strdup_printf ("nntp://%s/%s", url->host, line); - fi->unread_message_count = -1; - camel_folder_info_build_path(fi, '/'); - - if (last) - last->sibling = fi; - else - groups = fi; - last = fi; - } - } - - if (ret < 0) - goto error; - - CAMEL_NNTP_STORE_UNLOCK(nntp_store, command_lock); - - return groups; - -error: - CAMEL_NNTP_STORE_UNLOCK(nntp_store, command_lock); - - if (groups) - camel_store_free_folder_info(store, groups); - - return NULL; -} - -static gboolean -nntp_store_folder_subscribed (CamelStore *store, const char *folder_name) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store); - - nntp_store = nntp_store; - - /* FIXME: implement */ - - return TRUE; -} - -static void -nntp_store_subscribe_folder (CamelStore *store, const char *folder_name, - CamelException *ex) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store); - - nntp_store = nntp_store; - - /* FIXME: implement */ -} - -static void -nntp_store_unsubscribe_folder (CamelStore *store, const char *folder_name, - CamelException *ex) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store); - - nntp_store = nntp_store; - - /* FIXME: implement */ -} - -static void -nntp_store_finalise (CamelObject *object) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (object); - struct _CamelNNTPStorePrivate *p = nntp_store->priv; - - camel_service_disconnect((CamelService *)object, TRUE, NULL); - - camel_object_unref((CamelObject *)nntp_store->mem); - nntp_store->mem = NULL; - if (nntp_store->stream) - camel_object_unref((CamelObject *)nntp_store->stream); - - e_mutex_destroy(p->command_lock); - - g_free(p); -} - -static void -nntp_store_class_init (CamelNNTPStoreClass *camel_nntp_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_nntp_store_class); - CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS (camel_nntp_store_class); - - parent_class = CAMEL_STORE_CLASS (camel_type_get_global_classfuncs (camel_store_get_type ())); - - service_class = CAMEL_SERVICE_CLASS (camel_type_get_global_classfuncs (camel_service_get_type ())); - - /* virtual method overload */ - camel_service_class->connect = nntp_connect; - camel_service_class->disconnect = nntp_disconnect; - camel_service_class->query_auth_types = nntp_store_query_auth_types; - camel_service_class->get_name = nntp_store_get_name; - - camel_store_class->get_folder = nntp_store_get_folder; - camel_store_class->get_folder_info = nntp_store_get_folder_info; - camel_store_class->free_folder_info = camel_store_free_folder_info_full; - - camel_store_class->folder_subscribed = nntp_store_folder_subscribed; - camel_store_class->subscribe_folder = nntp_store_subscribe_folder; - camel_store_class->unsubscribe_folder = nntp_store_unsubscribe_folder; -} - -static void -nntp_store_init (gpointer object, gpointer klass) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE(object); - CamelStore *store = CAMEL_STORE (object); - struct _CamelNNTPStorePrivate *p; - - store->flags = CAMEL_STORE_SUBSCRIPTIONS; - - nntp_store->mem = (CamelStreamMem *)camel_stream_mem_new(); - - p = nntp_store->priv = g_malloc0(sizeof(*p)); - p->command_lock = e_mutex_new(E_MUTEX_REC); -} - -CamelType -camel_nntp_store_get_type (void) -{ - static CamelType camel_nntp_store_type = CAMEL_INVALID_TYPE; - - if (camel_nntp_store_type == CAMEL_INVALID_TYPE) { - camel_nntp_store_type = - camel_type_register (CAMEL_STORE_TYPE, - "CamelNNTPStore", - sizeof (CamelNNTPStore), - sizeof (CamelNNTPStoreClass), - (CamelObjectClassInitFunc) nntp_store_class_init, - NULL, - (CamelObjectInitFunc) nntp_store_init, - (CamelObjectFinalizeFunc) nntp_store_finalise); - } - - return camel_nntp_store_type; -} - -/* enter owning lock */ -int -camel_nntp_store_set_folder (CamelNNTPStore *store, CamelFolder *folder, CamelFolderChangeInfo *changes, CamelException *ex) -{ - int ret; - - if (store->current_folder && strcmp(folder->full_name, store->current_folder) == 0) - return 0; - - /* FIXME: Do something with changeinfo */ - ret = camel_nntp_summary_check((CamelNNTPSummary *)folder->summary, changes, ex); - - g_free(store->current_folder); - store->current_folder = g_strdup(folder->full_name); - - return ret; -} - -static gboolean -nntp_connected (CamelNNTPStore *store, CamelException *ex) -{ - if (store->stream == NULL) - return camel_service_connect (CAMEL_SERVICE (store), ex); - return TRUE; -} - -/* Enter owning lock */ -int -camel_nntp_command(CamelNNTPStore *store, char **line, const char *fmt, ...) -{ - const unsigned char *p, *ps; - unsigned char c; - va_list ap; - char *s; - int d; - unsigned int u, u2; - - e_mutex_assert_locked(store->priv->command_lock); - - if (!nntp_connected (store, NULL)) - return -1; - - /* Check for unprocessed data, ! */ - if (store->stream->mode == CAMEL_NNTP_STREAM_DATA) { - g_warning("Unprocessed data left in stream, flushing"); - while (camel_nntp_stream_getd(store->stream, (unsigned char **)&p, &u) > 0) - ; - } - camel_nntp_stream_set_mode(store->stream, CAMEL_NNTP_STREAM_LINE); - - va_start(ap, fmt); - ps = p = fmt; - while ( (c = *p++) ) { - switch (c) { - case '%': - c = *p++; - camel_stream_write((CamelStream *)store->mem, ps, p-ps-(c=='%'?1:2)); - ps = p; - switch (c) { - case 's': - s = va_arg(ap, char *); - camel_stream_write((CamelStream *)store->mem, s, strlen(s)); - break; - case 'd': - d = va_arg(ap, int); - camel_stream_printf((CamelStream *)store->mem, "%d", d); - break; - case 'u': - u = va_arg(ap, unsigned int); - camel_stream_printf((CamelStream *)store->mem, "%u", u); - break; - case 'm': - s = va_arg(ap, char *); - camel_stream_printf((CamelStream *)store->mem, "<%s>", s); - break; - case 'r': - u = va_arg(ap, unsigned int); - u2 = va_arg(ap, unsigned int); - if (u == u2) - camel_stream_printf((CamelStream *)store->mem, "%u", u); - else - camel_stream_printf((CamelStream *)store->mem, "%u-%u", u, u2); - break; - default: - g_warning("Passing unknown format to nntp_command: %c\n", c); - g_assert(0); - } - } - } - - camel_stream_write((CamelStream *)store->mem, ps, p-ps-1); - dd(printf("NNTP_COMMAND: '%.*s'\n", (int)store->mem->buffer->len, store->mem->buffer->data)); - camel_stream_write((CamelStream *)store->mem, "\r\n", 2); - camel_stream_write((CamelStream *)store->stream, store->mem->buffer->data, store->mem->buffer->len); - camel_stream_reset((CamelStream *)store->mem); - /* FIXME: hack */ - g_byte_array_set_size(store->mem->buffer, 0); - - if (camel_nntp_stream_line(store->stream, (unsigned char **)line, &u) == -1) - return -1; - - u = strtoul(*line, NULL, 10); - - /* Handle all switching to data mode here, to make callers job easier */ - if (u == 215 || (u >= 220 && u <=224) || (u >= 230 && u <= 231)) - camel_nntp_stream_set_mode(store->stream, CAMEL_NNTP_STREAM_DATA); - - return u; -} - diff --git a/camel/providers/nntp/camel-nntp-store.h b/camel/providers/nntp/camel-nntp-store.h deleted file mode 100644 index a201c2cea2..0000000000 --- a/camel/providers/nntp/camel-nntp-store.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-store.h : class for an nntp store */ - -/* - * - * Copyright (C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_NNTP_STORE_H -#define CAMEL_NNTP_STORE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include -#include -#include -#include -#include - -#include "camel-nntp-stream.h" - -#define CAMEL_NNTP_STORE_TYPE (camel_nntp_store_get_type ()) -#define CAMEL_NNTP_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_NNTP_STORE_TYPE, CamelNNTPStore)) -#define CAMEL_NNTP_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_NNTP_STORE_TYPE, CamelNNTPStoreClass)) -#define CAMEL_IS_NNTP_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_NNTP_STORE_TYPE)) - -#define CAMEL_NNTP_EXT_SEARCH (1<<0) -#define CAMEL_NNTP_EXT_SETGET (1<<1) -#define CAMEL_NNTP_EXT_OVER (1<<2) -#define CAMEL_NNTP_EXT_XPATTEXT (1<<3) -#define CAMEL_NNTP_EXT_XACTIVE (1<<4) -#define CAMEL_NNTP_EXT_LISTMOTD (1<<5) -#define CAMEL_NNTP_EXT_LISTSUBSCR (1<<6) -#define CAMEL_NNTP_EXT_LISTPNAMES (1<<7) - -typedef struct _CamelNNTPStore CamelNNTPStore; -typedef struct _CamelNNTPStoreClass CamelNNTPStoreClass; - -struct _CamelNNTPStore { - CamelStore parent_object; - - struct _CamelNNTPStorePrivate *priv; - - guint32 extensions; - - gboolean posting_allowed; - - CamelNNTPStream *stream; - CamelStreamMem *mem; - - CamelDataCache *cache; - - char *current_folder; -}; - -struct _CamelNNTPStoreClass { - CamelStoreClass parent_class; - -}; - -/* Standard Camel function */ -CamelType camel_nntp_store_get_type (void); - -int camel_nntp_command(CamelNNTPStore *store, char **line, const char *fmt, ...); -int camel_nntp_store_set_folder(CamelNNTPStore *store, CamelFolder *folder, CamelFolderChangeInfo *changes, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_NNTP_STORE_H */ - - diff --git a/camel/providers/nntp/camel-nntp-stream.c b/camel/providers/nntp/camel-nntp-stream.c deleted file mode 100644 index 1e2dcb23f9..0000000000 --- a/camel/providers/nntp/camel-nntp-stream.c +++ /dev/null @@ -1,462 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Author: - * Michael Zucchi - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include -#include - -#include - -#include "camel-nntp-stream.h" - -extern int camel_verbose_debug; -#define dd(x) (camel_verbose_debug?(x):0) - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelStream */ -#define CS_CLASS(so) CAMEL_NNTP_STREAM_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -#define CAMEL_NNTP_STREAM_SIZE (4096) -#define CAMEL_NNTP_STREAM_LINE (1024) /* maximum line size */ - -static int -stream_fill(CamelNNTPStream *is) -{ - int left = 0; - - if (is->source) { - left = is->end - is->ptr; - memcpy(is->buf, is->ptr, left); - is->end = is->buf + left; - is->ptr = is->buf; - left = camel_stream_read(is->source, is->end, CAMEL_NNTP_STREAM_SIZE - (is->end - is->buf)); - if (left > 0) { - is->end += left; - is->end[0] = '\n'; - return is->end - is->ptr; - } else { - dd(printf("NNTP_STREAM_FILL(ERROR): '%s'\n", strerror(errno))); - return -1; - } - } - - return 0; -} - -static ssize_t -stream_read(CamelStream *stream, char *buffer, size_t n) -{ - CamelNNTPStream *is = (CamelNNTPStream *)stream; - char *o, *oe; - unsigned char *p, *e, c; - int state; - - if (is->mode != CAMEL_NNTP_STREAM_DATA || n == 0) - return 0; - - o = buffer; - oe = buffer + n; - state = is->state; - - /* Need to copy/strip '.'s and whatnot */ - p = is->ptr; - e = is->end; - - switch(state) { - state_0: - case 0: /* start of line, always read at least 3 chars */ - while (e - p < 3) { - is->ptr = p; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } - if (p[0] == '.') { - if (p[1] == '\r' && p[2] == '\n') { - is->ptr = p+3; - is->mode = CAMEL_NNTP_STREAM_EOD; - is->state = 0; - dd(printf("NNTP_STREAM_READ(%d):\n%.*s\n", o-buffer, o-buffer, buffer)); - return o-buffer; - } - p++; - } - state = 1; - /* FALLS THROUGH */ - case 1: /* looking for next sol */ - while (o < oe) { - c = *p++; - if (c == '\n') { - /* end of input sentinal check */ - if (p > e) { - is->ptr = e; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } else { - *o++ = '\n'; - state = 0; - goto state_0; - } - } else if (c != '\r') { - *o++ = c; - } - } - break; - } - - is->ptr = p; - is->state = state; - - dd(printf("NNTP_STREAM_READ(%d):\n%.*s\n", o-buffer, o-buffer, buffer)); - - return o-buffer; -} - -static ssize_t -stream_write(CamelStream *stream, const char *buffer, size_t n) -{ - CamelNNTPStream *is = (CamelNNTPStream *)stream; - - return camel_stream_write(is->source, buffer, n); -} - -static int -stream_close(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static int -stream_flush(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static gboolean -stream_eos(CamelStream *stream) -{ - CamelNNTPStream *is = (CamelNNTPStream *)stream; - - return is->mode != CAMEL_NNTP_STREAM_DATA; -} - -static int -stream_reset(CamelStream *stream) -{ - /* nop? reset literal mode? */ - return 0; -} - -static void -camel_nntp_stream_class_init (CamelStreamClass *camel_nntp_stream_class) -{ - CamelStreamClass *camel_stream_class = (CamelStreamClass *)camel_nntp_stream_class; - - parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE ); - - /* virtual method definition */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->close = stream_close; - camel_stream_class->flush = stream_flush; - camel_stream_class->eos = stream_eos; - camel_stream_class->reset = stream_reset; -} - -static void -camel_nntp_stream_init(CamelNNTPStream *is, CamelNNTPStreamClass *isclass) -{ - /* +1 is room for appending a 0 if we need to for a line */ - is->ptr = is->end = is->buf = g_malloc(CAMEL_NNTP_STREAM_SIZE+1); - is->lineptr = is->linebuf = g_malloc(CAMEL_NNTP_STREAM_LINE+1); - is->lineend = is->linebuf + CAMEL_NNTP_STREAM_LINE; - - /* init sentinal */ - is->ptr[0] = '\n'; - - is->state = 0; - is->mode = CAMEL_NNTP_STREAM_LINE; -} - -static void -camel_nntp_stream_finalise(CamelNNTPStream *is) -{ - g_free(is->buf); - g_free(is->linebuf); - if (is->source) - camel_object_unref((CamelObject *)is->source); -} - -CamelType -camel_nntp_stream_get_type (void) -{ - static CamelType camel_nntp_stream_type = CAMEL_INVALID_TYPE; - - if (camel_nntp_stream_type == CAMEL_INVALID_TYPE) { - camel_nntp_stream_type = camel_type_register( camel_stream_get_type(), - "CamelNNTPStream", - sizeof( CamelNNTPStream ), - sizeof( CamelNNTPStreamClass ), - (CamelObjectClassInitFunc) camel_nntp_stream_class_init, - NULL, - (CamelObjectInitFunc) camel_nntp_stream_init, - (CamelObjectFinalizeFunc) camel_nntp_stream_finalise ); - } - - return camel_nntp_stream_type; -} - -/** - * camel_nntp_stream_new: - * - * Returns a NULL stream. A null stream is always at eof, and - * always returns success for all reads and writes. - * - * Return value: the stream - **/ -CamelStream * -camel_nntp_stream_new(CamelStream *source) -{ - CamelNNTPStream *is; - - is = (CamelNNTPStream *)camel_object_new(camel_nntp_stream_get_type ()); - camel_object_ref((CamelObject *)source); - is->source = source; - - return (CamelStream *)is; -} - -/* Get one line from the nntp stream */ -int -camel_nntp_stream_line(CamelNNTPStream *is, unsigned char **data, unsigned int *len) -{ - register unsigned char c, *p, *o, *oe; - int newlen, oldlen; - unsigned char *e; - - if (is->mode == CAMEL_NNTP_STREAM_EOD) { - *data = is->linebuf; - *len = 0; - return 0; - } - - o = is->linebuf; - oe = is->lineend - 1; - p = is->ptr; - e = is->end; - - /* Data mode, convert leading '..' to '.', and stop when we reach a solitary '.' */ - if (is->mode == CAMEL_NNTP_STREAM_DATA) { - /* need at least 3 chars in buffer */ - while (e-p < 3) { - is->ptr = p; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } - - /* check for isolated '.\r\n' or begging of line '.' */ - if (p[0] == '.') { - if (p[1] == '\r' && p[2] == '\n') { - is->ptr = p+3; - is->mode = CAMEL_NNTP_STREAM_EOD; - *data = is->linebuf; - *len = 0; - is->linebuf[0] = 0; - - dd(printf("NNTP_STREAM_LINE(END)\n")); - - return 0; - } - p++; - } - } - - while (1) { - while (o < oe) { - c = *p++; - if (c == '\n') { - /* sentinal? */ - if (p> e) { - is->ptr = e; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } else { - is->ptr = p; - *data = is->linebuf; - *len = o - is->linebuf; - *o = 0; - - dd(printf("NNTP_STREAM_LINE(%d): '%s'\n", *len, *data)); - - return 1; - } - } else if (c != '\r') { - *o++ = c; - } - } - - /* limit this for bad server data? */ - oldlen = o - is->linebuf; - newlen = (is->lineend - is->linebuf) * 3 / 2; - is->lineptr = is->linebuf = g_realloc(is->linebuf, newlen); - is->lineend = is->linebuf + newlen; - oe = is->lineend - 1; - o = is->linebuf + oldlen; - } - - return -1; -} - -/* returns -1 on error, 0 if last lot of data, >0 if more remaining */ -int camel_nntp_stream_gets(CamelNNTPStream *is, unsigned char **start, unsigned int *len) -{ - int max; - unsigned char *end; - - *len = 0; - - max = is->end - is->ptr; - if (max == 0) { - max = stream_fill(is); - if (max <= 0) - return max; - } - - *start = is->ptr; - end = memchr(is->ptr, '\n', max); - if (end) - max = (end - is->ptr) + 1; - *start = is->ptr; - *len = max; - is->ptr += max; - - dd(printf("NNTP_STREAM_GETS(%s,%d): '%.*s'\n", end==NULL?"more":"last", *len, (int)*len, *start)); - - return end == NULL?1:0; -} - -void camel_nntp_stream_set_mode(CamelNNTPStream *is, camel_nntp_stream_mode_t mode) -{ - is->mode = mode; -} - -/* returns -1 on erorr, 0 if last data, >0 if more data left */ -int camel_nntp_stream_getd(CamelNNTPStream *is, unsigned char **start, unsigned int *len) -{ - unsigned char *p, *e, *s; - int state; - - *len = 0; - - if (is->mode == CAMEL_NNTP_STREAM_EOD) - return 0; - - if (is->mode == CAMEL_NNTP_STREAM_LINE) { - g_warning("nntp_stream reading data in line mode\n"); - return 0; - } - - state = is->state; - p = is->ptr; - e = is->end; - - while (e - p < 3) { - is->ptr = p; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } - - s = p; - - do { - switch(state) { - case 0: - /* check leading '.', ... */ - if (p[0] == '.') { - if (p[1] == '\r' && p[2] == '\n') { - is->ptr = p+3; - *len = p-s; - *start = s; - is->mode = CAMEL_NNTP_STREAM_EOD; - is->state = 0; - - dd(printf("NNTP_STREAM_GETD(%s,%d): '%.*s'\n", "last", *len, (int)*len, *start)); - - return 0; - } - - /* If at start, just skip '.', else return data upto '.' but skip it */ - if (p == s) { - s++; - p++; - } else { - is->ptr = p+1; - *len = p-s; - *start = s; - is->state = 1; - - dd(printf("NNTP_STREAM_GETD(%s,%d): '%.*s'\n", "more", *len, (int)*len, *start)); - - return 1; - } - } - state = 1; - case 1: - /* Scan for sentinal */ - while ((*p++)!='\n') - ; - - if (p > e) { - p = e; - } else { - state = 0; - } - break; - } - } while ((e-p) >= 3); - - is->state = state; - is->ptr = p; - *len = p-s; - *start = s; - - dd(printf("NNTP_STREAM_GETD(%s,%d): '%.*s'\n", "more", *len, (int)*len, *start)); - return 1; -} - diff --git a/camel/providers/nntp/camel-nntp-stream.h b/camel/providers/nntp/camel-nntp-stream.h deleted file mode 100644 index eef217cef2..0000000000 --- a/camel/providers/nntp/camel-nntp-stream.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2001 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_NNTP_STREAM_H -#define _CAMEL_NNTP_STREAM_H - -#include - -#define CAMEL_NNTP_STREAM(obj) CAMEL_CHECK_CAST (obj, camel_nntp_stream_get_type (), CamelNNTPStream) -#define CAMEL_NNTP_STREAM_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_nntp_stream_get_type (), CamelNNTPStreamClass) -#define CAMEL_IS_NNTP_STREAM(obj) CAMEL_CHECK_TYPE (obj, camel_nntp_stream_get_type ()) - -typedef struct _CamelNNTPStreamClass CamelNNTPStreamClass; -typedef struct _CamelNNTPStream CamelNNTPStream; - -typedef enum { - CAMEL_NNTP_STREAM_LINE, - CAMEL_NNTP_STREAM_DATA, - CAMEL_NNTP_STREAM_EOD, /* end of data, acts as if end of stream */ -} camel_nntp_stream_mode_t; - -struct _CamelNNTPStream { - CamelStream parent; - - CamelStream *source; - - camel_nntp_stream_mode_t mode; - int state; - - unsigned char *buf, *ptr, *end; - unsigned char *linebuf, *lineptr, *lineend; -}; - -struct _CamelNNTPStreamClass { - CamelStreamClass parent_class; -}; - -CamelType camel_nntp_stream_get_type (void); - -CamelStream *camel_nntp_stream_new (CamelStream *source); - - -void camel_nntp_stream_set_mode (CamelNNTPStream *is, camel_nntp_stream_mode_t mode); - -int camel_nntp_stream_line (CamelNNTPStream *is, unsigned char **data, unsigned int *len); -int camel_nntp_stream_gets (CamelNNTPStream *is, unsigned char **start, unsigned int *len); -int camel_nntp_stream_getd (CamelNNTPStream *is, unsigned char **start, unsigned int *len); - -#endif /* ! _CAMEL_NNTP_STREAM_H */ diff --git a/camel/providers/nntp/camel-nntp-summary.c b/camel/providers/nntp/camel-nntp-summary.c deleted file mode 100644 index 2a9669d697..0000000000 --- a/camel/providers/nntp/camel-nntp-summary.c +++ /dev/null @@ -1,584 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "camel/camel-file-utils.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-stream-null.h" -#include "camel/camel-operation.h" -#include "camel/camel-data-cache.h" - -#include "camel-nntp-summary.h" -#include "camel-nntp-folder.h" -#include "camel-nntp-store.h" -#include "camel-nntp-stream.h" - -#define w(x) -#define io(x) -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ -extern int camel_verbose_debug; -#define dd(x) (camel_verbose_debug?(x):0) - -#define CAMEL_NNTP_SUMMARY_VERSION (0x200) - -static int xover_setup(CamelNNTPSummary *cns, CamelException *ex); -static int add_range_xover(CamelNNTPSummary *cns, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex); -static int add_range_head(CamelNNTPSummary *cns, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex); - -enum _xover_t { - XOVER_STRING = 0, - XOVER_MSGID, - XOVER_SIZE, -}; - -struct _xover_header { - struct _xover_header *next; - - const char *name; - unsigned int skip:8; - enum _xover_t type:8; -}; - -struct _CamelNNTPSummaryPrivate { - char *uid; - - struct _xover_header *xover; /* xoverview format */ - int xover_setup; -}; - -#define _PRIVATE(o) (((CamelNNTPSummary *)(o))->priv) - -static CamelMessageInfo * message_info_new (CamelFolderSummary *, struct _camel_header_raw *); -static int summary_header_load(CamelFolderSummary *, FILE *); -static int summary_header_save(CamelFolderSummary *, FILE *); - -static void camel_nntp_summary_class_init (CamelNNTPSummaryClass *klass); -static void camel_nntp_summary_init (CamelNNTPSummary *obj); -static void camel_nntp_summary_finalise (CamelObject *obj); -static CamelFolderSummaryClass *camel_nntp_summary_parent; - -CamelType -camel_nntp_summary_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_folder_summary_get_type(), "CamelNNTPSummary", - sizeof (CamelNNTPSummary), - sizeof (CamelNNTPSummaryClass), - (CamelObjectClassInitFunc) camel_nntp_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_nntp_summary_init, - (CamelObjectFinalizeFunc) camel_nntp_summary_finalise); - } - - return type; -} - -static void -camel_nntp_summary_class_init(CamelNNTPSummaryClass *klass) -{ - CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) klass; - - camel_nntp_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type())); - - sklass->message_info_new = message_info_new; - sklass->summary_header_load = summary_header_load; - sklass->summary_header_save = summary_header_save; -} - -static void -camel_nntp_summary_init(CamelNNTPSummary *obj) -{ - struct _CamelNNTPSummaryPrivate *p; - struct _CamelFolderSummary *s = (CamelFolderSummary *)obj; - - p = _PRIVATE(obj) = g_malloc0(sizeof(*p)); - - /* subclasses need to set the right instance data sizes */ - s->message_info_size = sizeof(CamelMessageInfo); - s->content_info_size = sizeof(CamelMessageContentInfo); - - /* and a unique file version */ - s->version += CAMEL_NNTP_SUMMARY_VERSION; -} - -static void -camel_nntp_summary_finalise(CamelObject *obj) -{ - CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY(obj); - struct _xover_header *xover, *xn; - - xover = cns->priv->xover; - while (xover) { - xn = xover->next; - g_free(xover); - xover = xn; - } - - g_free(cns->priv); -} - -CamelNNTPSummary * -camel_nntp_summary_new(CamelNNTPFolder *folder) -{ - CamelNNTPSummary *cns = (CamelNNTPSummary *)camel_object_new(camel_nntp_summary_get_type()); - char *path; - - cns->folder = folder; - path = g_strdup_printf("%s.ev-summary", folder->storage_path); - camel_folder_summary_set_filename((CamelFolderSummary *)cns, path); - g_free(path); - - camel_folder_summary_set_build_content((CamelFolderSummary *)cns, FALSE); - - return cns; -} - -static CamelMessageInfo * -message_info_new(CamelFolderSummary *s, struct _camel_header_raw *h) -{ - CamelMessageInfo *mi; - CamelNNTPSummary *cns = (CamelNNTPSummary *)s; - - /* error to call without this setup */ - if (cns->priv->uid == NULL) - return NULL; - - /* we shouldn't be here if we already have this uid */ - g_assert(camel_folder_summary_uid(s, cns->priv->uid) == NULL); - - mi = ((CamelFolderSummaryClass *)camel_nntp_summary_parent)->message_info_new(s, h); - if (mi) { - camel_message_info_set_uid(mi, cns->priv->uid); - cns->priv->uid = NULL; - } - - return mi; -} - -static int -summary_header_load(CamelFolderSummary *s, FILE *in) -{ - CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY(s); - - if (((CamelFolderSummaryClass *)camel_nntp_summary_parent)->summary_header_load(s, in) == -1 - || camel_file_util_decode_fixed_int32(in, &cns->high) == -1 - || camel_file_util_decode_fixed_int32(in, &cns->low) == -1) - return -1; - - return 0; -} - -static int -summary_header_save(CamelFolderSummary *s, FILE *out) -{ - CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY(s); - - if (((CamelFolderSummaryClass *)camel_nntp_summary_parent)->summary_header_save(s, out) == -1 - || camel_file_util_encode_fixed_int32(out, cns->high) == -1 - || camel_file_util_encode_fixed_int32(out, cns->low) == -1) - return -1; - - return 0; -} - -/* Assumes we have the stream */ -int -camel_nntp_summary_check(CamelNNTPSummary *cns, CamelFolderChangeInfo *changes, CamelException *ex) -{ - CamelNNTPStore *store; - CamelFolder *folder; - CamelFolderSummary *s; - int ret, i; - char *line; - unsigned int n, f, l; - int count; - - if (xover_setup(cns, ex) == -1) - return -1; - - folder = (CamelFolder *)cns->folder; - store = (CamelNNTPStore *)folder->parent_store; - s = (CamelFolderSummary *)cns; - - ret = camel_nntp_command(store, &line, "group %s", folder->full_name); - if (ret == 411) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID, - _("No such folder: %s"), line); - return -1; - } else if (ret != 211) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not get group: %s"), line); - return -1; - } - - line +=3; - n = strtoul(line, &line, 10); - f = strtoul(line, &line, 10); - l = strtoul(line, &line, 10); - - dd(printf("nntp_summary: got last '%u' first '%u'\n" - "nntp_summary: high '%u' low '%u'\n", l, f, cns->high, cns->low)); - - if (cns->low == f && cns->high == l) { - dd(printf("nntp_summary: no work to do!\n")); - return 0; - } - - /* Need to work out what to do with our messages */ - - /* Check for messages no longer on the server */ - if (cns->low != f) { - count = camel_folder_summary_count(s); - for (i = 0; i < count; i++) { - CamelMessageInfo *mi = camel_folder_summary_index(s, i); - - if (mi) { - const char *uid = camel_message_info_uid(mi); - const char *msgid; - - n = strtoul(uid, NULL, 10); - if (n < f || n > l) { - dd(printf("nntp_summary: %u is lower/higher than lowest/highest article, removed\n", n)); - /* Since we use a global cache this could prematurely remove - a cached message that might be in another folder - not that important as - it is a true cache */ - msgid = strchr(uid, ','); - if (msgid) - camel_data_cache_remove(store->cache, "cache", msgid+1, NULL); - camel_folder_change_info_remove_uid(changes, uid); - camel_folder_summary_remove(s, mi); - count--; - i--; - } - - camel_folder_summary_info_free(s, mi); - } - } - cns->low = f; - } - - if (cns->high < l) { - if (cns->high < f) - cns->high = f-1; - - if (cns->priv->xover) { - ret = add_range_xover(cns, l, cns->high+1, changes, ex); - } else { - ret = add_range_head(cns, l, cns->high+1, changes, ex); - } - } - - camel_folder_summary_touch(s); - - return ret; -} - -static struct { - const char *name; - int type; -} headers[] = { - { "subject", 0 }, - { "from", 0 }, - { "date", 0 }, - { "message-id", 1 }, - { "references", 0 }, - { "bytes", 2 }, -}; - -static int -xover_setup(CamelNNTPSummary *cns, CamelException *ex) -{ - CamelNNTPStore *store; - CamelFolder *folder; - CamelFolderSummary *s; - int ret, i; - char *line; - unsigned int len; - unsigned char c, *p; - struct _xover_header *xover, *last; - - if (cns->priv->xover_setup) - return 0; - - /* manual override */ - if (getenv("CAMEL_NNTP_DISABLE_XOVER") != NULL) { - cns->priv->xover_setup = TRUE; - return 0; - } - - folder = (CamelFolder *)cns->folder; - store = (CamelNNTPStore *)folder->parent_store; - s = (CamelFolderSummary *)cns; - - ret = camel_nntp_command(store, &line, "list overview.fmt"); - if (ret == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("NNTP Command failed: %s"), strerror(errno)); - return -1; - } - - cns->priv->xover_setup = TRUE; - - /* unsupported command? */ - if (ret != 215) - return 0; - - last = (struct _xover_header *)&cns->priv->xover; - - /* supported command */ - while ((ret = camel_nntp_stream_line(store->stream, (unsigned char **)&line, &len)) > 0) { - p = line; - xover = g_malloc0(sizeof(*xover)); - last->next = xover; - last = xover; - while ((c = *p++)) { - if (c == ':') { - p[-1] = 0; - for (i=0;iname = headers[i].name; - if (strncmp(p, "full", 4) == 0) - xover->skip = strlen(xover->name)+1; - else - xover->skip = 0; - xover->type = headers[i].type; - break; - } - } - break; - } else { - p[-1] = tolower(c); - } - } - } - - return ret; -} - -static int -add_range_xover(CamelNNTPSummary *cns, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex) -{ - CamelNNTPStore *store; - CamelFolder *folder; - CamelFolderSummary *s; - CamelMessageInfo *mi; - struct _camel_header_raw *headers = NULL; - char *line, *tab; - int len, ret; - unsigned int n, count, total, size; - struct _xover_header *xover; - time_t last, now; - - folder = (CamelFolder *)cns->folder; - store = (CamelNNTPStore *)folder->parent_store; - s = (CamelFolderSummary *)cns; - - camel_operation_start(NULL, _("%s: Scanning new messages"), ((CamelService *)store)->url->host); - - ret = camel_nntp_command(store, &line, "xover %r", low, high); - if (ret != 224) { - camel_operation_end(NULL); - return -1; - } - - last = time(0); - count = 0; - total = high-low+1; - while ((ret = camel_nntp_stream_line(store->stream, (unsigned char **)&line, &len)) > 0) { - camel_operation_progress(NULL, (count * 100) / total); - count++; - n = strtoul(line, &tab, 10); - if (*tab != '\t') - continue; - tab++; - xover = cns->priv->xover; - size = 0; - for (;tab[0] && xover;xover = xover->next) { - line = tab; - tab = strchr(line, '\t'); - if (tab) - *tab++ = 0; - else - tab = line+strlen(line); - - /* do we care about this column? */ - if (xover->name) { - line += xover->skip; - if (line < tab) { - camel_header_raw_append(&headers, xover->name, line, -1); - switch(xover->type) { - case XOVER_STRING: - break; - case XOVER_MSGID: - cns->priv->uid = g_strdup_printf("%u,%s", n, line); - break; - case XOVER_SIZE: - size = strtoul(line, NULL, 10); - break; - } - } - } - } - - /* truncated line? ignore? */ - if (xover == NULL) { - mi = camel_folder_summary_uid(s, cns->priv->uid); - if (mi == NULL) { - mi = camel_folder_summary_add_from_header(s, headers); - if (mi) { - mi->size = size; - cns->high = n; - camel_folder_change_info_add_uid(changes, camel_message_info_uid(mi)); - } - } else { - camel_folder_summary_info_free(s, mi); - } - } - - if (cns->priv->uid) { - g_free(cns->priv->uid); - cns->priv->uid = NULL; - } - - camel_header_raw_clear(&headers); - - now = time(0); - if (last + 2 < now) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", changes); - camel_folder_change_info_clear(changes); - last = now; - } - } - - camel_operation_end(NULL); - - return ret; -} - -static int -add_range_head(CamelNNTPSummary *cns, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex) -{ - CamelNNTPStore *store; - CamelFolder *folder; - CamelFolderSummary *s; - int i, ret = -1; - char *line, *msgid; - unsigned int n, count, total; - CamelMessageInfo *mi; - CamelMimeParser *mp; - time_t now, last; - - folder = (CamelFolder *)cns->folder; - store = (CamelNNTPStore *)folder->parent_store; - s = (CamelFolderSummary *)cns; - - mp = camel_mime_parser_new(); - - camel_operation_start(NULL, _("%s: Scanning new messages"), ((CamelService *)store)->url->host); - - last = time(0); - count = 0; - total = high-low+1; - for (i=low;i'))){ - line[1] = 0; - cns->priv->uid = g_strdup_printf("%u,%s\n", n, msgid); - mi = camel_folder_summary_uid(s, cns->priv->uid); - if (mi == NULL) { - if (camel_mime_parser_init_with_stream(mp, (CamelStream *)store->stream) == -1) - goto error; - mi = camel_folder_summary_add_from_parser(s, mp); - while (camel_mime_parser_step(mp, NULL, NULL) != CAMEL_MIME_PARSER_STATE_EOF) - ; - if (mi == NULL) { - goto error; - } - cns->high = i; - camel_folder_change_info_add_uid(changes, camel_message_info_uid(mi)); - } else { - /* already have, ignore */ - camel_folder_summary_info_free(s, mi); - } - if (cns->priv->uid) { - g_free(cns->priv->uid); - cns->priv->uid = NULL; - } - } - - now = time(0); - if (last + 2 < now) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", changes); - camel_folder_change_info_clear(changes); - last = now; - } - } - - ret = 0; -error: - - if (ret == -1) { - if (errno == EINTR) - camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Use cancel")); - else - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Operation failed: %s"), strerror(errno)); - } -ioerror: - - if (cns->priv->uid) { - g_free(cns->priv->uid); - cns->priv->uid = NULL; - } - camel_object_unref((CamelObject *)mp); - - camel_operation_end(NULL); - - return ret; -} diff --git a/camel/providers/nntp/camel-nntp-summary.h b/camel/providers/nntp/camel-nntp-summary.h deleted file mode 100644 index 82070cdc31..0000000000 --- a/camel/providers/nntp/camel-nntp-summary.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_NNTP_SUMMARY_H -#define _CAMEL_NNTP_SUMMARY_H - -#include -#include -#include -#include - -#define CAMEL_NNTP_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_nntp_summary_get_type (), CamelNNTPSummary) -#define CAMEL_NNTP_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_nntp_summary_get_type (), CamelNNTPSummaryClass) -#define CAMEL_IS_LOCAL_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_nntp_summary_get_type ()) - -typedef struct _CamelNNTPSummary CamelNNTPSummary; -typedef struct _CamelNNTPSummaryClass CamelNNTPSummaryClass; - -struct _CamelNNTPSummary { - CamelFolderSummary parent; - - struct _CamelNNTPSummaryPrivate *priv; - - struct _CamelNNTPFolder *folder; - - guint32 high, low; -}; - -struct _CamelNNTPSummaryClass { - CamelFolderSummaryClass parent_class; -}; - -CamelType camel_nntp_summary_get_type (void); -CamelNNTPSummary *camel_nntp_summary_new(struct _CamelNNTPFolder *folder); - -int camel_nntp_summary_check(CamelNNTPSummary *cns, CamelFolderChangeInfo *, CamelException *ex); - -#if 0 -/* load/check the summary */ -int camel_nntp_summary_load(CamelNNTPSummary *cls, CamelException *ex); -/* check for new/removed messages */ -int camel_nntp_summary_check(CamelNNTPSummary *cls, CamelFolderChangeInfo *, CamelException *ex); -/* perform a folder sync or expunge, if needed */ -int camel_nntp_summary_sync(CamelNNTPSummary *cls, gboolean expunge, CamelFolderChangeInfo *, CamelException *ex); -/* add a new message to the summary */ -CamelMessageInfo *camel_nntp_summary_add(CamelNNTPSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); -#endif - -#endif /* ! _CAMEL_NNTP_SUMMARY_H */ - diff --git a/camel/providers/nntp/camel-nntp-types.h b/camel/providers/nntp/camel-nntp-types.h deleted file mode 100644 index a37179c521..0000000000 --- a/camel/providers/nntp/camel-nntp-types.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-grouplist.h : getting/updating the list of newsgroups on the server. */ - -/* - * Author : Chris Toshok - * - * Copyright (C) 2000 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_NNTP_TYPES_H -#define CAMEL_NNTP_TYPES_H 1 - -typedef struct CamelNNTPGroupList CamelNNTPGroupList; -typedef struct CamelNNTPGroupListEntry CamelNNTPGroupListEntry; -typedef struct CamelNNTPOverField CamelNNTPOverField; -typedef struct CamelNNTPStore CamelNNTPStore; -typedef struct CamelNNTPStoreClass CamelNNTPStoreClass; - -#endif /* CAMEL_NNTP_TYPES_H */ diff --git a/camel/providers/nntp/camel-nntp-utils.c b/camel/providers/nntp/camel-nntp-utils.c deleted file mode 100644 index d8000a85ee..0000000000 --- a/camel/providers/nntp/camel-nntp-utils.c +++ /dev/null @@ -1,299 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-utils.c : utilities used by the nntp code. */ - -/* - * Author : Chris Toshok - * - * Copyright (C) 2000 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include "camel-folder-summary.h" -#include "camel-nntp-resp-codes.h" -#include "camel-nntp-folder.h" -#include "camel-nntp-store.h" -#include "camel-nntp-utils.h" -#include "camel-stream-mem.h" -#include "camel-exception.h" - -#include "e-util/md5-utils.h" - -#include -#include - -static void -get_XOVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, - int first_message, int last_message, CamelException *ex) -{ - int status; - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - char digest[16]; - - status = camel_nntp_command (nntp_store, ex, NULL, - "XOVER %d-%d", - first_message, - last_message); - - if (status == NNTP_DATA_FOLLOWS) { - gboolean done = FALSE; - - while (!done) { - char *line; - - if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (nntp_store), &line, ex) < 0) { - g_warning ("failed to recv_line while building OVER header list\n"); - break; - } - - if (*line == '.') { - done = TRUE; - g_print ("done\n"); - } - else { - CamelMessageInfo *new_info = camel_folder_summary_info_new(folder->summary); - char **split_line = g_strsplit (line, "\t", 7); - char *subject, *from, *date, *message_id, *bytes; - char *uid; - - subject = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_SUBJECT].index]; - from = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_FROM].index]; - date = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_DATE].index]; - message_id = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_MESSAGE_ID].index]; - bytes = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_BYTES].index]; - - /* if the overview format flagged this - field as "full", skip over the - preceding field name and colon */ - if (nntp_store->overview_field [ CAMEL_NNTP_OVER_SUBJECT ].full) - subject += strlen ("Subject:"); - if (nntp_store->overview_field [ CAMEL_NNTP_OVER_FROM ].full) - from += strlen ("From:"); - if (nntp_store->overview_field [ CAMEL_NNTP_OVER_DATE ].full) - date += strlen ("Date:"); - if (nntp_store->overview_field [ CAMEL_NNTP_OVER_MESSAGE_ID ].full) - message_id += strlen ("Message-ID:"); - if (nntp_store->overview_field [ CAMEL_NNTP_OVER_BYTES ].full) - bytes += strlen ("Bytes:"); - - uid = g_strdup_printf ("%s,%s", split_line[0], message_id); - camel_message_info_set_subject(new_info, g_strdup(subject)); - camel_message_info_set_from(new_info, g_strdup(from)); - camel_message_info_set_to(new_info, g_strdup(folder->name)); - camel_message_info_set_uid(new_info, uid); - - new_info->date_sent = camel_header_decode_date(date, NULL); -#if 0 - /* XXX do we need to fill in both dates? */ - new_info->headers.date_received = g_strdup(date); -#endif - new_info->size = atoi(bytes); - md5_get_digest(message_id, strlen(message_id), digest); - memcpy(new_info->message_id.id.hash, digest, sizeof(new_info->message_id.id.hash)); - - if (camel_nntp_newsrc_article_is_read (nntp_store->newsrc, - folder->name, - atoi (split_line[0]))) - new_info->flags |= CAMEL_MESSAGE_SEEN; - - camel_folder_summary_add (folder->summary, new_info); - g_strfreev (split_line); - } - g_free (line); - } - } - else { - /* XXX */ - g_warning ("weird nntp response for XOVER: %d\n", status); - } -} - -#if 0 -static GArray* -get_HEAD_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, - int first_message, int last_message, CamelException *ex) -{ - int i; - int status; - - for (i = first_message; i < last_message; i ++) { - status = camel_nntp_command (nntp_store, ex, NULL, - "HEAD %d", i); - - if (status == NNTP_HEAD_FOLLOWS) { - gboolean done = FALSE; - char *buf; - int buf_len; - int buf_alloc; - int h; - CamelStream *header_stream; - GArray *header_array; - CamelStream *nntp_istream; - CamelMessageInfo *new_info = g_new0(CamelMessageInfo, 1); - - buf_alloc = 2048; - buf_len = 0; - buf = g_malloc(buf_alloc); - done = FALSE; - - buf[0] = 0; - - nntp_istream = nntp_store->istream; - - while (!done) { - char *line; - int line_length; - - line = camel_stream_buffer_read_line ( - CAMEL_STREAM_BUFFER ( nntp_istream )); - line_length = strlen ( line ); - - if (*line == '.') { - done = TRUE; - } - else { - if (buf_len + line_length > buf_alloc) { - buf_alloc *= 2; - buf = g_realloc (buf, buf_alloc); - } - strcat(buf, line); - strcat(buf, "\n"); - buf_len += strlen(line); - g_free (line); - } - } - - /* create a stream from which to parse the headers */ - header_stream = camel_stream_mem_new_with_buffer (buf, buf_len, - CAMEL_STREAM_MEM_READ); - - header_array = get_header_array_from_stream (header_stream); - - memset (&info, 0, sizeof(info)); - - for (h = 0; h < header_array->len; h ++) { - Rfc822Header *header = &((Rfc822Header*)header_array->data)[h]; - if (!g_strcasecmp(header->name, "From")) - new_info->from = g_strdup(header->value); - else if (!g_strcasecmp(header->name, "To")) - new_info->to = g_strdup(header->value); - else if (!g_strcasecmp(header->name, "Subject")) - new_info->subject = g_strdup(header->value); - else if (!g_strcasecmp(header->name, "Message-ID")) { - new_info->uid = g_strdup_printf("%d,%s", i, header->value); - new_info->message_id = g_strdup(header->value); - } - else if (!g_strcasecmp(header->name, "Date")) { - new_info->date_sent = camel_header_decode_date (header->value); -#if 0 - new_info->date_sent = g_strdup(header->value); - new_info->date_received = g_strdup(header->value); -#endif - } - } - - camel_folder_summary_add (nntp_folder->summary, new_info); - } - else if (status == CAMEL_NNTP_FAIL) { - /* nasty things are afoot */ - g_warning ("failure doing HEAD\n"); - break; - } - } -} -#endif - -static inline int -uid_num (CamelFolderSummary *summary, int index) -{ - char *tmp; - char *brk; - CamelMessageInfo *minfo; - int ret; - - minfo = camel_folder_summary_index(summary, index); - if(minfo == NULL) - return 0; - - tmp = g_strdup(camel_message_info_uid(minfo)); - camel_message_info_free(minfo); - - if((brk = strchr(tmp, ',')) == NULL) - ret = 0; - else { - *brk = 0; - ret = atoi(tmp); - } - - g_free(tmp); - - return ret; -} - -void -camel_nntp_get_headers (CamelStore *store, - CamelNNTPFolder *nntp_folder, - CamelException *ex) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store); - CamelFolder *folder = CAMEL_FOLDER (nntp_folder); - char *ret; - int first_message, nb_message, last_message, last_summary; - int status; - int i; - - status = camel_nntp_command (nntp_store, ex, &ret, - "GROUP %s", folder->name); - sscanf (ret, "%d %d %d", &nb_message, &first_message, &last_message); - g_free (ret); - - i = camel_folder_summary_count(folder->summary); - if(i != 0) { - last_summary = uid_num(folder->summary, i-1); - - if(last_summary < first_message) - camel_folder_summary_clear(folder->summary); - else { - while(uid_num(folder->summary, 0) < first_message) - camel_folder_summary_remove_index(folder->summary, 0); - - if(last_summary >= last_message) - return; - - first_message = last_summary; - } - } - - if (status == NNTP_NO_SUCH_GROUP) { - /* XXX throw invalid group exception */ - camel_exception_setv (ex, - CAMEL_EXCEPTION_FOLDER_INVALID, - "group %s not found on server", - folder->name); - return; - } - - - if (nntp_store->extensions & CAMEL_NNTP_EXT_OVER) { - get_XOVER_headers (nntp_store, folder, first_message, last_message, ex); - } - else { - g_warning ("need to fix get_HEAD_headers\n"); -#if 0 - get_HEAD_headers (nntp_store, folder, first_message, last_message, ex); -#endif - } - -} diff --git a/camel/providers/nntp/camel-nntp-utils.h b/camel/providers/nntp/camel-nntp-utils.h deleted file mode 100644 index 48fd7490c9..0000000000 --- a/camel/providers/nntp/camel-nntp-utils.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-utils.h : Utilities for the NNTP provider */ - -/* - * - * Author : Chris Toshok - * - * Copyright (C) 1999 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_NNTP_UTILS_H -#define CAMEL_NNTP_UTILS_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -void camel_nntp_get_headers (CamelStore *store, CamelNNTPFolder *nntp_folder, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_NNTP_UTILS_H */ diff --git a/camel/providers/nntp/libcamelnntp.urls b/camel/providers/nntp/libcamelnntp.urls deleted file mode 100644 index dee2e70f14..0000000000 --- a/camel/providers/nntp/libcamelnntp.urls +++ /dev/null @@ -1,2 +0,0 @@ -news -nntp diff --git a/camel/providers/nntp/test-newsrc.c b/camel/providers/nntp/test-newsrc.c deleted file mode 100644 index c4b985e565..0000000000 --- a/camel/providers/nntp/test-newsrc.c +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include -#include "camel-nntp-newsrc.h" - -int -main(int argc, char *argv[]) -{ - CamelNNTPNewsrc *newsrc = camel_nntp_newsrc_read_for_server (argv[1]); - camel_nntp_newsrc_write_to_file (newsrc, stdout); -} diff --git a/camel/providers/pop3/.cvsignore b/camel/providers/pop3/.cvsignore deleted file mode 100644 index ddf4c8b28d..0000000000 --- a/camel/providers/pop3/.cvsignore +++ /dev/null @@ -1,10 +0,0 @@ -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/pop3/Makefile.am b/camel/providers/pop3/Makefile.am deleted file mode 100644 index 84f5477f97..0000000000 --- a/camel/providers/pop3/Makefile.am +++ /dev/null @@ -1,38 +0,0 @@ -## Process this file with automake to produce Makefile.in - -libcamelpop3includedir = $(privincludedir)/camel - -camel_provider_LTLIBRARIES = libcamelpop3.la -camel_provider_DATA = libcamelpop3.urls - -INCLUDES = \ - -I.. \ - -I$(srcdir)/.. \ - -I$(srcdir)/../../.. \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/e-util \ - $(CAMEL_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(GTK_INCLUDEDIR) \ - -DG_LOG_DOMAIN=\"camel-pop3-provider\" - -libcamelpop3_la_SOURCES = \ - camel-pop3-engine.c \ - camel-pop3-folder.c \ - camel-pop3-provider.c \ - camel-pop3-stream.c \ - camel-pop3-store.c - -libcamelpop3include_HEADERS = \ - camel-pop3-engine.h \ - camel-pop3-folder.h \ - camel-pop3-stream.h \ - camel-pop3-store.h - - -libcamelpop3_la_LDFLAGS = -avoid-version -module - -libcamelpop3_la_LIBADD = $(top_builddir)/e-util/libeutil.la - -EXTRA_DIST = libcamelpop3.urls diff --git a/camel/providers/pop3/camel-pop3-engine.c b/camel/providers/pop3/camel-pop3-engine.c deleted file mode 100644 index 2186136f95..0000000000 --- a/camel/providers/pop3/camel-pop3-engine.c +++ /dev/null @@ -1,382 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Author: - * Michael Zucchi - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include -#include - -#include - -#include "camel-pop3-engine.h" -#include "camel-pop3-stream.h" -#include -#include - -/* max 'outstanding' bytes in output stream, so we can't deadlock waiting - for the server to accept our data when pipelining */ -#define CAMEL_POP3_SEND_LIMIT (1024) - - -extern int camel_verbose_debug; -#define dd(x) (camel_verbose_debug?(x):0) - -static void get_capabilities(CamelPOP3Engine *pe, int read_greeting); - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelStream */ -#define CS_CLASS(so) CAMEL_POP3_ENGINE_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -static void -camel_pop3_engine_class_init (CamelPOP3EngineClass *camel_pop3_engine_class) -{ - parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE ); -} - -static void -camel_pop3_engine_init(CamelPOP3Engine *pe, CamelPOP3EngineClass *peclass) -{ - e_dlist_init(&pe->active); - e_dlist_init(&pe->queue); - e_dlist_init(&pe->done); - pe->state = CAMEL_POP3_ENGINE_DISCONNECT; -} - -static void -camel_pop3_engine_finalise(CamelPOP3Engine *pe) -{ - /* FIXME: Also flush/free any outstanding requests, etc */ - - if (pe->stream) - camel_object_unref((CamelObject *)pe->stream); -} - -CamelType -camel_pop3_engine_get_type (void) -{ - static CamelType camel_pop3_engine_type = CAMEL_INVALID_TYPE; - - if (camel_pop3_engine_type == CAMEL_INVALID_TYPE) { - camel_pop3_engine_type = camel_type_register(camel_object_get_type(), - "CamelPOP3Engine", - sizeof( CamelPOP3Engine ), - sizeof( CamelPOP3EngineClass ), - (CamelObjectClassInitFunc) camel_pop3_engine_class_init, - NULL, - (CamelObjectInitFunc) camel_pop3_engine_init, - (CamelObjectFinalizeFunc) camel_pop3_engine_finalise ); - } - - return camel_pop3_engine_type; -} - -/** - * camel_pop3_engine_new: - * @source: source stream - * @flags: engine flags - * - * Returns a NULL stream. A null stream is always at eof, and - * always returns success for all reads and writes. - * - * Return value: the stream - **/ -CamelPOP3Engine * -camel_pop3_engine_new(CamelStream *source, guint32 flags) -{ - CamelPOP3Engine *pe; - - pe = (CamelPOP3Engine *)camel_object_new(camel_pop3_engine_get_type ()); - - pe->stream = (CamelPOP3Stream *)camel_pop3_stream_new(source); - pe->state = CAMEL_POP3_ENGINE_AUTH; - pe->flags = flags; - - get_capabilities(pe, TRUE); - - return pe; -} - - -/** - * camel_pop3_engine_reget_capabilities: - * @engine: pop3 engine - * - * Regets server capabilities (needed after a STLS command is issued for example). - **/ -void -camel_pop3_engine_reget_capabilities (CamelPOP3Engine *engine) -{ - g_return_if_fail (CAMEL_IS_POP3_ENGINE (engine)); - - get_capabilities (engine, FALSE); -} - - -/* TODO: read implementation too? - etc? */ -struct { - char *cap; - guint32 flag; -} capa[] = { - { "APOP" , CAMEL_POP3_CAP_APOP }, - { "TOP" , CAMEL_POP3_CAP_TOP }, - { "UIDL", CAMEL_POP3_CAP_UIDL }, - { "PIPELINING", CAMEL_POP3_CAP_PIPE }, - { "STLS", CAMEL_POP3_CAP_STLS }, /* STARTTLS */ -}; - -static void -cmd_capa(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data) -{ - unsigned char *line, *tok, *next; - unsigned int len; - int ret; - int i; - CamelServiceAuthType *auth; - - dd(printf("cmd_capa\n")); - - do { - ret = camel_pop3_stream_line(stream, &line, &len); - if (ret >= 0) { - if (strncmp(line, "SASL ", 5) == 0) { - tok = line+5; - dd(printf("scanning tokens '%s'\n", tok)); - while (tok) { - next = strchr(tok, ' '); - if (next) - *next++ = 0; - auth = camel_sasl_authtype(tok); - if (auth) { - dd(printf("got auth type '%s'\n", tok)); - pe->auth = g_list_prepend(pe->auth, auth); - } else { - dd(printf("unsupported auth type '%s'\n", tok)); - } - tok = next; - } - } else { - for (i=0;icapa |= capa[i].flag; - } - } - } - } while (ret>0); -} - -static void -get_capabilities(CamelPOP3Engine *pe, int read_greeting) -{ - CamelPOP3Command *pc; - unsigned char *line, *apop, *apopend; - unsigned int len; - extern CamelServiceAuthType camel_pop3_password_authtype; - extern CamelServiceAuthType camel_pop3_apop_authtype; - - if (read_greeting) { - /* first, read the greeting */ - if (camel_pop3_stream_line(pe->stream, &line, &len) == -1 - || strncmp(line, "+OK", 3) != 0) - return; - - if ((apop = strchr(line+3, '<')) - && (apopend = strchr(apop, '>'))) { - apopend[1] = 0; - pe->apop = g_strdup(apop); - pe->capa = CAMEL_POP3_CAP_APOP; - pe->auth = g_list_append(pe->auth, &camel_pop3_apop_authtype); - } - - pe->auth = g_list_prepend(pe->auth, &camel_pop3_password_authtype); - } - - if (!(pe->flags & CAMEL_POP3_ENGINE_DISABLE_EXTENSIONS)) { - pc = camel_pop3_engine_command_new(pe, CAMEL_POP3_COMMAND_MULTI, cmd_capa, NULL, "CAPA\r\n"); - while (camel_pop3_engine_iterate(pe, pc) > 0) - ; - camel_pop3_engine_command_free(pe, pc); - - if (pe->state == CAMEL_POP3_ENGINE_TRANSACTION && !(pe->capa & CAMEL_POP3_CAP_UIDL)) { - /* check for UIDL support manually */ - pc = camel_pop3_engine_command_new (pe, CAMEL_POP3_COMMAND_SIMPLE, NULL, NULL, "UIDL 1\r\n"); - while (camel_pop3_engine_iterate (pe, pc) > 0) - ; - - if (pc->state == CAMEL_POP3_COMMAND_OK) - pe->capa |= CAMEL_POP3_CAP_UIDL; - - camel_pop3_engine_command_free (pe, pc); - } - } -} - -/* returns true if the command was sent, false if it was just queued */ -static int -engine_command_queue(CamelPOP3Engine *pe, CamelPOP3Command *pc) -{ - if (((pe->capa & CAMEL_POP3_CAP_PIPE) == 0 || (pe->sentlen + strlen(pc->data)) > CAMEL_POP3_SEND_LIMIT) - && pe->current != NULL) { - e_dlist_addtail(&pe->queue, (EDListNode *)pc); - return FALSE; - } else { - /* ??? */ - if (camel_stream_write((CamelStream *)pe->stream, pc->data, strlen(pc->data)) == -1) { - e_dlist_addtail(&pe->queue, (EDListNode *)pc); - return FALSE; - } - - pe->sentlen += strlen(pc->data); - - pc->state = CAMEL_POP3_COMMAND_DISPATCHED; - - if (pe->current == NULL) - pe->current = pc; - else - e_dlist_addtail(&pe->active, (EDListNode *)pc); - - return TRUE; - } -} - -/* returns -1 on error (sets errno), 0 when no work to do, or >0 if work remaining */ -int -camel_pop3_engine_iterate(CamelPOP3Engine *pe, CamelPOP3Command *pcwait) -{ - unsigned char *p; - unsigned int len; - CamelPOP3Command *pc, *pw, *pn; - - if (pcwait && pcwait->state >= CAMEL_POP3_COMMAND_OK) - return 0; - - pc = pe->current; - if (pc == NULL) - return 0; - - /* LOCK */ - - if (camel_pop3_stream_line(pe->stream, &pe->line, &pe->linelen) == -1) - return -1; - - p = pe->line; - switch (p[0]) { - case '+': - dd(printf("Got + response\n")); - if (pc->flags & CAMEL_POP3_COMMAND_MULTI) { - pc->state = CAMEL_POP3_COMMAND_DATA; - camel_pop3_stream_set_mode(pe->stream, CAMEL_POP3_STREAM_DATA); - - if (pc->func) - pc->func(pe, pe->stream, pc->func_data); - - /* Make sure we get all data before going back to command mode */ - while (camel_pop3_stream_getd(pe->stream, &p, &len) > 0) - ; - camel_pop3_stream_set_mode(pe->stream, CAMEL_POP3_STREAM_LINE); - } else { - pc->state = CAMEL_POP3_COMMAND_OK; - } - break; - case '-': - pc->state = CAMEL_POP3_COMMAND_ERR; - break; - default: - /* what do we do now? f'knows! */ - g_warning("Bad server response: %s\n", p); - pc->state = CAMEL_POP3_COMMAND_ERR; - break; - } - - e_dlist_addtail(&pe->done, (EDListNode *)pc); - pe->sentlen -= strlen(pc->data); - - /* Set next command */ - pe->current = (CamelPOP3Command *)e_dlist_remhead(&pe->active); - - /* check the queue for sending any we can now send also */ - pw = (CamelPOP3Command *)pe->queue.head; - pn = pw->next; - while (pn) { - if (((pe->capa & CAMEL_POP3_CAP_PIPE) == 0 || (pe->sentlen + strlen(pw->data)) > CAMEL_POP3_SEND_LIMIT) - && pe->current != NULL) - break; - - if (camel_stream_write((CamelStream *)pe->stream, pw->data, strlen(pw->data)) == -1) - return -1; - - e_dlist_remove((EDListNode *)pw); - - pe->sentlen += strlen(pw->data); - pw->state = CAMEL_POP3_COMMAND_DISPATCHED; - - if (pe->current == NULL) - pe->current = pw; - else - e_dlist_addtail(&pe->active, (EDListNode *)pw); - - pw = pn; - pn = pn->next; - } - - /* UNLOCK */ - - if (pcwait && pcwait->state >= CAMEL_POP3_COMMAND_OK) - return 0; - - return pe->current==NULL?0:1; -} - -CamelPOP3Command * -camel_pop3_engine_command_new(CamelPOP3Engine *pe, guint32 flags, CamelPOP3CommandFunc func, void *data, const char *fmt, ...) -{ - CamelPOP3Command *pc; - va_list ap; - - pc = g_malloc0(sizeof(*pc)); - pc->func = func; - pc->func_data = data; - pc->flags = flags; - - va_start(ap, fmt); - pc->data = g_strdup_vprintf(fmt, ap); - pc->state = CAMEL_POP3_COMMAND_IDLE; - - /* TODO: what about write errors? */ - engine_command_queue(pe, pc); - - return pc; -} - -void -camel_pop3_engine_command_free(CamelPOP3Engine *pe, CamelPOP3Command *pc) -{ - if (pe->current != pc) - e_dlist_remove((EDListNode *)pc); - g_free(pc->data); - g_free(pc); -} diff --git a/camel/providers/pop3/camel-pop3-engine.h b/camel/providers/pop3/camel-pop3-engine.h deleted file mode 100644 index 3114980311..0000000000 --- a/camel/providers/pop3/camel-pop3-engine.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2001 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_POP3_ENGINE_H -#define _CAMEL_POP3_ENGINE_H - -#include -#include "e-util/e-msgport.h" -#include "camel-pop3-stream.h" - -#define CAMEL_POP3_ENGINE(obj) CAMEL_CHECK_CAST (obj, camel_pop3_engine_get_type (), CamelPOP3Engine) -#define CAMEL_POP3_ENGINE_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_pop3_engine_get_type (), CamelPOP3EngineClass) -#define CAMEL_IS_POP3_ENGINE(obj) CAMEL_CHECK_TYPE (obj, camel_pop3_engine_get_type ()) - -typedef struct _CamelPOP3EngineClass CamelPOP3EngineClass; -typedef struct _CamelPOP3Engine CamelPOP3Engine; -typedef struct _CamelPOP3Command CamelPOP3Command; - -/* pop 3 connection states, actually since we're given a connected socket, we always start in auth state */ -typedef enum { - CAMEL_POP3_ENGINE_DISCONNECT = 0, - CAMEL_POP3_ENGINE_AUTH, - CAMEL_POP3_ENGINE_TRANSACTION, - CAMEL_POP3_ENGINE_UPDATE, -} camel_pop3_engine_t; - -/* state of a command */ -typedef enum { - CAMEL_POP3_COMMAND_IDLE = 0, /* command created or queued, not yet sent (e.g. non pipelined server) */ - CAMEL_POP3_COMMAND_DISPATCHED, /* command sent to server */ - - /* completion codes */ - CAMEL_POP3_COMMAND_OK, /* plain ok response */ - CAMEL_POP3_COMMAND_DATA, /* processing command response */ - CAMEL_POP3_COMMAND_ERR, /* error response */ -} camel_pop3_command_t; - -/* flags for command types */ -enum { - CAMEL_POP3_COMMAND_SIMPLE = 0, /* dont expect multiline response */ - CAMEL_POP3_COMMAND_MULTI = 1, /* expect multiline response */ -}; - -/* flags for server options */ -enum { - CAMEL_POP3_CAP_APOP = 1<<0, - CAMEL_POP3_CAP_UIDL = 1<<1, - CAMEL_POP3_CAP_SASL = 1<<2, - CAMEL_POP3_CAP_TOP = 1<<3, - CAMEL_POP3_CAP_PIPE = 1<<4, - CAMEL_POP3_CAP_STLS = 1<<5 -}; - -/* enable/disable flags for the engine itself */ -enum { - CAMEL_POP3_ENGINE_DISABLE_EXTENSIONS = 1<<0, -}; - -typedef void (*CamelPOP3CommandFunc)(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data); - -struct _CamelPOP3Command { - struct _CamelPOP3Command *next; - struct _CamelPOP3Command *prev; - - guint32 flags; - camel_pop3_command_t state; - - CamelPOP3CommandFunc func; - void *func_data; - - int data_size; - char *data; -}; - -struct _CamelPOP3Engine { - CamelObject parent; - - guint32 flags; - - camel_pop3_engine_t state; - - GList *auth; /* authtypes supported */ - - guint32 capa; /* capabilities */ - char *apop; /* apop time string */ - - unsigned char *line; /* current line buffer */ - unsigned int linelen; - - struct _CamelPOP3Stream *stream; - - unsigned int sentlen; /* data sent (so we dont overflow network buffer) */ - - EDList active; /* active commands */ - EDList queue; /* queue of waiting commands */ - EDList done; /* list of done commands, awaiting free */ - - CamelPOP3Command *current; /* currently busy (downloading) response */ -}; - -struct _CamelPOP3EngineClass { - CamelObjectClass parent_class; -}; - -CamelType camel_pop3_engine_get_type (void); - -CamelPOP3Engine *camel_pop3_engine_new (CamelStream *source, guint32 flags); - -void camel_pop3_engine_reget_capabilities (CamelPOP3Engine *engine); - -void camel_pop3_engine_command_free(CamelPOP3Engine *pe, CamelPOP3Command *pc); - -int camel_pop3_engine_iterate (CamelPOP3Engine *pe, CamelPOP3Command *pc); - -CamelPOP3Command *camel_pop3_engine_command_new (CamelPOP3Engine *pe, guint32 flags, CamelPOP3CommandFunc func, void *data, const char *fmt, ...); - -#endif /* ! _CAMEL_POP3_ENGINE_H */ diff --git a/camel/providers/pop3/camel-pop3-folder.c b/camel/providers/pop3/camel-pop3-folder.c deleted file mode 100644 index db77ad8191..0000000000 --- a/camel/providers/pop3/camel-pop3-folder.c +++ /dev/null @@ -1,558 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-pop3-folder.c : class for a pop3 folder */ - -/* - * Authors: - * Dan Winship - * Michael Zucchi - * - * Copyright (C) 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "camel-pop3-folder.h" -#include "camel-pop3-store.h" -#include "camel-exception.h" -#include "camel-stream-mem.h" -#include "camel-stream-filter.h" -#include "camel-mime-message.h" -#include "camel-operation.h" -#include "camel-data-cache.h" - -#include - -#include -#include - -#define d(x) - -#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o))) -static CamelFolderClass *parent_class; - -static void pop3_finalize (CamelObject *object); -static void pop3_refresh_info (CamelFolder *folder, CamelException *ex); -static void pop3_sync (CamelFolder *folder, gboolean expunge, CamelException *ex); -static gint pop3_get_message_count (CamelFolder *folder); -static GPtrArray *pop3_get_uids (CamelFolder *folder); -static CamelMimeMessage *pop3_get_message (CamelFolder *folder, const char *uid, CamelException *ex); -static void pop3_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, guint32 set); - -static void -camel_pop3_folder_class_init (CamelPOP3FolderClass *camel_pop3_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_pop3_folder_class); - - parent_class = CAMEL_FOLDER_CLASS(camel_folder_get_type()); - - /* virtual method overload */ - camel_folder_class->refresh_info = pop3_refresh_info; - camel_folder_class->sync = pop3_sync; - - camel_folder_class->get_message_count = pop3_get_message_count; - camel_folder_class->get_uids = pop3_get_uids; - camel_folder_class->free_uids = camel_folder_free_shallow; - - camel_folder_class->get_message = pop3_get_message; - camel_folder_class->set_message_flags = pop3_set_message_flags; -} - -CamelType -camel_pop3_folder_get_type (void) -{ - static CamelType camel_pop3_folder_type = CAMEL_INVALID_TYPE; - - if (!camel_pop3_folder_type) { - camel_pop3_folder_type = camel_type_register (CAMEL_FOLDER_TYPE, "CamelPOP3Folder", - sizeof (CamelPOP3Folder), - sizeof (CamelPOP3FolderClass), - (CamelObjectClassInitFunc) camel_pop3_folder_class_init, - NULL, - NULL, - (CamelObjectFinalizeFunc) pop3_finalize); - } - - return camel_pop3_folder_type; -} - -static void -pop3_finalize (CamelObject *object) -{ - CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (object); - CamelPOP3FolderInfo **fi = (CamelPOP3FolderInfo **)pop3_folder->uids->pdata; - CamelPOP3Store *pop3_store = (CamelPOP3Store *)((CamelFolder *)pop3_folder)->parent_store; - int i; - - if (pop3_folder->uids) { - for (i=0;iuids->len;i++,fi++) { - if (fi[0]->cmd) { - while (camel_pop3_engine_iterate(pop3_store->engine, fi[0]->cmd) > 0) - ; - camel_pop3_engine_command_free(pop3_store->engine, fi[0]->cmd); - } - - g_free(fi[0]->uid); - g_free(fi[0]); - } - - g_ptr_array_free(pop3_folder->uids, TRUE); - g_hash_table_destroy(pop3_folder->uids_uid); - } -} - -CamelFolder * -camel_pop3_folder_new (CamelStore *parent, CamelException *ex) -{ - CamelFolder *folder; - - d(printf("opening pop3 INBOX folder\n")); - - folder = CAMEL_FOLDER (camel_object_new (CAMEL_POP3_FOLDER_TYPE)); - camel_folder_construct (folder, parent, "inbox", "inbox"); - - /* mt-ok, since we dont have the folder-lock for new() */ - camel_folder_refresh_info (folder, ex);/* mt-ok */ - if (camel_exception_is_set (ex)) { - camel_object_unref (CAMEL_OBJECT (folder)); - folder = NULL; - } - - return folder; -} - -/* create a uid from md5 of 'top' output */ -static void -cmd_builduid(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data) -{ - CamelPOP3FolderInfo *fi = data; - MD5Context md5; - unsigned char digest[16]; - struct _camel_header_raw *h; - CamelMimeParser *mp; - - /* TODO; somehow work out the limit and use that for proper progress reporting - We need a pointer to the folder perhaps? */ - camel_operation_progress_count(NULL, fi->id); - - md5_init(&md5); - mp = camel_mime_parser_new(); - camel_mime_parser_init_with_stream(mp, (CamelStream *)stream); - switch (camel_mime_parser_step(mp, NULL, NULL)) { - case CAMEL_MIME_PARSER_STATE_HEADER: - case CAMEL_MIME_PARSER_STATE_MESSAGE: - case CAMEL_MIME_PARSER_STATE_MULTIPART: - h = camel_mime_parser_headers_raw(mp); - while (h) { - if (strcasecmp(h->name, "status") != 0 - && strcasecmp(h->name, "x-status") != 0) { - md5_update(&md5, h->name, strlen(h->name)); - md5_update(&md5, h->value, strlen(h->value)); - } - h = h->next; - } - default: - break; - } - camel_object_unref(mp); - md5_final(&md5, digest); - fi->uid = camel_base64_encode_simple(digest, 16); - - d(printf("building uid for id '%d' = '%s'\n", fi->id, fi->uid)); -} - -static void -cmd_list(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data) -{ - int ret; - unsigned int len, id, size; - unsigned char *line; - CamelFolder *folder = data; - CamelPOP3Store *pop3_store = CAMEL_POP3_STORE (folder->parent_store); - CamelPOP3FolderInfo *fi; - - do { - ret = camel_pop3_stream_line(stream, &line, &len); - if (ret>=0) { - if (sscanf(line, "%u %u", &id, &size) == 2) { - fi = g_malloc0(sizeof(*fi)); - fi->size = size; - fi->id = id; - fi->index = ((CamelPOP3Folder *)folder)->uids->len; - if ((pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) == 0) - fi->cmd = camel_pop3_engine_command_new(pe, CAMEL_POP3_COMMAND_MULTI, cmd_builduid, fi, "TOP %u 0\r\n", id); - g_ptr_array_add(((CamelPOP3Folder *)folder)->uids, fi); - g_hash_table_insert(((CamelPOP3Folder *)folder)->uids_id, GINT_TO_POINTER(id), fi); - } - } - } while (ret>0); -} - -static void -cmd_uidl(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data) -{ - int ret; - unsigned int len; - unsigned char *line; - char uid[1025]; - unsigned int id; - CamelPOP3FolderInfo *fi; - CamelPOP3Folder *folder = data; - - do { - ret = camel_pop3_stream_line(stream, &line, &len); - if (ret>=0) { - if (strlen(line) > 1024) - line[1024] = 0; - if (sscanf(line, "%u %s", &id, uid) == 2) { - fi = g_hash_table_lookup(folder->uids_id, GINT_TO_POINTER(id)); - if (fi) { - camel_operation_progress(NULL, (fi->index+1) * 100 / folder->uids->len); - fi->uid = g_strdup(uid); - g_hash_table_insert(folder->uids_uid, fi->uid, fi); - } else { - g_warning("ID %u (uid: %s) not in previous LIST output", id, uid); - } - } - } - } while (ret>0); -} - -static void -pop3_refresh_info (CamelFolder *folder, CamelException *ex) -{ - CamelPOP3Store *pop3_store = CAMEL_POP3_STORE (folder->parent_store); - CamelPOP3Folder *pop3_folder = (CamelPOP3Folder *) folder; - CamelPOP3Command *pcl, *pcu = NULL; - int i; - - camel_operation_start (NULL, _("Retrieving POP summary")); - - pop3_folder->uids = g_ptr_array_new (); - pop3_folder->uids_uid = g_hash_table_new(g_str_hash, g_str_equal); - /* only used during setup */ - pop3_folder->uids_id = g_hash_table_new(NULL, NULL); - - pcl = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_list, folder, "LIST\r\n"); - if (pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) { - pcu = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_uidl, folder, "UIDL\r\n"); - } - while ((i = camel_pop3_engine_iterate(pop3_store->engine, NULL)) > 0) - ; - - if (i == -1) { - if (errno == EINTR) - camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get POP summary: %s"), - g_strerror (errno)); - } - - /* TODO: check every id has a uid & commands returned OK too? */ - - camel_pop3_engine_command_free(pop3_store->engine, pcl); - - if (pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) { - camel_pop3_engine_command_free(pop3_store->engine, pcu); - } else { - for (i=0;iuids->len;i++) { - CamelPOP3FolderInfo *fi = pop3_folder->uids->pdata[i]; - if (fi->cmd) { - camel_pop3_engine_command_free(pop3_store->engine, fi->cmd); - fi->cmd = NULL; - } - if (fi->uid) - g_hash_table_insert(pop3_folder->uids_uid, fi->uid, fi); - } - } - - /* dont need this anymore */ - g_hash_table_destroy(pop3_folder->uids_id); - - camel_operation_end (NULL); - return; -} - -static void -pop3_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - CamelPOP3Folder *pop3_folder; - CamelPOP3Store *pop3_store; - int i; - CamelPOP3FolderInfo *fi; - - if (!expunge) - return; - - pop3_folder = CAMEL_POP3_FOLDER (folder); - pop3_store = CAMEL_POP3_STORE (folder->parent_store); - - camel_operation_start(NULL, _("Expunging deleted messages")); - - for (i = 0; i < pop3_folder->uids->len; i++) { - fi = pop3_folder->uids->pdata[i]; - /* busy already? wait for that to finish first */ - if (fi->cmd) { - while (camel_pop3_engine_iterate(pop3_store->engine, fi->cmd) > 0) - ; - camel_pop3_engine_command_free(pop3_store->engine, fi->cmd); - fi->cmd = NULL; - } - - if (fi->flags & CAMEL_MESSAGE_DELETED) { - fi->cmd = camel_pop3_engine_command_new(pop3_store->engine, 0, NULL, NULL, "DELE %u\r\n", fi->id); - - /* also remove from cache */ - if (pop3_store->cache && fi->uid) - camel_data_cache_remove(pop3_store->cache, "cache", fi->uid, NULL); - } - } - - for (i = 0; i < pop3_folder->uids->len; i++) { - fi = pop3_folder->uids->pdata[i]; - /* wait for delete commands to finish */ - if (fi->cmd) { - while (camel_pop3_engine_iterate(pop3_store->engine, fi->cmd) > 0) - ; - camel_pop3_engine_command_free(pop3_store->engine, fi->cmd); - fi->cmd = NULL; - } - camel_operation_progress(NULL, (i+1) * 100 / pop3_folder->uids->len); - } - - camel_operation_end(NULL); - - camel_pop3_store_expunge (pop3_store, ex); -} - -static void -cmd_tocache(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data) -{ - CamelPOP3FolderInfo *fi = data; - char buffer[2048]; - int w = 0, n; - - /* What if it fails? */ - - /* We write an '*' to the start of the stream to say its not complete yet */ - /* This should probably be part of the cache code */ - if ((n = camel_stream_write(fi->stream, "*", 1)) == -1) - goto done; - - while ((n = camel_stream_read((CamelStream *)stream, buffer, sizeof(buffer))) > 0) { - n = camel_stream_write(fi->stream, buffer, n); - if (n == -1) - break; - - w += n; - if (w > fi->size) - w = fi->size; - if (fi->size != 0) - camel_operation_progress(NULL, (w * 100) / fi->size); - } - - /* it all worked, output a '#' to say we're a-ok */ - if (n != -1) { - camel_stream_reset(fi->stream); - n = camel_stream_write(fi->stream, "#", 1); - } -done: - if (n == -1) { - fi->err = errno; - g_warning("POP3 retrieval failed: %s", strerror(errno)); - } else { - fi->err = 0; - } - - camel_object_unref((CamelObject *)fi->stream); - fi->stream = NULL; -} - -static CamelMimeMessage * -pop3_get_message (CamelFolder *folder, const char *uid, CamelException *ex) -{ - CamelMimeMessage *message = NULL; - CamelPOP3Store *pop3_store = CAMEL_POP3_STORE (folder->parent_store); - CamelPOP3Folder *pop3_folder = (CamelPOP3Folder *)folder; - CamelPOP3Command *pcr; - CamelPOP3FolderInfo *fi; - char buffer[1]; - int ok, i, last; - CamelStream *stream = NULL; - - fi = g_hash_table_lookup(pop3_folder->uids_uid, uid); - if (fi == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("No message with uid %s"), uid); - return NULL; - } - - /* Sigh, most of the crap in this function is so that the cancel button - returns the proper exception code. Sigh. */ - - camel_operation_start_transient(NULL, _("Retrieving POP message %d"), fi->id); - - /* If we have an oustanding retrieve message running, wait for that to complete - & then retrieve from cache, otherwise, start a new one, and similar */ - - if (fi->cmd != NULL) { - while ((i = camel_pop3_engine_iterate(pop3_store->engine, fi->cmd)) > 0) - ; - - if (i == -1) - fi->err = errno; - - /* getting error code? */ - ok = fi->cmd->state == CAMEL_POP3_COMMAND_DATA; - camel_pop3_engine_command_free(pop3_store->engine, fi->cmd); - fi->cmd = NULL; - - if (fi->err != 0) { - if (fi->err == EINTR) - camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message %s: %s"), - uid, g_strerror (fi->err)); - goto fail; - } - } - - /* check to see if we have safely written flag set */ - if (pop3_store->cache == NULL - || (stream = camel_data_cache_get(pop3_store->cache, "cache", fi->uid, NULL)) == NULL - || camel_stream_read(stream, buffer, 1) != 1 - || buffer[0] != '#') { - - /* Initiate retrieval, if disk backing fails, use a memory backing */ - if (pop3_store->cache == NULL - || (stream = camel_data_cache_add(pop3_store->cache, "cache", fi->uid, NULL)) == NULL) - stream = camel_stream_mem_new(); - - /* ref it, the cache storage routine unref's when done */ - camel_object_ref((CamelObject *)stream); - fi->stream = stream; - fi->err = EIO; - pcr = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_tocache, fi, "RETR %u\r\n", fi->id); - - /* Also initiate retrieval of some of the following messages, assume we'll be receiving them */ - if (pop3_store->cache != NULL) { - /* This should keep track of the last one retrieved, also how many are still - oustanding incase of random access on large folders */ - i = fi->index+1; - last = MIN(i+10, pop3_folder->uids->len); - for (;iuids->pdata[i]; - - if (pfi->uid && pfi->cmd == NULL) { - pfi->stream = camel_data_cache_add(pop3_store->cache, "cache", pfi->uid, NULL); - if (pfi->stream) { - pfi->err = EIO; - pfi->cmd = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, - cmd_tocache, pfi, "RETR %u\r\n", pfi->id); - } - } - } - } - - /* now wait for the first one to finish */ - while ((i = camel_pop3_engine_iterate(pop3_store->engine, pcr)) > 0) - ; - - if (i == -1) - fi->err = errno; - - /* getting error code? */ - ok = pcr->state == CAMEL_POP3_COMMAND_DATA; - camel_pop3_engine_command_free(pop3_store->engine, pcr); - camel_stream_reset(stream); - - /* Check to see we have safely written flag set */ - if (fi->err != 0) { - if (fi->err == EINTR) - camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message %s: %s"), - uid, g_strerror (fi->err)); - goto done; - } - - if (camel_stream_read(stream, buffer, 1) != 1 || buffer[0] != '#') { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message %s: %s"), uid, _("Unknown reason")); - goto done; - } - } - - message = camel_mime_message_new (); - if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, stream) == -1) { - if (errno == EINTR) - camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message %s: %s"), - uid, g_strerror (errno)); - camel_object_unref((CamelObject *)message); - message = NULL; - } -done: - camel_object_unref((CamelObject *)stream); -fail: - camel_operation_end(NULL); - - return message; -} - -static void -pop3_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, guint32 set) -{ - CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder); - CamelPOP3FolderInfo *fi; - - fi = g_hash_table_lookup(pop3_folder->uids_uid, uid); - if (fi) - fi->flags = (fi->flags & ~flags) | (set & flags); -} - -static gint -pop3_get_message_count (CamelFolder *folder) -{ - CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder); - - return pop3_folder->uids->len; -} - -static GPtrArray * -pop3_get_uids (CamelFolder *folder) -{ - CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder); - GPtrArray *uids = g_ptr_array_new(); - CamelPOP3FolderInfo **fi = (CamelPOP3FolderInfo **)pop3_folder->uids->pdata; - int i; - - for (i=0;iuids->len;i++,fi++) { - if (fi[0]->uid) - g_ptr_array_add(uids, fi[0]->uid); - } - - return uids; -} diff --git a/camel/providers/pop3/camel-pop3-folder.h b/camel/providers/pop3/camel-pop3-folder.h deleted file mode 100644 index 7dab07124c..0000000000 --- a/camel/providers/pop3/camel-pop3-folder.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-pop3-folder.h : Class for a POP3 folder */ - -/* - * Authors: - * Dan Winship - * Michael Zucchi - * - * Copyright (C) 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_POP3_FOLDER_H -#define CAMEL_POP3_FOLDER_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-folder.h" - -#define CAMEL_POP3_FOLDER_TYPE (camel_pop3_folder_get_type ()) -#define CAMEL_POP3_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_POP3_FOLDER_TYPE, CamelPOP3Folder)) -#define CAMEL_POP3_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_POP3_FOLDER_TYPE, CamelPOP3FolderClass)) -#define CAMEL_IS_POP3_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_POP3_FOLDER_TYPE)) - -typedef struct { - guint32 id; - guint32 size; - guint32 flags; - guint32 index; /* index of request */ - char *uid; - int err; - struct _CamelPOP3Command *cmd; - struct _CamelStream *stream; -} CamelPOP3FolderInfo; - -typedef struct { - CamelFolder parent_object; - - GPtrArray *uids; - GHashTable *uids_uid; /* messageinfo by uid */ - GHashTable *uids_id; /* messageinfo by id */ -} CamelPOP3Folder; - -typedef struct { - CamelFolderClass parent_class; - - /* Virtual methods */ - -} CamelPOP3FolderClass; - -/* public methods */ -CamelFolder *camel_pop3_folder_new (CamelStore *parent, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_pop3_folder_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_POP3_FOLDER_H */ diff --git a/camel/providers/pop3/camel-pop3-provider.c b/camel/providers/pop3/camel-pop3-provider.c deleted file mode 100644 index 1354470e69..0000000000 --- a/camel/providers/pop3/camel-pop3-provider.c +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-pop3-provider.c: pop3 provider registration code */ - -/* - * Authors : - * Dan Winship - * Michael Zucchi - * - * Copyright (C) 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "camel-pop3-store.h" -#include "camel-provider.h" -#include "camel-session.h" -#include "camel-url.h" -#include "camel-sasl.h" - -CamelProviderConfEntry pop3_conf_entries[] = { - { CAMEL_PROVIDER_CONF_SECTION_START, NULL, NULL, - N_("Message storage") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "keep_on_server", NULL, - N_("Leave messages on server"), "0" }, -#ifdef NOT_FOR_1_0 - { CAMEL_PROVIDER_CONF_CHECKSPIN, "delete_after", "UNIMPLEMENTED", - N_("Delete after %s day(s)"), "0:1:7:365" }, -#endif - { CAMEL_PROVIDER_CONF_CHECKBOX, "disable_extensions", NULL, - N_("Disable support for all POP3 extensions"), "0" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider pop3_provider = { - "pop", - - N_("POP"), - - N_("For connecting to and downloading mail from POP servers."), - - "mail", - - CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE | - CAMEL_PROVIDER_SUPPORTS_SSL, - - CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH, - - pop3_conf_entries, - - /* ... */ -}; - -CamelServiceAuthType camel_pop3_password_authtype = { - N_("Password"), - - N_("This option will connect to the POP server using a plaintext " - "password. This is the only option supported by many POP servers."), - - "", - TRUE -}; - -CamelServiceAuthType camel_pop3_apop_authtype = { - "APOP", - - N_("This option will connect to the POP server using an encrypted " - "password via the APOP protocol. This may not work for all users " - "even on servers that claim to support it."), - - "+APOP", - TRUE -}; - -void -camel_provider_module_init (CamelSession *session) -{ - CamelServiceAuthType *auth; - - pop3_provider.object_types[CAMEL_PROVIDER_STORE] = camel_pop3_store_get_type(); - pop3_provider.url_hash = camel_url_hash; - pop3_provider.url_equal = camel_url_equal; - - pop3_provider.authtypes = camel_sasl_authtype_list (FALSE); - auth = camel_sasl_authtype("LOGIN"); - if (auth) - pop3_provider.authtypes = g_list_prepend(pop3_provider.authtypes, auth); - pop3_provider.authtypes = g_list_prepend(pop3_provider.authtypes, &camel_pop3_apop_authtype); - pop3_provider.authtypes = g_list_prepend(pop3_provider.authtypes, &camel_pop3_password_authtype); - - camel_session_register_provider(session, &pop3_provider); -} diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c deleted file mode 100644 index fbdae86833..0000000000 --- a/camel/providers/pop3/camel-pop3-store.c +++ /dev/null @@ -1,657 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-pop3-store.c : class for a pop3 store */ - -/* - * Authors: - * Dan Winship - * Michael Zucchi - * - * Copyright (C) 2000-2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "camel-operation.h" - -#include "camel-pop3-store.h" -#include "camel-pop3-folder.h" -#include "camel-stream-buffer.h" -#include "camel-session.h" -#include "camel-exception.h" -#include "camel-url.h" -#include "e-util/md5-utils.h" -#include "camel-pop3-engine.h" -#include "camel-sasl.h" -#include "camel-data-cache.h" -#include "camel-tcp-stream.h" -#include "camel-tcp-stream-raw.h" -#ifdef HAVE_SSL -#include "camel-tcp-stream-ssl.h" -#endif - -/* Specified in RFC 1939 */ -#define POP3_PORT 110 - -static CamelStoreClass *parent_class = NULL; - -static void finalize (CamelObject *object); - -static gboolean pop3_connect (CamelService *service, CamelException *ex); -static gboolean pop3_disconnect (CamelService *service, gboolean clean, CamelException *ex); -static GList *query_auth_types (CamelService *service, CamelException *ex); - -static CamelFolder *get_folder (CamelStore *store, const char *folder_name, - guint32 flags, CamelException *ex); - -static void init_trash (CamelStore *store); -static CamelFolder *get_trash (CamelStore *store, CamelException *ex); - -static void -camel_pop3_store_class_init (CamelPOP3StoreClass *camel_pop3_store_class) -{ - CamelServiceClass *camel_service_class = - CAMEL_SERVICE_CLASS (camel_pop3_store_class); - CamelStoreClass *camel_store_class = - CAMEL_STORE_CLASS (camel_pop3_store_class); - - parent_class = CAMEL_STORE_CLASS (camel_type_get_global_classfuncs (camel_store_get_type ())); - - /* virtual method overload */ - camel_service_class->query_auth_types = query_auth_types; - camel_service_class->connect = pop3_connect; - camel_service_class->disconnect = pop3_disconnect; - - camel_store_class->get_folder = get_folder; - camel_store_class->init_trash = init_trash; - camel_store_class->get_trash = get_trash; -} - - - -static void -camel_pop3_store_init (gpointer object, gpointer klass) -{ - ; -} - -CamelType -camel_pop3_store_get_type (void) -{ - static CamelType camel_pop3_store_type = CAMEL_INVALID_TYPE; - - if (!camel_pop3_store_type) { - camel_pop3_store_type = camel_type_register (CAMEL_STORE_TYPE, - "CamelPOP3Store", - sizeof (CamelPOP3Store), - sizeof (CamelPOP3StoreClass), - (CamelObjectClassInitFunc) camel_pop3_store_class_init, - NULL, - (CamelObjectInitFunc) camel_pop3_store_init, - finalize); - } - - return camel_pop3_store_type; -} - -static void -finalize (CamelObject *object) -{ - CamelPOP3Store *pop3_store = CAMEL_POP3_STORE (object); - - /* force disconnect so we dont have it run later, after we've cleaned up some stuff */ - /* SIGH */ - - camel_service_disconnect((CamelService *)pop3_store, TRUE, NULL); - - if (pop3_store->engine) - camel_object_unref((CamelObject *)pop3_store->engine); - if (pop3_store->cache) - camel_object_unref((CamelObject *)pop3_store->cache); -} - -enum { - USE_SSL_NEVER, - USE_SSL_ALWAYS, - USE_SSL_WHEN_POSSIBLE -}; - -#define SSL_PORT_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3) -#define STARTTLS_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_TLS) - -static gboolean -connect_to_server (CamelService *service, int ssl_mode, int try_starttls, CamelException *ex) -{ - CamelPOP3Store *store = CAMEL_POP3_STORE (service); - CamelStream *tcp_stream; - CamelPOP3Command *pc; - struct hostent *h; - guint32 flags = 0; - int clean_quit; - int ret, port; - - h = camel_service_gethost (service, ex); - if (!h) - return FALSE; - - port = service->url->port ? service->url->port : 110; - - if (ssl_mode != USE_SSL_NEVER) { -#ifdef HAVE_SSL - if (try_starttls) { - tcp_stream = camel_tcp_stream_ssl_new_raw (service->session, service->url->host, STARTTLS_FLAGS); - } else { - port = service->url->port ? service->url->port : 995; - tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, SSL_PORT_FLAGS); - } -#else - if (!try_starttls) - port = service->url->port ? service->url->port : 995; - - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s (port %d): %s"), - service->url->host, port, - _("SSL unavailable")); - - camel_free_host (h); - - return FALSE; -#endif /* HAVE_SSL */ - } else { - tcp_stream = camel_tcp_stream_raw_new (); - } - - ret = camel_tcp_stream_connect (CAMEL_TCP_STREAM (tcp_stream), h, port); - camel_free_host (h); - if (ret == -1) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Connection cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to POP server %s (port %d): %s"), - service->url->host, port, g_strerror (errno)); - - camel_object_unref (CAMEL_OBJECT (tcp_stream)); - - return FALSE; - } - - /* parent class connect initialization */ - if (CAMEL_SERVICE_CLASS (parent_class)->connect (service, ex) == FALSE) { - camel_object_unref (CAMEL_OBJECT (tcp_stream)); - return FALSE; - } - - if (camel_url_get_param (service->url, "disable_extensions")) - flags |= CAMEL_POP3_ENGINE_DISABLE_EXTENSIONS; - - store->engine = camel_pop3_engine_new (tcp_stream, flags); - -#ifdef HAVE_SSL - if (store->engine) { - if (ssl_mode == USE_SSL_WHEN_POSSIBLE) { - if (store->engine->capa & CAMEL_POP3_CAP_STLS) - goto starttls; - } else if (ssl_mode == USE_SSL_ALWAYS) { - if (try_starttls) { - if (store->engine->capa & CAMEL_POP3_CAP_STLS) { - /* attempt to toggle STARTTLS mode */ - goto starttls; - } else { - /* server doesn't support STARTTLS, abort */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to POP server %s in secure mode: %s"), - service->url->host, _("SSL/TLS extension not supported.")); - /* we have the possibility of quitting cleanly here */ - clean_quit = TRUE; - goto stls_exception; - } - } - } - } -#endif /* HAVE_SSL */ - - camel_object_unref (CAMEL_OBJECT (tcp_stream)); - - return store->engine != NULL; - -#ifdef HAVE_SSL - starttls: - /* as soon as we send a STLS command, all hope is lost of a clean QUIT if problems arise */ - clean_quit = FALSE; - - pc = camel_pop3_engine_command_new (store->engine, 0, NULL, NULL, "STLS\r\n"); - while (camel_pop3_engine_iterate (store->engine, NULL) > 0) - ; - - ret = pc->state == CAMEL_POP3_COMMAND_OK; - camel_pop3_engine_command_free (store->engine, pc); - - if (ret == FALSE) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to POP server %s in secure mode: %s"), - service->url->host, store->engine->line); - goto stls_exception; - } - - /* Okay, now toggle SSL/TLS mode */ - ret = camel_tcp_stream_ssl_enable_ssl (CAMEL_TCP_STREAM_SSL (tcp_stream)); - - camel_object_unref (CAMEL_OBJECT (tcp_stream)); - - if (ret == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to POP server %s in secure mode: %s"), - service->url->host, _("SSL negotiations failed")); - goto stls_exception; - } - - /* rfc2595, section 4 states that after a successful STLS - command, the client MUST discard prior CAPA responses */ - camel_pop3_engine_reget_capabilities (store->engine); - - return TRUE; - - stls_exception: - if (clean_quit) { - /* try to disconnect cleanly */ - pc = camel_pop3_engine_command_new (store->engine, 0, NULL, NULL, "QUIT\r\n"); - while (camel_pop3_engine_iterate (store->engine, NULL) > 0) - ; - camel_pop3_engine_command_free (store->engine, pc); - } - - camel_object_unref (CAMEL_OBJECT (store->engine)); - camel_object_unref (CAMEL_OBJECT (tcp_stream)); - store->engine = NULL; - - return FALSE; -#endif /* HAVE_SSL */ -} - -static struct { - char *value; - int mode; -} ssl_options[] = { - { "", USE_SSL_ALWAYS }, - { "always", USE_SSL_ALWAYS }, - { "when-possible", USE_SSL_WHEN_POSSIBLE }, - { "never", USE_SSL_NEVER }, - { NULL, USE_SSL_NEVER }, -}; - -static gboolean -connect_to_server_wrapper (CamelService *service, CamelException *ex) -{ -#ifdef HAVE_SSL - const char *use_ssl; - int i, ssl_mode; - - use_ssl = camel_url_get_param (service->url, "use_ssl"); - if (use_ssl) { - for (i = 0; ssl_options[i].value; i++) - if (!strcmp (ssl_options[i].value, use_ssl)) - break; - ssl_mode = ssl_options[i].mode; - } else - ssl_mode = USE_SSL_NEVER; - - if (ssl_mode == USE_SSL_ALWAYS) { - /* First try the ssl port */ - if (!connect_to_server (service, ssl_mode, FALSE, ex)) { - if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE) { - /* The ssl port seems to be unavailable, lets try STARTTLS */ - camel_exception_clear (ex); - return connect_to_server (service, ssl_mode, TRUE, ex); - } else { - return FALSE; - } - } - - return TRUE; - } else if (ssl_mode == USE_SSL_WHEN_POSSIBLE) { - /* If the server supports STARTTLS, use it */ - return connect_to_server (service, ssl_mode, TRUE, ex); - } else { - /* User doesn't care about SSL */ - return connect_to_server (service, ssl_mode, FALSE, ex); - } -#else - return connect_to_server (service, USE_SSL_NEVER, FALSE, ex); -#endif -} - -extern CamelServiceAuthType camel_pop3_password_authtype; -extern CamelServiceAuthType camel_pop3_apop_authtype; - -static GList * -query_auth_types (CamelService *service, CamelException *ex) -{ - CamelPOP3Store *store = CAMEL_POP3_STORE (service); - GList *types = NULL; - - types = CAMEL_SERVICE_CLASS (parent_class)->query_auth_types (service, ex); - if (camel_exception_is_set (ex)) - return NULL; - - if (connect_to_server_wrapper (service, NULL)) { - types = g_list_concat(types, g_list_copy(store->engine->auth)); - pop3_disconnect (service, TRUE, NULL); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to POP server %s"), - service->url->host); - } - - return types; -} - -/** - * camel_pop3_store_expunge: - * @store: the store - * @ex: a CamelException - * - * Expunge messages from the store. This will result in the connection - * being closed, which may cause later commands to fail if they can't - * reconnect. - **/ -void -camel_pop3_store_expunge (CamelPOP3Store *store, CamelException *ex) -{ - CamelPOP3Command *pc; - - pc = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "QUIT\r\n"); - while (camel_pop3_engine_iterate(store->engine, NULL) > 0) - ; - camel_pop3_engine_command_free(store->engine, pc); - - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, ex); -} - -static int -try_sasl(CamelPOP3Store *store, const char *mech, CamelException *ex) -{ - CamelPOP3Stream *stream = store->engine->stream; - unsigned char *line, *resp; - CamelSasl *sasl; - unsigned int len; - int ret; - - sasl = camel_sasl_new("pop3", mech, (CamelService *)store); - if (sasl == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID, - _("Unable to connect to POP server %s: " - "No support for requested authentication mechanism."), - CAMEL_SERVICE (store)->url->host); - return -1; - } - - if (camel_stream_printf((CamelStream *)stream, "AUTH %s\r\n", mech) == -1) - goto ioerror; - - while (1) { - if (camel_pop3_stream_line(stream, &line, &len) == -1) - goto ioerror; - if (strncmp(line, "+OK", 3) == 0) - break; - if (strncmp(line, "-ERR", 4) == 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("SASL `%s' Login failed for POP server %s: %s"), - mech, CAMEL_SERVICE (store)->url->host, line); - goto done; - } - /* If we dont get continuation, or the sasl object's run out of work, or we dont get a challenge, - its a protocol error, so fail, and try reset the server */ - if (strncmp(line, "+ ", 2) != 0 - || camel_sasl_authenticated(sasl) - || (resp = camel_sasl_challenge_base64(sasl, line+2, ex)) == NULL) { - camel_stream_printf((CamelStream *)stream, "*\r\n"); - camel_pop3_stream_line(stream, &line, &len); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Cannot login to POP server %s: SASL Protocol error"), - CAMEL_SERVICE (store)->url->host); - goto done; - } - - ret = camel_stream_printf((CamelStream *)stream, "%s\r\n", resp); - g_free(resp); - if (ret == -1) - goto ioerror; - - } - camel_object_unref((CamelObject *)sasl); - return 0; - - ioerror: - if (errno == EINTR) { - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to authenticate on POP server %s: %s"), - CAMEL_SERVICE (store)->url->host, g_strerror (errno)); - } - done: - camel_object_unref((CamelObject *)sasl); - return -1; -} - -static int -pop3_try_authenticate (CamelService *service, gboolean reprompt, const char *errmsg, CamelException *ex) -{ - CamelPOP3Store *store = (CamelPOP3Store *)service; - CamelPOP3Command *pcu = NULL, *pcp = NULL; - int status; - - /* override, testing only */ - /*printf("Forcing authmech to 'login'\n"); - service->url->authmech = g_strdup("LOGIN");*/ - - if (!service->url->passwd) { - char *prompt; - - prompt = g_strdup_printf (_("%sPlease enter the POP password for %s@%s"), - errmsg ? errmsg : "", - service->url->user, - service->url->host); - service->url->passwd = camel_session_get_password (camel_service_get_session (service), - prompt, reprompt, TRUE, service, "password", ex); - g_free (prompt); - if (!service->url->passwd) - return FALSE; - } - - if (!service->url->authmech) { - /* pop engine will take care of pipelining ability */ - pcu = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "USER %s\r\n", service->url->user); - pcp = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "PASS %s\r\n", service->url->passwd); - } else if (strcmp(service->url->authmech, "+APOP") == 0 && store->engine->apop) { - char *secret, md5asc[33], *d; - unsigned char md5sum[16], *s; - - secret = g_alloca(strlen(store->engine->apop)+strlen(service->url->passwd)+1); - sprintf(secret, "%s%s", store->engine->apop, service->url->passwd); - md5_get_digest(secret, strlen (secret), md5sum); - - for (s = md5sum, d = md5asc; d < md5asc + 32; s++, d += 2) - sprintf (d, "%.2x", *s); - - pcp = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "APOP %s %s\r\n", - service->url->user, md5asc); - } else { - CamelServiceAuthType *auth; - GList *l; - - l = store->engine->auth; - while (l) { - auth = l->data; - if (strcmp(auth->authproto, service->url->authmech) == 0) - return try_sasl(store, service->url->authmech, ex) == -1; - l = l->next; - } - - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID, - _("Unable to connect to POP server %s: " - "No support for requested authentication mechanism."), - CAMEL_SERVICE (store)->url->host); - return FALSE; - } - - while ((status = camel_pop3_engine_iterate(store->engine, pcp)) > 0) - ; - - if (status == -1) { - if (errno == EINTR) { - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unable to connect to POP server %s.\n" - "Error sending password: %s"), - CAMEL_SERVICE (store)->url->host, - errno ? g_strerror (errno) : _("Unknown error")); - } - } else if (pcp->state != CAMEL_POP3_COMMAND_OK) - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Unable to connect to POP server %s.\n" - "Error sending password: %s"), - CAMEL_SERVICE (store)->url->host, - store->engine->line ? (char *)store->engine->line : _("Unknown error")); - - camel_pop3_engine_command_free(store->engine, pcp); - - if (pcu) - camel_pop3_engine_command_free(store->engine, pcu); - - return status; -} - -static gboolean -pop3_connect (CamelService *service, CamelException *ex) -{ - CamelPOP3Store *store = (CamelPOP3Store *)service; - gboolean reprompt = FALSE; - CamelSession *session; - char *errbuf = NULL; - int status; - - session = camel_service_get_session (service); - - if (store->cache == NULL) { - char *root; - - root = camel_session_get_storage_path (session, service, ex); - if (root) { - store->cache = camel_data_cache_new(root, 0, ex); - g_free(root); - if (store->cache) { - /* Default cache expiry - 1 week or not visited in a day */ - camel_data_cache_set_expire_age(store->cache, 60*60*24*7); - camel_data_cache_set_expire_access(store->cache, 60*60*24); - } - } - } - - if (!connect_to_server_wrapper (service, ex)) - return FALSE; - - do { - camel_exception_clear (ex); - status = pop3_try_authenticate (service, reprompt, errbuf, ex); - g_free (errbuf); - errbuf = NULL; - - /* we only re-prompt if we failed to authenticate, any other error and we just abort */ - if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE) { - errbuf = g_strdup_printf ("%s\n\n", camel_exception_get_description (ex)); - g_free (service->url->passwd); - service->url->passwd = NULL; - reprompt = TRUE; - } - } while (status != -1 && ex->id == CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE); - - g_free (errbuf); - - if (status == -1 || camel_exception_is_set(ex)) { - camel_service_disconnect(service, TRUE, ex); - return FALSE; - } - - /* Now that we are in the TRANSACTION state, try regetting the capabilities */ - store->engine->state = CAMEL_POP3_ENGINE_TRANSACTION; - camel_pop3_engine_reget_capabilities (store->engine); - - return TRUE; -} - -static gboolean -pop3_disconnect (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelPOP3Store *store = CAMEL_POP3_STORE (service); - - if (clean) { - CamelPOP3Command *pc; - - pc = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "QUIT\r\n"); - while (camel_pop3_engine_iterate(store->engine, NULL) > 0) - ; - camel_pop3_engine_command_free(store->engine, pc); - } - - if (!CAMEL_SERVICE_CLASS (parent_class)->disconnect (service, clean, ex)) - return FALSE; - - camel_object_unref((CamelObject *)store->engine); - store->engine = NULL; - - return TRUE; -} - -static CamelFolder * -get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) -{ - if (strcasecmp (folder_name, "inbox") != 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID, - _("No such folder `%s'."), folder_name); - return NULL; - } - return camel_pop3_folder_new (store, ex); -} - -static void -init_trash (CamelStore *store) -{ - /* no-op */ - ; -} - -static CamelFolder * -get_trash (CamelStore *store, CamelException *ex) -{ - /* no-op */ - return NULL; -} diff --git a/camel/providers/pop3/camel-pop3-store.h b/camel/providers/pop3/camel-pop3-store.h deleted file mode 100644 index 3b9b1f7ae1..0000000000 --- a/camel/providers/pop3/camel-pop3-store.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-pop3-store.h : class for an pop3 store */ - -/* - * Authors: - * Dan Winship - * Michael Zucchi - * - * Copyright (C) 2000-2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_POP3_STORE_H -#define CAMEL_POP3_STORE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include -#include -#include "camel-pop3-engine.h" - -#define CAMEL_POP3_STORE_TYPE (camel_pop3_store_get_type ()) -#define CAMEL_POP3_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_POP3_STORE_TYPE, CamelPOP3Store)) -#define CAMEL_POP3_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_POP3_STORE_TYPE, CamelPOP3StoreClass)) -#define CAMEL_IS_POP3_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_POP3_STORE_TYPE)) - - -typedef struct { - CamelStore parent_object; - - CamelPOP3Engine *engine; /* pop processing engine */ - - struct _CamelDataCache *cache; -} CamelPOP3Store; - - - -typedef struct { - CamelStoreClass parent_class; - -} CamelPOP3StoreClass; - - -/* public methods */ -void camel_pop3_store_expunge (CamelPOP3Store *store, CamelException *ex); - -/* support functions */ -enum { CAMEL_POP3_OK, CAMEL_POP3_ERR, CAMEL_POP3_FAIL }; -int camel_pop3_command (CamelPOP3Store *store, char **ret, CamelException *ex, char *fmt, ...); -char *camel_pop3_command_get_additional_data (CamelPOP3Store *store, int total, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_pop3_store_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_POP3_STORE_H */ - - diff --git a/camel/providers/pop3/camel-pop3-stream.c b/camel/providers/pop3/camel-pop3-stream.c deleted file mode 100644 index cb27bece26..0000000000 --- a/camel/providers/pop3/camel-pop3-stream.c +++ /dev/null @@ -1,471 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Author: - * Michael Zucchi - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -/* This is *identical* to the camel-nntp-stream, so should probably - work out a way to merge them */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include -#include - -#include - -#include "camel-pop3-stream.h" - -extern int camel_verbose_debug; -#define dd(x) (camel_verbose_debug?(x):0) - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelStream */ -#define CS_CLASS(so) CAMEL_POP3_STREAM_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -#define CAMEL_POP3_STREAM_SIZE (4096) -#define CAMEL_POP3_STREAM_LINE (1024) /* maximum line size */ - -static int -stream_fill(CamelPOP3Stream *is) -{ - int left = 0; - - if (is->source) { - left = is->end - is->ptr; - memcpy(is->buf, is->ptr, left); - is->end = is->buf + left; - is->ptr = is->buf; - left = camel_stream_read(is->source, is->end, CAMEL_POP3_STREAM_SIZE - (is->end - is->buf)); - if (left > 0) { - is->end += left; - is->end[0] = '\n'; - return is->end - is->ptr; - } else { - dd(printf("POP3_STREAM_FILL(ERROR): '%s'\n", strerror (errno))); - return -1; - } - } - - return 0; -} - -static ssize_t -stream_read(CamelStream *stream, char *buffer, size_t n) -{ - CamelPOP3Stream *is = (CamelPOP3Stream *)stream; - char *o, *oe; - unsigned char *p, *e, c; - int state; - - if (is->mode != CAMEL_POP3_STREAM_DATA || n == 0) - return 0; - - o = buffer; - oe = buffer + n; - state = is->state; - - /* Need to copy/strip '.'s and whatnot */ - p = is->ptr; - e = is->end; - - switch(state) { - state_0: - case 0: /* start of line, always read at least 3 chars */ - while (e - p < 3) { - is->ptr = p; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } - if (p[0] == '.') { - if (p[1] == '\r' && p[2] == '\n') { - is->ptr = p+3; - is->mode = CAMEL_POP3_STREAM_EOD; - is->state = 0; - dd(printf("POP3_STREAM_READ(%d):\n%.*s\n", o-buffer, o-buffer, buffer)); - return o-buffer; - } - p++; - } - state = 1; - /* FALLS THROUGH */ - case 1: /* looking for next sol */ - while (o < oe) { - c = *p++; - if (c == '\n') { - /* end of input sentinal check */ - if (p > e) { - is->ptr = e; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } else { - *o++ = '\n'; - state = 0; - goto state_0; - } - } else if (c != '\r') { - *o++ = c; - } - } - break; - } - - is->ptr = p; - is->state = state; - - dd(printf("POP3_STREAM_READ(%d):\n%.*s\n", o-buffer, o-buffer, buffer)); - - return o-buffer; -} - -static ssize_t -stream_write(CamelStream *stream, const char *buffer, size_t n) -{ - CamelPOP3Stream *is = (CamelPOP3Stream *)stream; - - if (strncmp (buffer, "PASS ", 5) != 0) - dd(printf("POP3_STREAM_WRITE(%d):\n%.*s\n", n, (int)n, buffer)); - else - dd(printf("POP3_STREAM_WRITE(%d):\nPASS xxxxxxxx\n", n)); - - return camel_stream_write(is->source, buffer, n); -} - -static int -stream_close(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static int -stream_flush(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static gboolean -stream_eos(CamelStream *stream) -{ - CamelPOP3Stream *is = (CamelPOP3Stream *)stream; - - return is->mode != CAMEL_POP3_STREAM_DATA; -} - -static int -stream_reset(CamelStream *stream) -{ - /* nop? reset literal mode? */ - return 0; -} - -static void -camel_pop3_stream_class_init (CamelStreamClass *camel_pop3_stream_class) -{ - CamelStreamClass *camel_stream_class = (CamelStreamClass *)camel_pop3_stream_class; - - parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE ); - - /* virtual method definition */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->close = stream_close; - camel_stream_class->flush = stream_flush; - camel_stream_class->eos = stream_eos; - camel_stream_class->reset = stream_reset; -} - -static void -camel_pop3_stream_init(CamelPOP3Stream *is, CamelPOP3StreamClass *isclass) -{ - /* +1 is room for appending a 0 if we need to for a line */ - is->ptr = is->end = is->buf = g_malloc(CAMEL_POP3_STREAM_SIZE+1); - is->lineptr = is->linebuf = g_malloc(CAMEL_POP3_STREAM_LINE+1); - is->lineend = is->linebuf + CAMEL_POP3_STREAM_LINE; - - /* init sentinal */ - is->ptr[0] = '\n'; - - is->state = 0; - is->mode = CAMEL_POP3_STREAM_LINE; -} - -static void -camel_pop3_stream_finalise(CamelPOP3Stream *is) -{ - g_free(is->buf); - g_free(is->linebuf); - if (is->source) - camel_object_unref((CamelObject *)is->source); -} - -CamelType -camel_pop3_stream_get_type (void) -{ - static CamelType camel_pop3_stream_type = CAMEL_INVALID_TYPE; - - if (camel_pop3_stream_type == CAMEL_INVALID_TYPE) { - camel_pop3_stream_type = camel_type_register( camel_stream_get_type(), - "CamelPOP3Stream", - sizeof( CamelPOP3Stream ), - sizeof( CamelPOP3StreamClass ), - (CamelObjectClassInitFunc) camel_pop3_stream_class_init, - NULL, - (CamelObjectInitFunc) camel_pop3_stream_init, - (CamelObjectFinalizeFunc) camel_pop3_stream_finalise ); - } - - return camel_pop3_stream_type; -} - -/** - * camel_pop3_stream_new: - * - * Returns a NULL stream. A null stream is always at eof, and - * always returns success for all reads and writes. - * - * Return value: the stream - **/ -CamelStream * -camel_pop3_stream_new(CamelStream *source) -{ - CamelPOP3Stream *is; - - is = (CamelPOP3Stream *)camel_object_new(camel_pop3_stream_get_type ()); - camel_object_ref((CamelObject *)source); - is->source = source; - - return (CamelStream *)is; -} - -/* Get one line from the pop3 stream */ -int -camel_pop3_stream_line(CamelPOP3Stream *is, unsigned char **data, unsigned int *len) -{ - register unsigned char c, *p, *o, *oe; - int newlen, oldlen; - unsigned char *e; - - if (is->mode == CAMEL_POP3_STREAM_EOD) { - *data = is->linebuf; - *len = 0; - return 0; - } - - o = is->linebuf; - oe = is->lineend - 1; - p = is->ptr; - e = is->end; - - /* Data mode, convert leading '..' to '.', and stop when we reach a solitary '.' */ - if (is->mode == CAMEL_POP3_STREAM_DATA) { - /* need at least 3 chars in buffer */ - while (e-p < 3) { - is->ptr = p; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } - - /* check for isolated '.\r\n' or begging of line '.' */ - if (p[0] == '.') { - if (p[1] == '\r' && p[2] == '\n') { - is->ptr = p+3; - is->mode = CAMEL_POP3_STREAM_EOD; - *data = is->linebuf; - *len = 0; - is->linebuf[0] = 0; - - dd(printf("POP3_STREAM_LINE(END)\n")); - - return 0; - } - p++; - } - } - - while (1) { - while (o < oe) { - c = *p++; - if (c == '\n') { - /* sentinal? */ - if (p> e) { - is->ptr = e; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } else { - is->ptr = p; - *data = is->linebuf; - *len = o - is->linebuf; - *o = 0; - - dd(printf("POP3_STREAM_LINE(%d): '%s'\n", *len, *data)); - - return 1; - } - } else if (c != '\r') { - *o++ = c; - } - } - - /* limit this for bad server data? */ - oldlen = o - is->linebuf; - newlen = (is->lineend - is->linebuf) * 3 / 2; - is->lineptr = is->linebuf = g_realloc(is->linebuf, newlen); - is->lineend = is->linebuf + newlen; - oe = is->lineend - 1; - o = is->linebuf + oldlen; - } - - return -1; -} - -/* returns -1 on error, 0 if last lot of data, >0 if more remaining */ -int camel_pop3_stream_gets(CamelPOP3Stream *is, unsigned char **start, unsigned int *len) -{ - int max; - unsigned char *end; - - *len = 0; - - max = is->end - is->ptr; - if (max == 0) { - max = stream_fill(is); - if (max <= 0) - return max; - } - - *start = is->ptr; - end = memchr(is->ptr, '\n', max); - if (end) - max = (end - is->ptr) + 1; - *start = is->ptr; - *len = max; - is->ptr += max; - - dd(printf("POP3_STREAM_GETS(%s,%d): '%.*s'\n", end==NULL?"more":"last", *len, (int)*len, *start)); - - return end == NULL?1:0; -} - -void camel_pop3_stream_set_mode(CamelPOP3Stream *is, camel_pop3_stream_mode_t mode) -{ - is->mode = mode; -} - -/* returns -1 on erorr, 0 if last data, >0 if more data left */ -int camel_pop3_stream_getd(CamelPOP3Stream *is, unsigned char **start, unsigned int *len) -{ - unsigned char *p, *e, *s; - int state; - - *len = 0; - - if (is->mode == CAMEL_POP3_STREAM_EOD) - return 0; - - if (is->mode == CAMEL_POP3_STREAM_LINE) { - g_warning("pop3_stream reading data in line mode\n"); - return 0; - } - - state = is->state; - p = is->ptr; - e = is->end; - - while (e - p < 3) { - is->ptr = p; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } - - s = p; - - do { - switch(state) { - case 0: - /* check leading '.', ... */ - if (p[0] == '.') { - if (p[1] == '\r' && p[2] == '\n') { - is->ptr = p+3; - *len = p-s; - *start = s; - is->mode = CAMEL_POP3_STREAM_EOD; - is->state = 0; - - dd(printf("POP3_STREAM_GETD(%s,%d): '%.*s'\n", "last", *len, (int)*len, *start)); - - return 0; - } - - /* If at start, just skip '.', else return data upto '.' but skip it */ - if (p == s) { - s++; - p++; - } else { - is->ptr = p+1; - *len = p-s; - *start = s; - is->state = 1; - - dd(printf("POP3_STREAM_GETD(%s,%d): '%.*s'\n", "more", *len, (int)*len, *start)); - - return 1; - } - } - state = 1; - case 1: - /* Scan for sentinal */ - while ((*p++)!='\n') - ; - - if (p > e) { - p = e; - } else { - state = 0; - } - break; - } - } while ((e-p) >= 3); - - is->state = state; - is->ptr = p; - *len = p-s; - *start = s; - - dd(printf("POP3_STREAM_GETD(%s,%d): '%.*s'\n", "more", *len, (int)*len, *start)); - - return 1; -} diff --git a/camel/providers/pop3/camel-pop3-stream.h b/camel/providers/pop3/camel-pop3-stream.h deleted file mode 100644 index 2a4ebc01f2..0000000000 --- a/camel/providers/pop3/camel-pop3-stream.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2002 Ximian Inc. - * - * Authors: Michael Zucchi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* This is *identical* to the camel-nntp-stream, so should probably - work out a way to merge them */ - -#ifndef _CAMEL_POP3_STREAM_H -#define _CAMEL_POP3_STREAM_H - -#include - -#define CAMEL_POP3_STREAM(obj) CAMEL_CHECK_CAST (obj, camel_pop3_stream_get_type (), CamelPOP3Stream) -#define CAMEL_POP3_STREAM_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_pop3_stream_get_type (), CamelPOP3StreamClass) -#define CAMEL_IS_POP3_STREAM(obj) CAMEL_CHECK_TYPE (obj, camel_pop3_stream_get_type ()) - -typedef struct _CamelPOP3StreamClass CamelPOP3StreamClass; -typedef struct _CamelPOP3Stream CamelPOP3Stream; - -typedef enum { - CAMEL_POP3_STREAM_LINE, - CAMEL_POP3_STREAM_DATA, - CAMEL_POP3_STREAM_EOD, /* end of data, acts as if end of stream */ -} camel_pop3_stream_mode_t; - -struct _CamelPOP3Stream { - CamelStream parent; - - CamelStream *source; - - camel_pop3_stream_mode_t mode; - int state; - - unsigned char *buf, *ptr, *end; - unsigned char *linebuf, *lineptr, *lineend; -}; - -struct _CamelPOP3StreamClass { - CamelStreamClass parent_class; -}; - -CamelType camel_pop3_stream_get_type (void); - -CamelStream *camel_pop3_stream_new (CamelStream *source); - - -void camel_pop3_stream_set_mode (CamelPOP3Stream *is, camel_pop3_stream_mode_t mode); - -int camel_pop3_stream_line (CamelPOP3Stream *is, unsigned char **data, unsigned int *len); -int camel_pop3_stream_gets (CamelPOP3Stream *is, unsigned char **start, unsigned int *len); -int camel_pop3_stream_getd (CamelPOP3Stream *is, unsigned char **start, unsigned int *len); - -#endif /* ! _CAMEL_POP3_STREAM_H */ diff --git a/camel/providers/pop3/libcamelpop3.urls b/camel/providers/pop3/libcamelpop3.urls deleted file mode 100644 index 7fffa4d861..0000000000 --- a/camel/providers/pop3/libcamelpop3.urls +++ /dev/null @@ -1 +0,0 @@ -pop diff --git a/camel/providers/sendmail/.cvsignore b/camel/providers/sendmail/.cvsignore deleted file mode 100644 index 097fdedafb..0000000000 --- a/camel/providers/sendmail/.cvsignore +++ /dev/null @@ -1,11 +0,0 @@ -Makefile -Makefile.in -.deps -.libs -*.lo -*.la -*.o -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/sendmail/Makefile.am b/camel/providers/sendmail/Makefile.am deleted file mode 100644 index 8c75af2de8..0000000000 --- a/camel/providers/sendmail/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -## Process this file with automake to produce Makefile.in - -libcamelsendmailincludedir = $(privincludedir)/camel - -camel_provider_LTLIBRARIES = libcamelsendmail.la -camel_provider_DATA = libcamelsendmail.urls - -INCLUDES = \ - -I.. \ - -I$(srcdir)/.. \ - -I$(srcdir)/../../.. \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/camel \ - $(CAMEL_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(GTK_INCLUDEDIR) \ - -DG_LOG_DOMAIN=\"camel-sendmail-provider\" - -libcamelsendmail_la_SOURCES = \ - camel-sendmail-provider.c \ - camel-sendmail-transport.c - -libcamelsendmailinclude_HEADERS = \ - camel-sendmail-transport.h - -libcamelsendmail_la_LDFLAGS = -avoid-version -module - -EXTRA_DIST = libcamelsendmail.urls diff --git a/camel/providers/sendmail/camel-sendmail-provider.c b/camel/providers/sendmail/camel-sendmail-provider.c deleted file mode 100644 index 9615dff1b4..0000000000 --- a/camel/providers/sendmail/camel-sendmail-provider.c +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-sendmail-provider.c: sendmail provider registration code */ - -/* - * Authors : - * Dan Winship - * - * Copyright (C) 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "camel-provider.h" -#include "camel-sendmail-transport.h" -#include "camel-session.h" -#include "camel-url.h" - -static CamelProvider sendmail_provider = { - "sendmail", - N_("Sendmail"), - - N_("For delivering mail by passing it to the \"sendmail\" program " - "on the local system."), - - "mail", - - 0, /* flags */ - - 0, /* url_flags */ - - /* ... */ -}; - -void -camel_provider_module_init (CamelSession *session) -{ - sendmail_provider.object_types[CAMEL_PROVIDER_TRANSPORT] = - camel_sendmail_transport_get_type(); - - sendmail_provider.url_hash = camel_url_hash; - sendmail_provider.url_equal = camel_url_equal; - - camel_session_register_provider (session, &sendmail_provider); -} - - - diff --git a/camel/providers/sendmail/camel-sendmail-transport.c b/camel/providers/sendmail/camel-sendmail-transport.c deleted file mode 100644 index fbf6f08a6b..0000000000 --- a/camel/providers/sendmail/camel-sendmail-transport.c +++ /dev/null @@ -1,262 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-sendmail-transport.c: Sendmail-based transport class. */ - -/* - * - * Authors: Dan Winship - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include "camel-sendmail-transport.h" -#include "camel-mime-filter-crlf.h" -#include "camel-stream-filter.h" -#include "camel-mime-message.h" -#include "camel-data-wrapper.h" -#include "camel-stream-fs.h" -#include "camel-exception.h" - -static char *get_name (CamelService *service, gboolean brief); - -static gboolean sendmail_send_to (CamelTransport *transport, - CamelMimeMessage *message, - CamelAddress *from, CamelAddress *recipients, - CamelException *ex); - - -static void -camel_sendmail_transport_class_init (CamelSendmailTransportClass *camel_sendmail_transport_class) -{ - CamelTransportClass *camel_transport_class = - CAMEL_TRANSPORT_CLASS (camel_sendmail_transport_class); - CamelServiceClass *camel_service_class = - CAMEL_SERVICE_CLASS (camel_sendmail_transport_class); - - /* virtual method overload */ - camel_service_class->get_name = get_name; - camel_transport_class->send_to = sendmail_send_to; -} - -CamelType -camel_sendmail_transport_get_type (void) -{ - static CamelType camel_sendmail_transport_type = CAMEL_INVALID_TYPE; - - if (camel_sendmail_transport_type == CAMEL_INVALID_TYPE) { - camel_sendmail_transport_type = - camel_type_register (CAMEL_TRANSPORT_TYPE, "CamelSendmailTransport", - sizeof (CamelSendmailTransport), - sizeof (CamelSendmailTransportClass), - (CamelObjectClassInitFunc) camel_sendmail_transport_class_init, - NULL, - (CamelObjectInitFunc) NULL, - NULL); - } - - return camel_sendmail_transport_type; -} - - -static gboolean -sendmail_send_to (CamelTransport *transport, CamelMimeMessage *message, - CamelAddress *from, CamelAddress *recipients, - CamelException *ex) -{ - struct _camel_header_raw *header, *savedbcc, *n, *tail; - const char *from_addr, *addr, **argv; - int i, len, fd[2], nullfd, wstat; - CamelStreamFilter *filter; - CamelMimeFilter *crlf; - sigset_t mask, omask; - CamelStream *out; - pid_t pid; - - if (!camel_internet_address_get (CAMEL_INTERNET_ADDRESS (from), 0, NULL, &from_addr)) - return FALSE; - - len = camel_address_length (recipients); - argv = g_malloc ((len + 6) * sizeof (char *)); - argv[0] = "sendmail"; - argv[1] = "-i"; - argv[2] = "-f"; - argv[3] = from_addr; - argv[4] = "--"; - - for (i = 0; i < len; i++) { - if (!camel_internet_address_get (CAMEL_INTERNET_ADDRESS (recipients), i, NULL, &addr)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not parse recipient list")); - g_free (argv); - return FALSE; - } - - argv[i + 5] = addr; - } - - argv[i + 5] = NULL; - - /* unlink the bcc headers */ - savedbcc = NULL; - tail = (struct _camel_header_raw *) &savedbcc; - - header = (struct _camel_header_raw *) &CAMEL_MIME_PART (message)->headers; - n = header->next; - while (n != NULL) { - if (!strcasecmp (n->name, "Bcc")) { - header->next = n->next; - tail->next = n; - n->next = NULL; - tail = n; - } else { - header = n; - } - - n = header->next; - } - - if (pipe (fd) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create pipe to sendmail: " - "%s: mail not sent"), - g_strerror (errno)); - - /* restore the bcc headers */ - header->next = savedbcc; - - return FALSE; - } - - /* Block SIGCHLD so the calling application doesn't notice - * sendmail exiting before we do. - */ - sigemptyset (&mask); - sigaddset (&mask, SIGCHLD); - sigprocmask (SIG_BLOCK, &mask, &omask); - - pid = fork (); - switch (pid) { - case -1: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not fork sendmail: " - "%s: mail not sent"), - g_strerror (errno)); - sigprocmask (SIG_SETMASK, &omask, NULL); - g_free (argv); - - /* restore the bcc headers */ - header->next = savedbcc; - - return FALSE; - case 0: - /* Child process */ - nullfd = open ("/dev/null", O_RDWR); - dup2 (fd[0], STDIN_FILENO); - /*dup2 (nullfd, STDOUT_FILENO); - dup2 (nullfd, STDERR_FILENO);*/ - close (nullfd); - close (fd[1]); - - execv (SENDMAIL_PATH, (char **)argv); - _exit (255); - } - g_free (argv); - - /* Parent process. Write the message out. */ - close (fd[0]); - out = camel_stream_fs_new_with_fd (fd[1]); - - /* workaround for lame sendmail implementations that can't handle CRLF eoln sequences */ - filter = camel_stream_filter_new_with_stream (out); - crlf = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - camel_stream_filter_add (filter, crlf); - camel_object_unref (crlf); - camel_object_unref (out); - - out = (CamelStream *) filter; - if (camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), out) == -1 - || camel_stream_close (out) == -1) { - camel_object_unref (CAMEL_OBJECT (out)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not send message: %s"), - g_strerror (errno)); - - /* Wait for sendmail to exit. */ - while (waitpid (pid, &wstat, 0) == -1 && errno == EINTR) - ; - - sigprocmask (SIG_SETMASK, &omask, NULL); - - /* restore the bcc headers */ - header->next = savedbcc; - - return FALSE; - } - - camel_object_unref (CAMEL_OBJECT (out)); - - /* Wait for sendmail to exit. */ - while (waitpid (pid, &wstat, 0) == -1 && errno == EINTR) - ; - - sigprocmask (SIG_SETMASK, &omask, NULL); - - /* restore the bcc headers */ - header->next = savedbcc; - - if (!WIFEXITED (wstat)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("sendmail exited with signal %s: " - "mail not sent."), - g_strsignal (WTERMSIG (wstat))); - return FALSE; - } else if (WEXITSTATUS (wstat) != 0) { - if (WEXITSTATUS (wstat) == 255) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not execute %s: " - "mail not sent."), - SENDMAIL_PATH); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("sendmail exited with status " - "%d: mail not sent."), - WEXITSTATUS (wstat)); - } - return FALSE; - } - - return TRUE; -} - -static char * -get_name (CamelService *service, gboolean brief) -{ - if (brief) - return g_strdup (_("sendmail")); - else - return g_strdup (_("Mail delivery via the sendmail program")); -} diff --git a/camel/providers/sendmail/camel-sendmail-transport.h b/camel/providers/sendmail/camel-sendmail-transport.h deleted file mode 100644 index 056be03bc8..0000000000 --- a/camel/providers/sendmail/camel-sendmail-transport.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-sendmail-transport.h: Sendmail-based transport class */ - -/* - * - * Author : - * Dan Winship - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_SENDMAIL_TRANSPORT_H -#define CAMEL_SENDMAIL_TRANSPORT_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-transport.h" - -#define CAMEL_SENDMAIL_TRANSPORT_TYPE (camel_sendmail_transport_get_type ()) -#define CAMEL_SENDMAIL_TRANSPORT(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SENDMAIL_TRANSPORT_TYPE, CamelSendmailTransport)) -#define CAMEL_SENDMAIL_TRANSPORT_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SENDMAIL_TRANSPORT_TYPE, CamelSendmailTransportClass)) -#define CAMEL_IS_SENDMAIL_TRANSPORT(o) (CAMEL_CHECK_TYPE((o), CAMEL_SENDMAIL_TRANSPORT_TYPE)) - - -typedef struct { - CamelTransport parent_object; - -} CamelSendmailTransport; - - -typedef struct { - CamelTransportClass parent_class; - -} CamelSendmailTransportClass; - - -/* Standard Camel function */ -CamelType camel_sendmail_transport_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SENDMAIL_TRANSPORT_H */ diff --git a/camel/providers/sendmail/libcamelsendmail.urls b/camel/providers/sendmail/libcamelsendmail.urls deleted file mode 100644 index ccad52828e..0000000000 --- a/camel/providers/sendmail/libcamelsendmail.urls +++ /dev/null @@ -1 +0,0 @@ -sendmail diff --git a/camel/providers/smtp/.cvsignore b/camel/providers/smtp/.cvsignore deleted file mode 100644 index b948585108..0000000000 --- a/camel/providers/smtp/.cvsignore +++ /dev/null @@ -1,10 +0,0 @@ -.deps -.libs -Makefile -Makefile.in -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/smtp/Makefile.am b/camel/providers/smtp/Makefile.am deleted file mode 100644 index b6bba766d6..0000000000 --- a/camel/providers/smtp/Makefile.am +++ /dev/null @@ -1,35 +0,0 @@ -## Process this file with automake to produce Makefile.in - -libcamelsmtpincludedir = $(privincludedir)/camel - -camel_provider_LTLIBRARIES = libcamelsmtp.la -camel_provider_DATA = libcamelsmtp.urls - -INCLUDES = \ - -I.. \ - -I$(srcdir)/.. \ - -I$(srcdir)/../../.. \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/e-util \ - $(CAMEL_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(GTK_INCLUDEDIR) \ - $(NSPR_CFLAGS) \ - $(NSS_CFLAGS) \ - $(OPENSSL_CFLAGS) \ - -DG_LOG_DOMAIN=\"camel-smtp-provider\" - -libcamelsmtp_la_SOURCES = \ - camel-smtp-provider.c \ - camel-smtp-transport.c - -libcamelsmtpinclude_HEADERS = \ - camel-smtp-transport.h - - -libcamelsmtp_la_LDFLAGS = -avoid-version -module - -libcamelsmtp_la_LIBADD = $(top_builddir)/e-util/libeutil.la - -EXTRA_DIST = libcamelsmtp.urls diff --git a/camel/providers/smtp/camel-smtp-provider.c b/camel/providers/smtp/camel-smtp-provider.c deleted file mode 100644 index 07991eb695..0000000000 --- a/camel/providers/smtp/camel-smtp-provider.c +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-smtp-provider.c: smtp provider registration code */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "camel-smtp-transport.h" -#include "camel-provider.h" -#include "camel-session.h" -#include "camel-url.h" -#include "camel-sasl.h" - -static CamelProvider smtp_provider = { - "smtp", - N_("SMTP"), - - N_("For delivering mail by connecting to a remote mailhub " - "using SMTP.\n"), - - "mail", - - CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_SUPPORTS_SSL, - - CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH | CAMEL_URL_ALLOW_USER, - - /* ... */ -}; - -void -camel_provider_module_init (CamelSession *session) -{ - smtp_provider.object_types[CAMEL_PROVIDER_TRANSPORT] = - camel_smtp_transport_get_type (); - smtp_provider.authtypes = g_list_append (camel_sasl_authtype_list (TRUE), camel_sasl_authtype ("LOGIN")); - smtp_provider.authtypes = g_list_append (smtp_provider.authtypes, camel_sasl_authtype ("POPB4SMTP")); - smtp_provider.url_hash = camel_url_hash; - smtp_provider.url_equal = camel_url_equal; - - camel_session_register_provider (session, &smtp_provider); -} - - - diff --git a/camel/providers/smtp/camel-smtp-transport.c b/camel/providers/smtp/camel-smtp-transport.c deleted file mode 100644 index 5bf5add2ee..0000000000 --- a/camel/providers/smtp/camel-smtp-transport.c +++ /dev/null @@ -1,1455 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-smtp-transport.c : class for a smtp transport */ - -/* - * Authors: Jeffrey Stedfast - * - * Copyright (C) 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#undef MIN -#undef MAX -#include "camel-mime-filter-crlf.h" -#include "camel-stream-filter.h" -#include "camel-smtp-transport.h" -#include "camel-mime-message.h" -#include "camel-multipart.h" -#include "camel-mime-part.h" -#include "camel-operation.h" -#include "camel-stream-buffer.h" -#include "camel-tcp-stream.h" -#include "camel-tcp-stream-raw.h" -#ifdef HAVE_SSL -#include "camel-tcp-stream-ssl.h" -#endif -#include "camel-session.h" -#include "camel-exception.h" -#include "camel-sasl.h" - - -extern int camel_verbose_debug; -#define d(x) (camel_verbose_debug ? (x) : 0) - -/* Specified in RFC 821 */ -#define SMTP_PORT 25 - -/* camel smtp transport class prototypes */ -static gboolean smtp_send_to (CamelTransport *transport, CamelMimeMessage *message, - CamelAddress *from, CamelAddress *recipients, CamelException *ex); - -/* support prototypes */ -static void smtp_construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex); -static gboolean smtp_connect (CamelService *service, CamelException *ex); -static gboolean smtp_disconnect (CamelService *service, gboolean clean, CamelException *ex); -static GHashTable *esmtp_get_authtypes (const unsigned char *buffer); -static GList *query_auth_types (CamelService *service, CamelException *ex); -static char *get_name (CamelService *service, gboolean brief); - -static gboolean smtp_helo (CamelSmtpTransport *transport, CamelException *ex); -static gboolean smtp_auth (CamelSmtpTransport *transport, const char *mech, CamelException *ex); -static gboolean smtp_mail (CamelSmtpTransport *transport, const char *sender, - gboolean has_8bit_parts, CamelException *ex); -static gboolean smtp_rcpt (CamelSmtpTransport *transport, const char *recipient, CamelException *ex); -static gboolean smtp_data (CamelSmtpTransport *transport, CamelMimeMessage *message, CamelException *ex); -static gboolean smtp_rset (CamelSmtpTransport *transport, CamelException *ex); -static gboolean smtp_quit (CamelSmtpTransport *transport, CamelException *ex); - -static void smtp_set_exception (CamelSmtpTransport *transport, const char *respbuf, - const char *message, CamelException *ex); - -/* private data members */ -static CamelTransportClass *parent_class = NULL; - -static void -camel_smtp_transport_class_init (CamelSmtpTransportClass *camel_smtp_transport_class) -{ - CamelTransportClass *camel_transport_class = - CAMEL_TRANSPORT_CLASS (camel_smtp_transport_class); - CamelServiceClass *camel_service_class = - CAMEL_SERVICE_CLASS (camel_smtp_transport_class); - - parent_class = CAMEL_TRANSPORT_CLASS (camel_type_get_global_classfuncs (camel_transport_get_type ())); - - /* virtual method overload */ - camel_service_class->construct = smtp_construct; - camel_service_class->connect = smtp_connect; - camel_service_class->disconnect = smtp_disconnect; - camel_service_class->query_auth_types = query_auth_types; - camel_service_class->get_name = get_name; - - camel_transport_class->send_to = smtp_send_to; -} - -static void -camel_smtp_transport_init (gpointer object) -{ - CamelSmtpTransport *smtp = CAMEL_SMTP_TRANSPORT (object); - - smtp->flags = 0; - smtp->connected = FALSE; -} - -CamelType -camel_smtp_transport_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (CAMEL_TRANSPORT_TYPE, - "CamelSmtpTransport", - sizeof (CamelSmtpTransport), - sizeof (CamelSmtpTransportClass), - (CamelObjectClassInitFunc) camel_smtp_transport_class_init, - NULL, - (CamelObjectInitFunc) camel_smtp_transport_init, - NULL); - } - - return type; -} - -static void -smtp_construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex) -{ - CamelSmtpTransport *smtp_transport = CAMEL_SMTP_TRANSPORT (service); - const char *use_ssl; - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - - if ((use_ssl = camel_url_get_param (url, "use_ssl"))) { - /* Note: previous versions would use "" to toggle use_ssl to 'on' */ - if (!*use_ssl || !strcmp (use_ssl, "always")) - smtp_transport->flags |= CAMEL_SMTP_TRANSPORT_USE_SSL_ALWAYS; - else if (!strcmp (use_ssl, "when-possible")) - smtp_transport->flags |= CAMEL_SMTP_TRANSPORT_USE_SSL_WHEN_POSSIBLE; - } -} - -static const char * -smtp_error_string (int error) -{ - /* SMTP error codes grabbed from rfc821 */ - switch (error) { - case 0: - /* looks like a read problem, check errno */ - if (errno) - return g_strerror (errno); - else - return _("Unknown"); - case 500: - return _("Syntax error, command unrecognized"); - case 501: - return _("Syntax error in parameters or arguments"); - case 502: - return _("Command not implemented"); - case 504: - return _("Command parameter not implemented"); - case 211: - return _("System status, or system help reply"); - case 214: - return _("Help message"); - case 220: - return _("Service ready"); - case 221: - return _("Service closing transmission channel"); - case 421: - return _("Service not available, closing transmission channel"); - case 250: - return _("Requested mail action okay, completed"); - case 251: - return _("User not local; will forward to "); - case 450: - return _("Requested mail action not taken: mailbox unavailable"); - case 550: - return _("Requested action not taken: mailbox unavailable"); - case 451: - return _("Requested action aborted: error in processing"); - case 551: - return _("User not local; please try "); - case 452: - return _("Requested action not taken: insufficient system storage"); - case 552: - return _("Requested mail action aborted: exceeded storage allocation"); - case 553: - return _("Requested action not taken: mailbox name not allowed"); - case 354: - return _("Start mail input; end with ."); - case 554: - return _("Transaction failed"); - - /* AUTH error codes: */ - case 432: - return _("A password transition is needed"); - case 534: - return _("Authentication mechanism is too weak"); - case 538: - return _("Encryption required for requested authentication mechanism"); - case 454: - return _("Temporary authentication failure"); - case 530: - return _("Authentication required"); - - default: - return _("Unknown"); - } -} - -#define SSL_PORT_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3) -#define STARTTLS_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_TLS) - -static gboolean -connect_to_server (CamelService *service, int try_starttls, CamelException *ex) -{ - CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service); - CamelStream *tcp_stream; - char *respbuf = NULL; - struct hostent *h; - int port, ret; - - if (!CAMEL_SERVICE_CLASS (parent_class)->connect (service, ex)) - return FALSE; - - h = camel_service_gethost (service, ex); - if (!h) - return FALSE; - - /* set some smtp transport defaults */ - transport->flags &= CAMEL_SMTP_TRANSPORT_USE_SSL; /* reset all but ssl flags */ - transport->authtypes = NULL; - - port = service->url->port ? service->url->port : SMTP_PORT; - - if (transport->flags & CAMEL_SMTP_TRANSPORT_USE_SSL) { -#ifdef HAVE_SSL - if (try_starttls) { - tcp_stream = camel_tcp_stream_ssl_new_raw (service->session, service->url->host, STARTTLS_FLAGS); - } else { - port = service->url->port ? service->url->port : 465; - tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, SSL_PORT_FLAGS); - } -#else - if (!try_starttls) - port = service->url->port ? service->url->port : 465; - - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s (port %d): %s"), - service->url->host, port, - _("SSL unavailable")); - - camel_free_host (h); - - return FALSE; -#endif /* HAVE_SSL */ - } else { - tcp_stream = camel_tcp_stream_raw_new (); - } - - ret = camel_tcp_stream_connect (CAMEL_TCP_STREAM (tcp_stream), h, port); - camel_free_host (h); - if (ret == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s (port %d): %s"), - service->url->host, port, - g_strerror (errno)); - - camel_object_unref (tcp_stream); - - return FALSE; - } - - transport->connected = TRUE; - - /* get the localaddr - needed later by smtp_helo */ - transport->localaddr = camel_tcp_stream_get_local_address (CAMEL_TCP_STREAM (tcp_stream)); - - transport->ostream = tcp_stream; - transport->istream = camel_stream_buffer_new (tcp_stream, CAMEL_STREAM_BUFFER_READ); - - /* Read the greeting, note whether the server is ESMTP or not. */ - do { - /* Check for "220" */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - if (!respbuf || strncmp (respbuf, "220", 3)) { - smtp_set_exception (transport, respbuf, _("Welcome response error"), ex); - g_free (respbuf); - return FALSE; - } - } while (*(respbuf+3) == '-'); /* if we got "220-" then loop again */ - g_free (respbuf); - - /* Try sending EHLO */ - transport->flags |= CAMEL_SMTP_TRANSPORT_IS_ESMTP; - if (!smtp_helo (transport, ex)) { - if (!transport->connected) - return FALSE; - - /* Fall back to HELO */ - camel_exception_clear (ex); - transport->flags &= ~CAMEL_SMTP_TRANSPORT_IS_ESMTP; - if (!smtp_helo (transport, ex) && !transport->connected) - return FALSE; - } - - /* clear any EHLO/HELO exception and assume that any SMTP errors encountered were non-fatal */ - camel_exception_clear (ex); - -#ifdef HAVE_SSL - if (transport->flags & CAMEL_SMTP_TRANSPORT_USE_SSL_WHEN_POSSIBLE) { - /* try_starttls is always TRUE here */ - if (transport->flags & CAMEL_SMTP_TRANSPORT_STARTTLS) - goto starttls; - } else if (transport->flags & CAMEL_SMTP_TRANSPORT_USE_SSL_ALWAYS) { - if (try_starttls) { - if (transport->flags & CAMEL_SMTP_TRANSPORT_STARTTLS) { - goto starttls; - } else { - /* server doesn't support STARTTLS, abort */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to SMTP server %s in secure mode: %s"), - service->url->host, _("server does not appear to support SSL")); - goto exception_cleanup; - } - } - } -#endif /* HAVE_SSL */ - - return TRUE; - -#ifdef HAVE_SSL - starttls: - d(fprintf (stderr, "sending : STARTTLS\r\n")); - if (camel_stream_write (tcp_stream, "STARTTLS\r\n", 10) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("STARTTLS request timed out: %s"), - g_strerror (errno)); - goto exception_cleanup; - } - - respbuf = NULL; - - do { - /* Check for "220 Ready for TLS" */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "220", 3)) { - smtp_set_exception (transport, respbuf, _("STARTTLS response error"), ex); - g_free (respbuf); - goto exception_cleanup; - } - } while (*(respbuf+3) == '-'); /* if we got "220-" then loop again */ - - /* Okay, now toggle SSL/TLS mode */ - if (camel_tcp_stream_ssl_enable_ssl (CAMEL_TCP_STREAM_SSL (tcp_stream)) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to SMTP server %s in secure mode: %s"), - service->url->host, g_strerror (errno)); - goto exception_cleanup; - } - - /* We are supposed to re-EHLO after a successful STARTTLS to - re-fetch any supported extensions. */ - if (!smtp_helo (transport, ex) && !transport->connected) - return FALSE; - - return TRUE; - - exception_cleanup: - - camel_object_unref (transport->istream); - transport->istream = NULL; - camel_object_unref (transport->ostream); - transport->ostream = NULL; - - transport->connected = FALSE; - - return FALSE; -#endif /* HAVE_SSL */ -} - -static gboolean -connect_to_server_wrapper (CamelService *service, CamelException *ex) -{ -#ifdef HAVE_SSL - CamelSmtpTransport *transport = (CamelSmtpTransport *) service; - - if (transport->flags & CAMEL_SMTP_TRANSPORT_USE_SSL_ALWAYS) { - /* First try connecting to the SSL port */ - if (!connect_to_server (service, FALSE, ex)) { - if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE) { - /* Seems the SSL port is unavailable, lets try STARTTLS */ - camel_exception_clear (ex); - return connect_to_server (service, TRUE, ex); - } else { - return FALSE; - } - } - - return TRUE; - } else if (transport->flags & CAMEL_SMTP_TRANSPORT_USE_SSL_WHEN_POSSIBLE) { - /* If the server supports STARTTLS, use it */ - return connect_to_server (service, TRUE, ex); - } else { - /* User doesn't care about SSL */ - return connect_to_server (service, FALSE, ex); - } -#else - return connect_to_server (service, FALSE, ex); -#endif -} - -static gboolean -smtp_connect (CamelService *service, CamelException *ex) -{ - CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service); - gboolean has_authtypes; - - /* We (probably) need to check popb4smtp before we connect ... */ - if (service->url->authmech && !strcmp (service->url->authmech, "POPB4SMTP")) { - int truth; - GByteArray *chal; - CamelSasl *sasl; - - sasl = camel_sasl_new ("smtp", "POPB4SMTP", service); - chal = camel_sasl_challenge (sasl, NULL, ex); - truth = camel_sasl_authenticated (sasl); - if (chal) - g_byte_array_free (chal, TRUE); - camel_object_unref (sasl); - - if (!truth) - return FALSE; - - return connect_to_server_wrapper (service, ex); - } - - if (!connect_to_server_wrapper (service, ex)) - return FALSE; - - /* check to see if AUTH is required, if so...then AUTH ourselves */ - has_authtypes = transport->authtypes ? g_hash_table_size (transport->authtypes) > 0 : FALSE; - if (service->url->authmech && (transport->flags & CAMEL_SMTP_TRANSPORT_IS_ESMTP) && has_authtypes) { - CamelSession *session = camel_service_get_session (service); - CamelServiceAuthType *authtype; - gboolean authenticated = FALSE; - char *errbuf = NULL; - - if (!g_hash_table_lookup (transport->authtypes, service->url->authmech)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("SMTP server %s does not support requested " - "authentication type %s."), - service->url->host, service->url->authmech); - camel_service_disconnect (service, TRUE, NULL); - return FALSE; - } - - authtype = camel_sasl_authtype (service->url->authmech); - if (!authtype) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("No support for authentication type %s"), - service->url->authmech); - camel_service_disconnect (service, TRUE, NULL); - return FALSE; - } - - if (!authtype->need_password) { - /* authentication mechanism doesn't need a password, - so if it fails there's nothing we can do */ - authenticated = smtp_auth (transport, authtype->authproto, ex); - if (!authenticated) { - camel_service_disconnect (service, TRUE, NULL); - return FALSE; - } - } - - /* keep trying to login until either we succeed or the user cancels */ - while (!authenticated) { - if (errbuf) { - /* We need to un-cache the password before prompting again */ - camel_session_forget_password (session, service, "password", NULL); - g_free (service->url->passwd); - service->url->passwd = NULL; - } - - if (!service->url->passwd) { - char *prompt; - - prompt = g_strdup_printf (_("%sPlease enter the SMTP password for %s@%s"), - errbuf ? errbuf : "", service->url->user, - service->url->host); - - service->url->passwd = camel_session_get_password (session, prompt, FALSE, TRUE, - service, "password", ex); - - g_free (prompt); - g_free (errbuf); - errbuf = NULL; - - if (!service->url->passwd) { - camel_service_disconnect (service, TRUE, NULL); - return FALSE; - } - } - - authenticated = smtp_auth (transport, authtype->authproto, ex); - if (!authenticated) { - errbuf = g_strdup_printf (_("Unable to authenticate " - "to SMTP server.\n%s\n\n"), - camel_exception_get_description (ex)); - camel_exception_clear (ex); - } - } - - /* The spec says we have to re-EHLO, but some servers - * we won't bother to name don't want you to... so ignore - * errors. - */ - if (!smtp_helo (transport, ex) && !transport->connected) - return FALSE; - - camel_exception_clear (ex); - } - - return TRUE; -} - -static void -authtypes_free (gpointer key, gpointer value, gpointer data) -{ - g_free (value); -} - -static gboolean -smtp_disconnect (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service); - - /*if (!service->connected) - * return TRUE; - */ - - if (transport->connected && clean) { - /* send the QUIT command to the SMTP server */ - smtp_quit (transport, ex); - } - - if (!CAMEL_SERVICE_CLASS (parent_class)->disconnect (service, clean, ex)) - return FALSE; - - if (transport->authtypes) { - g_hash_table_foreach (transport->authtypes, authtypes_free, NULL); - g_hash_table_destroy (transport->authtypes); - transport->authtypes = NULL; - } - - if (transport->istream) { - camel_object_unref (transport->istream); - transport->istream = NULL; - } - - if (transport->ostream) { - camel_object_unref (transport->ostream); - transport->ostream = NULL; - } - - camel_tcp_address_free (transport->localaddr); - transport->localaddr = NULL; - - transport->connected = FALSE; - - return TRUE; -} - -static GHashTable * -esmtp_get_authtypes (const unsigned char *buffer) -{ - const unsigned char *start, *end; - GHashTable *table = NULL; - - /* advance to the first token */ - start = buffer; - while (isspace ((int) *start) || *start == '=') - start++; - - if (!*start) - return NULL; - - table = g_hash_table_new (g_str_hash, g_str_equal); - - for ( ; *start; ) { - char *type; - - /* advance to the end of the token */ - end = start; - while (*end && !isspace ((int) *end)) - end++; - - type = g_strndup (start, end - start); - g_hash_table_insert (table, type, type); - - /* advance to the next token */ - start = end; - while (isspace ((int) *start)) - start++; - } - - return table; -} - -static GList * -query_auth_types (CamelService *service, CamelException *ex) -{ - CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service); - CamelServiceAuthType *authtype; - GList *types, *t, *next; - - if (!connect_to_server_wrapper (service, ex)) - return NULL; - - types = g_list_copy (service->provider->authtypes); - for (t = types; t; t = next) { - authtype = t->data; - next = t->next; - - if (!g_hash_table_lookup (transport->authtypes, authtype->authproto)) { - types = g_list_remove_link (types, t); - g_list_free_1 (t); - } - } - - smtp_disconnect (service, TRUE, NULL); - - return types; -} - -static char * -get_name (CamelService *service, gboolean brief) -{ - if (brief) - return g_strdup_printf (_("SMTP server %s"), service->url->host); - else { - return g_strdup_printf (_("SMTP mail delivery via %s"), - service->url->host); - } -} - -static gboolean -smtp_send_to (CamelTransport *transport, CamelMimeMessage *message, - CamelAddress *from, CamelAddress *recipients, - CamelException *ex) -{ - CamelSmtpTransport *smtp_transport = CAMEL_SMTP_TRANSPORT (transport); - const CamelInternetAddress *cia; - gboolean has_8bit_parts; - const char *addr; - int i, len; - - if (!camel_internet_address_get (CAMEL_INTERNET_ADDRESS (from), 0, NULL, &addr)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot send message: " - "sender address not valid.")); - return FALSE; - } - - camel_operation_start (NULL, _("Sending message")); - - /* find out if the message has 8bit mime parts */ - has_8bit_parts = camel_mime_message_has_8bit_parts (message); - - /* rfc1652 (8BITMIME) requires that you notify the ESMTP daemon that - you'll be sending an 8bit mime message at "MAIL FROM:" time. */ - if (!smtp_mail (smtp_transport, addr, has_8bit_parts, ex)) { - camel_operation_end (NULL); - return FALSE; - } - - len = camel_address_length (recipients); - if (len == 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot send message: no recipients defined.")); - camel_operation_end (NULL); - return FALSE; - } - - cia = CAMEL_INTERNET_ADDRESS (recipients); - for (i = 0; i < len; i++) { - char *enc; - - if (!camel_internet_address_get (cia, i, NULL, &addr)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot send message: one or more invalid recipients")); - camel_operation_end (NULL); - return FALSE; - } - - enc = camel_internet_address_encode_address(NULL, NULL, addr); - if (!smtp_rcpt (smtp_transport, enc, ex)) { - g_free(enc); - camel_operation_end (NULL); - return FALSE; - } - g_free(enc); - } - - if (!smtp_data (smtp_transport, message, ex)) { - camel_operation_end (NULL); - return FALSE; - } - - /* reset the service for our next transfer session */ - smtp_rset (smtp_transport, ex); - - camel_operation_end (NULL); - - return TRUE; -} - -static const char * -smtp_next_token (const char *buf) -{ - const unsigned char *token; - - token = (const unsigned char *) buf; - while (*token && !isspace ((int) *token)) - token++; - - while (*token && isspace ((int) *token)) - token++; - - return (const char *) token; -} - -#define HEXVAL(c) (isdigit (c) ? (c) - '0' : (c) - 'A' + 10) - -/** - * example (rfc2034): - * 5.1.1 Mailbox "nosuchuser" does not exist - * - * The human-readable status code is what we want. Since this text - * could possibly be encoded, we must decode it. - * - * "xtext" is formally defined as follows: - * - * xtext = *( xchar / hexchar / linear-white-space / comment ) - * - * xchar = any ASCII CHAR between "!" (33) and "~" (126) inclusive, - * except for "+", "\" and "(". - * - * "hexchar"s are intended to encode octets that cannot be represented - * as plain text, either because they are reserved, or because they are - * non-printable. However, any octet value may be represented by a - * "hexchar". - * - * hexchar = ASCII "+" immediately followed by two upper case - * hexadecimal digits - **/ -static char * -smtp_decode_status_code (const char *in, size_t len) -{ - unsigned char *inptr, *outptr; - const unsigned char *inend; - char *outbuf; - - outptr = outbuf = g_malloc (len + 1); - - inptr = (unsigned char *) in; - inend = inptr + len; - while (inptr < inend) { - if (*inptr == '+') { - if (isxdigit (inptr[1]) && isxdigit (inptr[2])) { - *outptr++ = HEXVAL (inptr[1]) * 16 + HEXVAL (inptr[2]); - inptr += 3; - } else - *outptr++ = *inptr++; - } else - *outptr++ = *inptr++; - } - - *outptr = '\0'; - - return outbuf; -} - -static void -smtp_set_exception (CamelSmtpTransport *transport, const char *respbuf, const char *message, CamelException *ex) -{ - const char *token, *rbuf = respbuf; - char *buffer = NULL; - GString *string; - int error; - - if (!respbuf || !(transport->flags & CAMEL_SMTP_TRANSPORT_ENHANCEDSTATUSCODES)) { - fake_status_code: - error = respbuf ? atoi (respbuf) : 0; - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, "%s: %s", message, - smtp_error_string (error)); - } else { - string = g_string_new (""); - do { - token = smtp_next_token (rbuf + 4); - if (*token == '\0') { - g_free (buffer); - g_string_free (string, TRUE); - goto fake_status_code; - } - - g_string_append (string, token); - if (*(rbuf + 3) == '-') { - g_free (buffer); - buffer = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - g_string_append_c (string, '\n'); - } else { - g_free (buffer); - buffer = NULL; - } - - rbuf = buffer; - } while (rbuf); - - buffer = smtp_decode_status_code (string->str, string->len); - g_string_free (string, TRUE); - if (!buffer) - goto fake_status_code; - - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - "%s: %s", message, buffer); - - g_free (buffer); - } - - if (!respbuf) { - /* we got disconnected */ - transport->connected = FALSE; - } -} - -static gboolean -smtp_helo (CamelSmtpTransport *transport, CamelException *ex) -{ - /* say hello to the server */ - char *name = NULL, *cmdbuf = NULL, *respbuf = NULL; - struct hostent *host; - CamelException err; - const char *token; - int af; - - /* these are flags that we set, so unset them in case we - are being called a second time (ie, after a STARTTLS) */ - transport->flags &= ~(CAMEL_SMTP_TRANSPORT_8BITMIME | - CAMEL_SMTP_TRANSPORT_ENHANCEDSTATUSCODES | - CAMEL_SMTP_TRANSPORT_STARTTLS); - - if (transport->authtypes) { - g_hash_table_foreach (transport->authtypes, authtypes_free, NULL); - g_hash_table_destroy (transport->authtypes); - transport->authtypes = NULL; - } - - camel_operation_start_transient (NULL, _("SMTP Greeting")); - - /* get the local host name */ - camel_exception_init (&err); -#ifdef ENABLE_IPv6 - af = transport->localaddr->family == CAMEL_TCP_ADDRESS_IPv6 ? AF_INET6 : AF_INET; -#else - af = AF_INET; -#endif - host = camel_gethostbyaddr ((char *) &transport->localaddr->address, - transport->localaddr->length, af, &err); - - camel_exception_clear (&err); - - if (host && host->h_name && *host->h_name) { - name = g_strdup (host->h_name); - } else { -#ifdef ENABLE_IPv6 - char ip[MAXHOSTNAMELEN + 1]; - const char *proto; - - proto = transport->localaddr->family == CAMEL_TCP_ADDRESS_IPv6 ? "IPv6:" : ""; - name = g_strdup_printf ("[%s%s]", proto, inet_ntop (af, transport->localaddr->address, ip, MAXHOSTNAMELEN)); -#else - /* We *could* use inet_ntoa() here, but it's probably - not worth it since we would have to worry about - some systems not having inet_ntoa() */ - name = g_strdup_printf ("[%d.%d.%d.%d]", - transport->localaddr->address[0], - transport->localaddr->address[1], - transport->localaddr->address[2], - transport->localaddr->address[3]); -#endif - } - - if (host) - camel_free_host (host); - - /* hiya server! how are you today? */ - if (transport->flags & CAMEL_SMTP_TRANSPORT_IS_ESMTP) - cmdbuf = g_strdup_printf ("EHLO %s\r\n", name); - else - cmdbuf = g_strdup_printf ("HELO %s\r\n", name); - g_free (name); - - d(fprintf (stderr, "sending : %s", cmdbuf)); - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("HELO request timed out: %s"), - g_strerror (errno)); - camel_operation_end (NULL); - - transport->connected = FALSE; - camel_object_unref (transport->istream); - transport->istream = NULL; - camel_object_unref (transport->ostream); - transport->ostream = NULL; - - return FALSE; - } - g_free (cmdbuf); - - do { - /* Check for "250" */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "250", 3)) { - smtp_set_exception (transport, respbuf, _("HELO response error"), ex); - camel_operation_end (NULL); - g_free (respbuf); - - return FALSE; - } - - token = respbuf + 4; - - if (transport->flags & CAMEL_SMTP_TRANSPORT_IS_ESMTP) { - if (!strncmp (token, "8BITMIME", 8)) { - d(fprintf (stderr, "This server supports 8bit MIME\n")); - transport->flags |= CAMEL_SMTP_TRANSPORT_8BITMIME; - } else if (!strncmp (token, "ENHANCEDSTATUSCODES", 19)) { - d(fprintf (stderr, "This server supports enhanced status codes\n")); - transport->flags |= CAMEL_SMTP_TRANSPORT_ENHANCEDSTATUSCODES; - } else if (!strncmp (token, "STARTTLS", 8)) { - d(fprintf (stderr, "This server supports STARTTLS\n")); - transport->flags |= CAMEL_SMTP_TRANSPORT_STARTTLS; - } else if (!strncmp (token, "AUTH", 4)) { - if (!transport->authtypes || transport->flags & CAMEL_SMTP_TRANSPORT_AUTH_EQUAL) { - /* Don't bother parsing any authtypes if we already have a list. - * Some servers will list AUTH twice, once the standard way and - * once the way Microsoft Outlook requires them to be: - * - * 250-AUTH LOGIN PLAIN DIGEST-MD5 CRAM-MD5 - * 250-AUTH=LOGIN PLAIN DIGEST-MD5 CRAM-MD5 - * - * Since they can come in any order, parse each list that we get - * until we parse an authtype list that does not use the AUTH= - * format. We want to let the standard way have priority over the - * broken way. - **/ - - if (token[4] == '=') - transport->flags |= CAMEL_SMTP_TRANSPORT_AUTH_EQUAL; - else - transport->flags &= ~CAMEL_SMTP_TRANSPORT_AUTH_EQUAL; - - /* parse for supported AUTH types */ - token += 5; - - if (transport->authtypes) { - g_hash_table_foreach (transport->authtypes, authtypes_free, NULL); - g_hash_table_destroy (transport->authtypes); - } - - transport->authtypes = esmtp_get_authtypes (token); - } - } - } - } while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */ - g_free (respbuf); - - camel_operation_end (NULL); - - return TRUE; -} - -static gboolean -smtp_auth (CamelSmtpTransport *transport, const char *mech, CamelException *ex) -{ - char *cmdbuf, *respbuf = NULL, *challenge; - gboolean auth_challenge = FALSE; - CamelSasl *sasl = NULL; - - camel_operation_start_transient (NULL, _("SMTP Authentication")); - - sasl = camel_sasl_new ("smtp", mech, CAMEL_SERVICE (transport)); - if (!sasl) { - camel_operation_end (NULL); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Error creating SASL authentication object.")); - return FALSE; - } - - challenge = camel_sasl_challenge_base64 (sasl, NULL, ex); - if (challenge) { - auth_challenge = TRUE; - cmdbuf = g_strdup_printf ("AUTH %s %s\r\n", mech, challenge); - g_free (challenge); - } else { - cmdbuf = g_strdup_printf ("AUTH %s\r\n", mech); - } - - d(fprintf (stderr, "sending : %s", cmdbuf)); - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("AUTH request timed out: %s"), - g_strerror (errno)); - goto lose; - } - g_free (cmdbuf); - - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - while (!camel_sasl_authenticated (sasl)) { - if (!respbuf) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("AUTH request timed out: %s"), - g_strerror (errno)); - goto lose; - } - - /* the server challenge/response should follow a 334 code */ - if (strncmp (respbuf, "334", 3)) { - g_free (respbuf); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("AUTH request failed.")); - goto lose; - } - - if (FALSE) { - broken_smtp_server: - d(fprintf (stderr, "Your SMTP server's implementation of the %s SASL\n" - "authentication mechanism is broken. Please report this to the\n" - "appropriate vendor and suggest that they re-read rfc2554 again\n" - "for the first time (specifically Section 4).\n", - mech)); - } - - /* eat whtspc */ - for (challenge = respbuf + 4; isspace (*challenge); challenge++); - - challenge = camel_sasl_challenge_base64 (sasl, challenge, ex); - g_free (respbuf); - if (challenge == NULL) - goto break_and_lose; - - /* send our challenge */ - cmdbuf = g_strdup_printf ("%s\r\n", challenge); - g_free (challenge); - d(fprintf (stderr, "sending : %s", cmdbuf)); - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - goto lose; - } - g_free (cmdbuf); - - /* get the server's response */ - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - } - - /* check that the server says we are authenticated */ - if (!respbuf || strncmp (respbuf, "235", 3)) { - if (respbuf && auth_challenge && !strncmp (respbuf, "334", 3)) { - /* broken server, but lets try and work around it anyway... */ - goto broken_smtp_server; - } - g_free (respbuf); - goto lose; - } - - camel_object_unref (sasl); - camel_operation_end (NULL); - - return TRUE; - - break_and_lose: - /* Get the server out of "waiting for continuation data" mode. */ - d(fprintf (stderr, "sending : *\n")); - camel_stream_write (transport->ostream, "*\r\n", 3); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - lose: - if (!camel_exception_is_set (ex)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Bad authentication response from server.\n")); - } - - camel_object_unref (sasl); - camel_operation_end (NULL); - - return FALSE; -} - -static gboolean -smtp_mail (CamelSmtpTransport *transport, const char *sender, gboolean has_8bit_parts, CamelException *ex) -{ - /* we gotta tell the smtp server who we are. (our email addy) */ - char *cmdbuf, *respbuf = NULL; - - if (transport->flags & CAMEL_SMTP_TRANSPORT_8BITMIME && has_8bit_parts) - cmdbuf = g_strdup_printf ("MAIL FROM:<%s> BODY=8BITMIME\r\n", sender); - else - cmdbuf = g_strdup_printf ("MAIL FROM:<%s>\r\n", sender); - - d(fprintf (stderr, "sending : %s", cmdbuf)); - - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("MAIL FROM request timed out: %s: mail not sent"), - g_strerror (errno)); - - camel_object_unref (transport->istream); - transport->istream = NULL; - camel_object_unref (transport->ostream); - transport->ostream = NULL; - - return FALSE; - } - g_free (cmdbuf); - - do { - /* Check for "250 Sender OK..." */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "250", 3)) { - smtp_set_exception (transport, respbuf, _("MAIL FROM response error"), ex); - g_free (respbuf); - return FALSE; - } - } while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */ - g_free (respbuf); - - return TRUE; -} - -static gboolean -smtp_rcpt (CamelSmtpTransport *transport, const char *recipient, CamelException *ex) -{ - /* we gotta tell the smtp server who we are going to be sending - * our email to */ - char *cmdbuf, *respbuf = NULL; - - cmdbuf = g_strdup_printf ("RCPT TO:<%s>\r\n", recipient); - - d(fprintf (stderr, "sending : %s", cmdbuf)); - - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("RCPT TO request timed out: %s: mail not sent"), - g_strerror (errno)); - - camel_object_unref (transport->istream); - transport->istream = NULL; - camel_object_unref (transport->ostream); - transport->ostream = NULL; - - return FALSE; - } - g_free (cmdbuf); - - do { - /* Check for "250 Recipient OK..." */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "250", 3)) { - char *message; - - message = g_strdup_printf (_("RCPT TO <%s> failed"), recipient); - smtp_set_exception (transport, respbuf, message, ex); - g_free (message); - g_free (respbuf); - return FALSE; - } - } while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */ - g_free (respbuf); - - return TRUE; -} - -static gboolean -smtp_data (CamelSmtpTransport *transport, CamelMimeMessage *message, CamelException *ex) -{ - CamelBestencEncoding enctype = CAMEL_BESTENC_8BIT; - struct _camel_header_raw *header, *savedbcc, *n, *tail; - char *cmdbuf, *respbuf = NULL; - CamelStreamFilter *filtered_stream; - CamelMimeFilter *crlffilter; - int ret; - - /* If the server doesn't support 8BITMIME, set our required encoding to be 7bit */ - if (!(transport->flags & CAMEL_SMTP_TRANSPORT_8BITMIME)) - enctype = CAMEL_BESTENC_7BIT; - - /* FIXME: should we get the best charset too?? */ - /* Changes the encoding of all mime parts to fit within our required - encoding type and also force any text parts with long lines (longer - than 998 octets) to wrap by QP or base64 encoding them. */ - camel_mime_message_set_best_encoding (message, CAMEL_BESTENC_GET_ENCODING, enctype); - - cmdbuf = g_strdup ("DATA\r\n"); - - d(fprintf (stderr, "sending : %s", cmdbuf)); - - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("DATA request timed out: %s: mail not sent"), - g_strerror (errno)); - - camel_object_unref (transport->istream); - transport->istream = NULL; - camel_object_unref (transport->ostream); - transport->ostream = NULL; - - return FALSE; - } - g_free (cmdbuf); - - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "354", 3)) { - /* we should have gotten instructions on how to use the DATA command: - * 354 Enter mail, end with "." on a line by itself - */ - smtp_set_exception (transport, respbuf, _("DATA response error"), ex); - g_free (respbuf); - return FALSE; - } - - g_free (respbuf); - respbuf = NULL; - - /* setup stream filtering */ - crlffilter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS); - filtered_stream = camel_stream_filter_new_with_stream (transport->ostream); - camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (crlffilter)); - camel_object_unref (crlffilter); - - /* unlink the bcc headers */ - savedbcc = NULL; - tail = (struct _camel_header_raw *) &savedbcc; - - header = (struct _camel_header_raw *) &CAMEL_MIME_PART (message)->headers; - n = header->next; - while (n != NULL) { - if (!strcasecmp (n->name, "Bcc")) { - header->next = n->next; - tail->next = n; - n->next = NULL; - tail = n; - } else { - header = n; - } - - n = header->next; - } - - /* write the message */ - ret = camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), CAMEL_STREAM (filtered_stream)); - - /* restore the bcc headers */ - header->next = savedbcc; - - if (ret == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("DATA send timed out: message termination: " - "%s: mail not sent"), - g_strerror (errno)); - - camel_object_unref (filtered_stream); - - camel_object_unref (transport->istream); - transport->istream = NULL; - camel_object_unref (transport->ostream); - transport->ostream = NULL; - - return FALSE; - } - - camel_stream_flush (CAMEL_STREAM (filtered_stream)); - camel_object_unref (filtered_stream); - - /* terminate the message body */ - - d(fprintf (stderr, "sending : \\r\\n.\\r\\n\n")); - - if (camel_stream_write (transport->ostream, "\r\n.\r\n", 5) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("DATA send timed out: message termination: " - "%s: mail not sent"), - g_strerror (errno)); - - camel_object_unref (transport->istream); - transport->istream = NULL; - camel_object_unref (transport->ostream); - transport->ostream = NULL; - - return FALSE; - } - - do { - /* Check for "250 Sender OK..." */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "250", 3)) { - smtp_set_exception (transport, respbuf, _("DATA termination response error"), ex); - g_free (respbuf); - return FALSE; - } - } while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */ - g_free (respbuf); - - return TRUE; -} - -static gboolean -smtp_rset (CamelSmtpTransport *transport, CamelException *ex) -{ - /* we are going to reset the smtp server (just to be nice) */ - char *cmdbuf, *respbuf = NULL; - - cmdbuf = g_strdup ("RSET\r\n"); - - d(fprintf (stderr, "sending : %s", cmdbuf)); - - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("RSET request timed out: %s"), - g_strerror (errno)); - - camel_object_unref (transport->istream); - transport->istream = NULL; - camel_object_unref (transport->ostream); - transport->ostream = NULL; - - return FALSE; - } - g_free (cmdbuf); - - do { - /* Check for "250" */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "250", 3)) { - smtp_set_exception (transport, respbuf, _("RSET response error"), ex); - g_free (respbuf); - return FALSE; - } - } while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */ - g_free (respbuf); - - return TRUE; -} - -static gboolean -smtp_quit (CamelSmtpTransport *transport, CamelException *ex) -{ - /* we are going to reset the smtp server (just to be nice) */ - char *cmdbuf, *respbuf = NULL; - - cmdbuf = g_strdup ("QUIT\r\n"); - - d(fprintf (stderr, "sending : %s", cmdbuf)); - - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("QUIT request timed out: %s"), - g_strerror (errno)); - - camel_object_unref (transport->istream); - transport->istream = NULL; - camel_object_unref (transport->ostream); - transport->ostream = NULL; - - return FALSE; - } - g_free (cmdbuf); - - do { - /* Check for "221" */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "221", 3)) { - smtp_set_exception (transport, respbuf, _("QUIT response error"), ex); - g_free (respbuf); - return FALSE; - } - } while (*(respbuf+3) == '-'); /* if we got "221-" then loop again */ - g_free (respbuf); - - return TRUE; -} diff --git a/camel/providers/smtp/camel-smtp-transport.h b/camel/providers/smtp/camel-smtp-transport.h deleted file mode 100644 index ef15f2b07d..0000000000 --- a/camel/providers/smtp/camel-smtp-transport.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-smtp-transport.h : class for an smtp transfer */ - -/* - * Authors: - * Jeffrey Stedfast - * - * Copyright (C) 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_SMTP_TRANSPORT_H -#define CAMEL_SMTP_TRANSPORT_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - - -#include "camel-transport.h" -#include "camel-tcp-stream.h" - -#define CAMEL_SMTP_TRANSPORT_TYPE (camel_smtp_transport_get_type ()) -#define CAMEL_SMTP_TRANSPORT(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SMTP_TRANSPORT_TYPE, CamelSmtpTransport)) -#define CAMEL_SMTP_TRANSPORT_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SMTP_TRANSPORT_TYPE, CamelSmtpTransportClass)) -#define CAMEL_IS_SMTP_TRANSPORT(o) (CAMEL_CHECK_TYPE((o), CAMEL_SMTP_TRANSPORT_TYPE)) - - -#define CAMEL_SMTP_TRANSPORT_IS_ESMTP (1 << 0) -#define CAMEL_SMTP_TRANSPORT_8BITMIME (1 << 1) -#define CAMEL_SMTP_TRANSPORT_ENHANCEDSTATUSCODES (1 << 2) -#define CAMEL_SMTP_TRANSPORT_STARTTLS (1 << 3) - -#define CAMEL_SMTP_TRANSPORT_USE_SSL_ALWAYS (1 << 4) -#define CAMEL_SMTP_TRANSPORT_USE_SSL_WHEN_POSSIBLE (1 << 5) - -#define CAMEL_SMTP_TRANSPORT_USE_SSL (CAMEL_SMTP_TRANSPORT_USE_SSL_ALWAYS | \ - CAMEL_SMTP_TRANSPORT_USE_SSL_WHEN_POSSIBLE) - -#define CAMEL_SMTP_TRANSPORT_AUTH_EQUAL (1 << 6) /* set if we are using authtypes from a broken AUTH= */ - -typedef struct { - CamelTransport parent_object; - - CamelStream *istream, *ostream; - - guint32 flags; - - gboolean connected; - CamelTcpAddress *localaddr; - - GHashTable *authtypes; - -} CamelSmtpTransport; - - - -typedef struct { - CamelTransportClass parent_class; - -} CamelSmtpTransportClass; - - -/* Standard Camel function */ -CamelType camel_smtp_transport_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SMTP_TRANSPORT_H */ - - diff --git a/camel/providers/smtp/libcamelsmtp.urls b/camel/providers/smtp/libcamelsmtp.urls deleted file mode 100644 index ec2fc0fc16..0000000000 --- a/camel/providers/smtp/libcamelsmtp.urls +++ /dev/null @@ -1 +0,0 @@ -smtp diff --git a/camel/tests/.cvsignore b/camel/tests/.cvsignore deleted file mode 100644 index fd6b811c68..0000000000 --- a/camel/tests/.cvsignore +++ /dev/null @@ -1,7 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la diff --git a/camel/tests/Makefile.am b/camel/tests/Makefile.am deleted file mode 100644 index e32f2e455f..0000000000 --- a/camel/tests/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ - -SUBDIRS = lib \ - message folder stream smime misc mime-filter diff --git a/camel/tests/README b/camel/tests/README deleted file mode 100644 index 6815330102..0000000000 --- a/camel/tests/README +++ /dev/null @@ -1,44 +0,0 @@ - -This directory is to contain regression tests that should be run -before committing anything to camel. - -In each subdirectory of tests there is a README containing a -one-line description of each test file. This README must be kept -uptodate. - -To write a new test: copy an existing one and replace the contents. - -See camel-test.h for a number of functions and macros which setup and -define the test environmet, and help provide meaningful messages when -something actually fails. - -All tests have the following options: - -v[vvvv] - verbose. more v's more verbose. 2 v's will give you - a simple test backtrace of any partially failed tests. - No v's give you a simple backtrace of any failed tests. - -q - quiet. Dont print anything, unless there is a SEGV. - -See the other files in lib/* for utility functions that help to -write the tests (object comparison, creation, etc functions). - -Tests may fail and be non-fatal. In this case, you will see "Partial -success" on the result of each test line. To get more information -about the test, run the test manually with a -v command line argument. -The more v's you have the more detail you get (upto about -vvvvv), -generally use -vv to find out which parts of a partially successful -test failed, and where. - -Note that if writing tests, non-fatal tests (bracketed by a -camel_test_nonfatal() and camel_test_fatal() pair) should only be -defined where: 1. The test in question should ideally pass, and 2. The -code has known limitations currently that stop it passing, but -otherwise works for nominal input. - -To debug tests, set a breakpoint on camel_test_fail, which will be -called for any failure, even a non-fatal one. Or set it to -camel_test_break, which will only be called for fatal errors which are -to print to the screen. - - Michael diff --git a/camel/tests/data/camel-test.gpg.pub b/camel/tests/data/camel-test.gpg.pub deleted file mode 100644 index fdf28a59bd..0000000000 --- a/camel/tests/data/camel-test.gpg.pub +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.0.7 (GNU/Linux) - -mQGiBD8qsjARBACkS39GA1e6pDUumC9sQyZaE2PEZW6VEHMGQ9IlJ/Qi2wJBFKgl -Myl2Cko9Rpj2DmgGkBnoL6fPJNM9aCV0RvclvE15EViURU7mjYzF41uspvVMBg7b -y3cwAzkkgyhLc/V0Inzm9UpJZ6JvrqYO5OvJUA+ka5SHrhuX4ptmjKLjNwCgwNCx -CQHx9RIbPggYtfci1w9npm8D/3vks1q+G9r91JkRBqGTboBZ7HI1yU2tHJ38wsKp -kamloFr3j0hmN0s5PY4wgz4daJ120yTmweJQfIljcN2+aHeI5838u7f3Wk5LJtLG -+0xKBpBeejzqT/FzhxLIOoQl3L8aF+KAY+Oz7Bm/J/5MRPEPdxWGIB1LhnkoDP5F -5szGA/9POpFU7y34ACid5Grzk77LUVyHMGob+vgqoVITfCNGjfGf7tnXn1LlRf6N -TE81p1vYDz2K4bpPmOgBXuESmpaTfXvlDy6oW7buslFqgddm/MfzzM0wC2jdx5TV -NdNApku4PKA4pE2oTSg5EuGgxQLjJG/PHkoiRiK6yG8gign8vrQbTm8gVXNlciA8 -bm8udXNlckBuby5kb21haW4+iFkEExECABkFAj8qsjAECwcDAgMVAgMDFgIBAh4B -AheAAAoJEOvMhgJ6QMoGIQcAoIweyKELWnksPUk5mmZz26JFsmQVAJ9aTm+OO289 -+fdwq95xw/6KH2dEtrkBDQQ/KrIxEAQA26Y+QRaR7RymzyUW7MQlDbshD/vInLtb -36FusuOWzL5TgYn6fiiu/e/J+qjZO5psucWelnBIbnLTZZJs06EgybLPCeEP34X7 -cSsAPZ2JE+TKPM93pxpQpRdWKhv+ocjJ4xPlwI8LTrQIHKxB3yF2WNCh/TQDi0hm -6ktEi2RVusMAAwUD/3Wp0UbJ2/bgM9wOMAD8celvbl9V/L+9/UVBJrw4tH87FMZi -NMNg13TbMrARqJjdpOoHzozMv1GOumC5sE8A0/pwbIdU9oSYA07D3+02dCQq+52a -qtCGJoRq5okccQelRcs0cZIy/z5lzwsNnbshrmnqNdmuVf7BSdw7DjoFj5OLiEYE -GBECAAYFAj8qsjEACgkQ68yGAnpAygZaCgCfZu68SOUfcUZC3CWi4ITBvcKGvmUA -n1wrC5ZGv0SIRo5G1PswsKRZuEpl -=SWoX ------END PGP PUBLIC KEY BLOCK----- diff --git a/camel/tests/data/camel-test.gpg.sec b/camel/tests/data/camel-test.gpg.sec deleted file mode 100644 index f2af11e82e..0000000000 --- a/camel/tests/data/camel-test.gpg.sec +++ /dev/null @@ -1,33 +0,0 @@ ------BEGIN PGP PRIVATE KEY BLOCK----- -Version: GnuPG v1.0.7 (GNU/Linux) - -lQHhBD8qsjARBACkS39GA1e6pDUumC9sQyZaE2PEZW6VEHMGQ9IlJ/Qi2wJBFKgl -Myl2Cko9Rpj2DmgGkBnoL6fPJNM9aCV0RvclvE15EViURU7mjYzF41uspvVMBg7b -y3cwAzkkgyhLc/V0Inzm9UpJZ6JvrqYO5OvJUA+ka5SHrhuX4ptmjKLjNwCgwNCx -CQHx9RIbPggYtfci1w9npm8D/3vks1q+G9r91JkRBqGTboBZ7HI1yU2tHJ38wsKp -kamloFr3j0hmN0s5PY4wgz4daJ120yTmweJQfIljcN2+aHeI5838u7f3Wk5LJtLG -+0xKBpBeejzqT/FzhxLIOoQl3L8aF+KAY+Oz7Bm/J/5MRPEPdxWGIB1LhnkoDP5F -5szGA/9POpFU7y34ACid5Grzk77LUVyHMGob+vgqoVITfCNGjfGf7tnXn1LlRf6N -TE81p1vYDz2K4bpPmOgBXuESmpaTfXvlDy6oW7buslFqgddm/MfzzM0wC2jdx5TV -NdNApku4PKA4pE2oTSg5EuGgxQLjJG/PHkoiRiK6yG8gign8vv4DAwJKsiNZxDAs -LGBFwzjlfD8Wpo+OQQSuw8kHCJRhMpjBlkWYXuAIXrPVJBZmr3hYQbaL413EFp0w -DeQUzP0mIzpEU0FfZmFjdG9yOgAAr2ShZqfqP4RkV02MsarSDNg/K9RXc5f9JiM6 -RFNBX2ZhY3RvcjoAAK9F/Ldv8ksX8Ns3uqh8GEEDq88XZIeh/SYjOkRTQV9mYWN0 -b3I6AACvaOM+Tasvvj5+aQ3E44IHW8xzeXdM5bQbTm8gVXNlciA8bm8udXNlckBu -by5kb21haW4+iFkEExECABkFAj8qsjAECwcDAgMVAgMDFgIBAh4BAheAAAoJEOvM -hgJ6QMoGIQcAniz8Z+AESmwwrtQpllkLWaXQhkNMAJ4yqLAKSsfimKf3BDjxUzJ5 -6RKTE50BVwQ/KrIxEAQA26Y+QRaR7RymzyUW7MQlDbshD/vInLtb36FusuOWzL5T -gYn6fiiu/e/J+qjZO5psucWelnBIbnLTZZJs06EgybLPCeEP34X7cSsAPZ2JE+TK -PM93pxpQpRdWKhv+ocjJ4xPlwI8LTrQIHKxB3yF2WNCh/TQDi0hm6ktEi2RVusMA -AwUD/3Wp0UbJ2/bgM9wOMAD8celvbl9V/L+9/UVBJrw4tH87FMZiNMNg13TbMrAR -qJjdpOoHzozMv1GOumC5sE8A0/pwbIdU9oSYA07D3+02dCQq+52aqtCGJoRq5okc -cQelRcs0cZIy/z5lzwsNnbshrmnqNdmuVf7BSdw7DjoFj5OL/gMDAkqyI1nEMCws -YMk7XUGj7+BY1uyYyNpYp50F52HFsGXEffiKYPGIuybuP+Yz3ic4W9aQTJJPcIJg -ZqUP9b14WfY4mgIm1Tz9JiM6RUxHX2ZhY3RvcjoAAKsH4JdVQugM+lGnuNuGoj7I -V8O8bIsP/SYjOkVMR19mYWN0b3I6AACrBzvFd1NLrbYGMjsN3SKhgBtuHjGQx/0m -IzpFTEdfZmFjdG9yOgAAqwR77L22dgo/dV8XO8NThXMbEmQgoY39JiM6RUxHX2Zh -Y3RvcjoAAKsFRPzjSodiTFMeiwWHgpdgf4e2qzEN/SYjOkVMR19mYWN0b3I6AACr -BX9hqiLZJKfgpo/hs/0wK8yHq6GXh4hGBBgRAgAGBQI/KrIxAAoJEOvMhgJ6QMoG -WgoAoKwAHwpedO9qQNBu0REM1jNR9PuuAJ9ZtHyuOiziV/JageUT+hZ8s27U3A== -=xLRp ------END PGP PRIVATE KEY BLOCK----- diff --git a/camel/tests/data/gendoc.pl b/camel/tests/data/gendoc.pl deleted file mode 100755 index 732f05a4ed..0000000000 --- a/camel/tests/data/gendoc.pl +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/perl - -# Generate 'documents' in different encodings, from po files - -if ($#ARGV < 0) { - print "Usage: gendoc.pl pofile pofile ...\n"; - exit 1; -} - -$fmt = "| fmt -u "; - -sub read_msgstr() -{ - my $str = ""; - while () { - if (m/^msgstr \"(.*)\"/) { - $str = $1; - if ($str eq "") { - while () { - if (m/\"(.*)\"/) { - $str .= $1; - } else { - last; - } - } - } - return $str; - } - } - return ""; -} - -$unknown = "x-unknown-1"; - -foreach $name (@ARGV) { - if ($name =~ m@([^/]*).po$@) { - $poname = $1; - - open IN,"<$name"; - - $header = read_msgstr; - if ($header =~ /Content-Type:.*charset=([-a-zA-Z0-9]*)/i) { - $charset = $1; - } else { - $charset = $unknown++; - } - - print "Building $poname.$charset.txt from $name\n"; - - open OUT,"$fmt > $poname.$charset.txt"; - while (!eof(IN)) { - $msg = read_msgstr; - # de-escape - $msg =~ s/\\n/\n/gso; - $msg =~ s/\\t/\t/gso; - $msg =~ s/\\(.)/$1/gso; - print OUT $msg." "; - } - close OUT; - close IN; - } else { - printf("ignoring $name, probably not intended\n"); - } -} - diff --git a/camel/tests/data/genline.pl b/camel/tests/data/genline.pl deleted file mode 100755 index 99ff43c882..0000000000 --- a/camel/tests/data/genline.pl +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/perl - -# Generate 'documents' in different encodings, from po files - -if ($#ARGV < 0) { - print "Usage: genline.pl pofile pofile ...\n"; - exit 1; -} - -sub read_msgstr() -{ - my $str = ""; - while () { - if (m/^msgstr \"(.*)\"/) { - $str = $1; - if ($str eq "") { - while () { - if (m/\"(.*)\"/) { - $str .= $1; - } else { - last; - } - } - } - return $str; - } - } - return ""; -} - -$unknown = "x-unknown-1"; -open OUT, ">test-lines.h"; - -print OUT < 60 && length($msg) < 160) { - print OUT "\t{ \"$charset\", \"$msg\" },\n"; - last; - } -# $msg =~ s/\\n/\n/gso; -# $msg =~ s/\\t/\t/gso; -# $msg =~ s/\\(.)/$1/gso; -# print OUT $msg." "; - } - close IN; - } else { - printf("ignoring $name, probably not intended\n"); - } -} - -print OUT "};\n"; -close OUT; diff --git a/camel/tests/data/getaddr.pl b/camel/tests/data/getaddr.pl deleted file mode 100755 index 74a8a81f74..0000000000 --- a/camel/tests/data/getaddr.pl +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/perl - -# get addresses out of messages - -if ($#ARGV < 0) { - print "Usage: $0 message(s) mbox(es)\n"; - exit 1; -} - -foreach $name (@ARGV) { - open IN,"<$name"; - while () { - if (/^From: (.*)/i - || /^To: (.*)/i - || /^Cc: (.*)/i) { - $base = $1; - while () { - if (/^\s+(.*)/) { - $base .= " ".$1; - } else { - last; - } - } - $uniq{$base} = 1; - } - } - close IN; -} - -foreach $key (sort keys %uniq) { - print $key."\n"; -} diff --git a/camel/tests/data/messages/.cvsignore b/camel/tests/data/messages/.cvsignore deleted file mode 100644 index e358dd1903..0000000000 --- a/camel/tests/data/messages/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -*.msg diff --git a/camel/tests/folder/.cvsignore b/camel/tests/folder/.cvsignore deleted file mode 100644 index 26eaf2f7e1..0000000000 --- a/camel/tests/folder/.cvsignore +++ /dev/null @@ -1,21 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -temp-test -*.bb -*.bbg -*.da -*.gcov -test1 -test2 -test3 -test4 -test5 -test6 -test7 -test8 -test9 diff --git a/camel/tests/folder/Makefile.am b/camel/tests/folder/Makefile.am deleted file mode 100644 index e49fd92a87..0000000000 --- a/camel/tests/folder/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ - -INCLUDES = \ - -I$(includedir) \ - -I$(top_srcdir) \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/camel/tests/lib \ - -DG_LOG_DOMAIN=\"evolution-tests\" \ - $(CAMEL_CFLAGS) - -LDADD = \ - $(top_builddir)/camel/libcamel.la \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/camel/tests/lib/libcameltest.a \ - $(INTLLIBS) \ - $(EVOLUTION_MAIL_LIBS) - -check_PROGRAMS = \ - test1 test2 test3 \ - test4 test5 test6 \ - test7 test8 test9 \ - test10 - -TESTS = test1 test2 test3 \ - test4 test5 test6 \ - test7 test8 test9 \ - test10 diff --git a/camel/tests/folder/README b/camel/tests/folder/README deleted file mode 100644 index 3ab64ecd1c..0000000000 --- a/camel/tests/folder/README +++ /dev/null @@ -1,12 +0,0 @@ - -test1 camel store folder operations (local only) -test2 basic folder operations, local -test3 folder searching and indexing, local -test4 camel store folder operations, IMAP -test5 camel store folder operations, NNTP -test6 basic folder operations, IMAP -test7 basic folder operations, NNTP - -test8 multithreaded folder torture test, local -test9 filtering -test10 multithreaded folder/store object bag torture test diff --git a/camel/tests/folder/test1.c b/camel/tests/folder/test1.c deleted file mode 100644 index c1d3809852..0000000000 --- a/camel/tests/folder/test1.c +++ /dev/null @@ -1,50 +0,0 @@ -/* store testing */ - -#include "camel-test.h" -#include "folders.h" -#include "session.h" - -#include -#include -#include - -#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) - -static char *local_providers[] = { - "mbox", - "mh", - "maildir" -}; - -int main(int argc, char **argv) -{ - CamelSession *session; - CamelException *ex; - int i; - char *path; - - camel_test_init(argc, argv); - - ex = camel_exception_new(); - - /* clear out any camel-test data */ - system("/bin/rm -rf /tmp/camel-test"); - - session = camel_test_session_new ("/tmp/camel-test"); - - /* todo: cross-check everything with folder_info checks as well */ - /* todo: subscriptions? */ - /* todo: work out how to do imap/pop/nntp tests */ - for (i=0;i -#include - -#include "camel-test.h" -#include "folders.h" -#include "messages.h" -#include "session.h" - -#include -#include -#include - -#define MAX_LOOP (10000) -#define MAX_THREADS (5) - -#define d(x) - -#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) - -static char *local_providers[] = { - "mbox", - "mh", - "maildir" -}; - -static char *path; -static CamelSession *session; -static int testid; - -static void * -worker(void *d) -{ - int i; - CamelException *ex = camel_exception_new(); - CamelStore *store; - CamelFolder *folder; - - for (i=0;i -#include -#include - -#include "camel-test.h" -#include "messages.h" -#include "folders.h" -#include "session.h" - -#include -#include -#include - -#include -#include -#include - -#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) - -static char *stores[] = { - "mbox:///tmp/camel-test/mbox", - "mh:///tmp/camel-test/mh", - "maildir:///tmp/camel-test/maildir" -}; - -int main(int argc, char **argv) -{ - CamelSession *session; - CamelException *ex; - int i; - - camel_test_init(argc, argv); - - /* clear out any camel-test data */ - system("/bin/rm -rf /tmp/camel-test"); - - ex = camel_exception_new(); - - session = camel_test_session_new ("/tmp/camel-test"); - - /* we iterate over all stores we want to test, with indexing or indexing turned on or off */ - for (i=0;i - -#include - -#include "camel-test.h" -#include "messages.h" -#include "folders.h" -#include "session.h" - -#include -#include -#include - -#include -#include -#include - -#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) - -static void -test_folder_search_sub(CamelFolder *folder, const char *expr, int expected) -{ - CamelException *ex = camel_exception_new(); - GPtrArray *uids; - GHashTable *hash; - int i; - - uids = camel_folder_search_by_expression(folder, expr, ex); - check(uids != NULL); - check_msg(uids->len == expected, "search %s expected %d got %d", expr, expected, uids->len); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - - /* check the uid's are actually unique, too */ - hash = g_hash_table_new(g_str_hash, g_str_equal); - for (i=0;ilen;i++) { - check(g_hash_table_lookup(hash, uids->pdata[i]) == NULL); - g_hash_table_insert(hash, uids->pdata[i], uids->pdata[i]); - } - g_hash_table_destroy(hash); - - camel_folder_search_free(folder, uids); - - camel_exception_free(ex); -} - -static void -test_folder_search(CamelFolder *folder, const char *expr, int expected) -{ - char *matchall; - -#if 0 - /* FIXME: ??? */ - camel_test_nonfatal("most searches require match-all construct"); - push("Testing search: %s", expr); - test_folder_search_sub(folder, expr, expected); - pull(); - camel_test_fatal(); -#endif - - matchall = g_strdup_printf("(match-all %s)", expr); - push("Testing search: %s", matchall); - test_folder_search_sub(folder, matchall, expected); - test_free(matchall); - pull(); -} - -static struct { - int counts[3]; - char *expr; -} searches[] = { - { { 1, 1, 0 }, "(header-matches \"subject\" \"Test1 message99 subject\")" }, - - { { 100, 50, 0 }, "(header-contains \"subject\" \"subject\")" }, - { { 100, 50, 0 }, "(header-contains \"subject\" \"Subject\")" }, - - { { 100, 50, 0 }, "(body-contains \"content\")" }, - { { 100, 50, 0 }, "(body-contains \"Content\")" }, - - { { 0, 0, 0 }, "(user-flag \"every7\")" }, - { { 100/13+1, 50/13+1, 0 }, "(user-flag \"every13\")" }, - { { 1, 1, 0 }, "(= \"7tag1\" (user-tag \"every7\"))" }, - { { 100/11+1, 50/11+1, 0 }, "(= \"11tag\" (user-tag \"every11\"))" }, - - { { 100/13 + 100/17 + 1, 50/13 + 50/17 + 2, 0 }, "(user-flag \"every13\" \"every17\")" }, - { { 100/13 + 100/17 + 1, 50/13 + 50/17 + 2, 0 }, "(or (user-flag \"every13\") (user-flag \"every17\"))" }, - { { 1, 0, 0 }, "(and (user-flag \"every13\") (user-flag \"every17\"))" }, - - { { 0, 0, 0 }, "(and (header-contains \"subject\" \"Test1\") (header-contains \"subject\" \"Test2\"))" }, - /* we get 11 here as the header-contains is a substring match */ - { { 11, 6, 0 }, "(and (header-contains \"subject\" \"Test1\") (header-contains \"subject\" \"subject\"))" }, - { { 1, 1, 0 }, "(and (header-contains \"subject\" \"Test19\") (header-contains \"subject\" \"subject\"))" }, - { { 0, 0, 0 }, "(and (header-contains \"subject\" \"Test191\") (header-contains \"subject\" \"subject\"))" }, - { { 1, 1, 0 }, "(and (header-contains \"subject\" \"Test1\") (header-contains \"subject\" \"message99\"))" }, - - { { 22, 11, 0 }, "(or (header-contains \"subject\" \"Test1\") (header-contains \"subject\" \"Test2\"))" }, - { { 2, 1, 0 }, "(or (header-contains \"subject\" \"Test16\") (header-contains \"subject\" \"Test99\"))" }, - { { 1, 1, 0 }, "(or (header-contains \"subject\" \"Test123\") (header-contains \"subject\" \"Test99\"))" }, - { { 100, 50, 0 }, "(or (header-contains \"subject\" \"Test1\") (header-contains \"subject\" \"subject\"))" }, - { { 11, 6, 0 }, "(or (header-contains \"subject\" \"Test1\") (header-contains \"subject\" \"message99\"))" }, - - /* 72000 is 24*60*100 == half the 'sent date' of the messages */ - { { 100/2, 50/2, 0 }, "(> 72000 (get-sent-date))" }, - { { 100/2-1, 50/2, 0 }, "(< 72000 (get-sent-date))" }, - { { 1, 0, 0 }, "(= 72000 (get-sent-date))" }, - { { 0, 0, 0 }, "(= 72001 (get-sent-date))" }, - - { { (100/2-1)/17+1, (50/2-1)/17+1, 0 }, "(and (user-flag \"every17\") (< 72000 (get-sent-date)))" }, - { { (100/2-1)/17+1, (50/2-1)/17, 0 }, "(and (user-flag \"every17\") (> 72000 (get-sent-date)))" }, - { { (100/2-1)/13+1, (50/2-1)/13+1, 0 }, "(and (user-flag \"every13\") (< 72000 (get-sent-date)))" }, - { { (100/2-1)/13+1, (50/2-1)/13+1, 0 }, "(and (user-flag \"every13\") (> 72000 (get-sent-date)))" }, - - { { 100/2+100/2/17, 50/2+50/2/17, 0 }, "(or (user-flag \"every17\") (< 72000 (get-sent-date)))" }, - { { 100/2+100/2/17+1, 50/2+50/2/17+1, 0 }, "(or (user-flag \"every17\") (> 72000 (get-sent-date)))" }, - { { 100/2+100/2/13, 50/2+50/2/13+1, 0 }, "(or (user-flag \"every13\") (< 72000 (get-sent-date)))" }, - { { 100/2+100/2/13+1, 50/2+50/2/13+1, 0 }, "(or (user-flag \"every13\") (> 72000 (get-sent-date)))" }, -}; - -static void -run_search(CamelFolder *folder, int m) -{ - int i, j = 0; - - check(m == 50 || m == 100 || m == 0); - - /* *shrug* messy, but it'll do */ - if (m==50) - j = 1; - else if (m==0) - j = 2; - - push("performing searches, expected %d", m); - for (i=0;ilen == 100); - for (j=0;j<100;j++) { - char *uid = uids->pdata[j]; - - if ((j/13)*13 == j) { - camel_folder_set_message_user_flag(folder, uid, "every13", TRUE); - } - if ((j/17)*17 == j) { - camel_folder_set_message_user_flag(folder, uid, "every17", TRUE); - } - if ((j/7)*7 == j) { - char *tag = g_strdup_printf("7tag%d", j/7); - camel_folder_set_message_user_tag(folder, uid, "every7", tag); - test_free(tag); - } - if ((j/11)*11 == j) { - camel_folder_set_message_user_tag(folder, uid, "every11", "11tag"); - } - } - camel_folder_free_uids(folder, uids); - pull(); - - camel_test_nonfatal("Index not guaranteed to be accurate before sync: should be fixed eventually"); - push("Search before sync"); - run_search(folder, 100); - pull(); - camel_test_fatal(); - - push("syncing folder, searching"); - camel_folder_sync(folder, FALSE, ex); - run_search(folder, 100); - pull(); - - push("syncing wiht expunge, search"); - camel_folder_sync(folder, TRUE, ex); - run_search(folder, 100); - pull(); - - push("deleting every 2nd message"); - uids = camel_folder_get_uids(folder); - check(uids->len == 100); - for (j=0;jlen;j+=2) { - camel_folder_delete_message(folder, uids->pdata[j]); - } - camel_folder_free_uids(folder, uids); - run_search(folder, 100); - - push("syncing"); - camel_folder_sync(folder, FALSE, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - run_search(folder, 100); - pull(); - - push("expunging"); - camel_folder_expunge(folder, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - run_search(folder, 50); - pull(); - - pull(); - - push("closing and re-opening folder"); - check_unref(folder, 1); - folder = camel_store_get_folder(store, "testbox", flags&~(CAMEL_STORE_FOLDER_CREATE), ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - check(folder != NULL); - - push("deleting remaining messages"); - uids = camel_folder_get_uids(folder); - check(uids->len == 50); - for (j=0;jlen;j++) { - camel_folder_delete_message(folder, uids->pdata[j]); - } - camel_folder_free_uids(folder, uids); - run_search(folder, 50); - - push("syncing"); - camel_folder_sync(folder, FALSE, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - run_search(folder, 50); - pull(); - - push("expunging"); - camel_folder_expunge(folder, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - run_search(folder, 0); - pull(); - - pull(); - - check_unref(folder, 1); - pull(); - - push("deleting test folder, with no messages in it"); - camel_store_delete_folder(store, "testbox", ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - pull(); - - check_unref(store, 1); - camel_test_end(); - } - } - - check_unref(session, 1); - camel_exception_free(ex); - - return 0; -} diff --git a/camel/tests/folder/test4.c b/camel/tests/folder/test4.c deleted file mode 100644 index e6c58e023d..0000000000 --- a/camel/tests/folder/test4.c +++ /dev/null @@ -1,53 +0,0 @@ -/* store testing, for remote folders */ - -#include "camel-test.h" -#include "folders.h" -#include "session.h" - -#include -#include -#include - -#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) - -static char *remote_providers[] = { - "IMAP_TEST_URL", -}; - -int main(int argc, char **argv) -{ - CamelSession *session; - CamelException *ex; - int i; - char *path; - - camel_test_init(argc, argv); - - ex = camel_exception_new(); - - /* clear out any camel-test data */ - system("/bin/rm -rf /tmp/camel-test"); - - session = camel_test_session_new ("/tmp/camel-test"); - - /* todo: cross-check everything with folder_info checks as well */ - /* todo: subscriptions? */ - for (i=0;i -#include -#include - -#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) - -static char *remote_providers[] = { - "NNTP_TEST_URL", -}; - -int main(int argc, char **argv) -{ - CamelSession *session; - CamelException *ex; - int i; - char *path; - - camel_test_init(argc, argv); - - ex = camel_exception_new(); - - /* clear out any camel-test data */ - system("/bin/rm -rf /tmp/camel-test"); - - session = camel_test_session_new ("/tmp/camel-test"); - - /* todo: cross-check everything with folder_info checks as well */ - /* todo: subscriptions? */ - for (i=0;i -#include -#include - -#include -#include -#include - -#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) - -static char *remote_providers[] = { - "IMAP_TEST_URL", -}; - -int main(int argc, char **argv) -{ - CamelSession *session; - CamelException *ex; - int i; - char *path; - - camel_test_init(argc, argv); - - /* clear out any camel-test data */ - system("/bin/rm -rf /tmp/camel-test"); - - ex = camel_exception_new(); - - session = camel_test_session_new ("/tmp/camel-test"); - - for (i=0;i -#include -#include - -#include -#include -#include - -#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) - -static char *remote_providers[] = { - "NNTP_TEST_URL", -}; - -int main(int argc, char **argv) -{ - CamelSession *session; - CamelException *ex; - int i; - char *path; - - camel_test_init(argc, argv); - - /* clear out any camel-test data */ - system("/bin/rm -rf /tmp/camel-test"); - - ex = camel_exception_new(); - - session = camel_test_session_new ("/tmp/camel-test"); - - for (i=0;i -#include - -#include "camel-test.h" -#include "folders.h" -#include "messages.h" -#include "session.h" - -#include -#include -#include - -#define MAX_MESSAGES (100) -#define MAX_THREADS (10) - -#define d(x) - -#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) - -static char *local_providers[] = { - "mbox", - "mh", - "maildir" -}; - -static void -test_add_message(CamelFolder *folder, int j) -{ - CamelMimeMessage *msg; - char *content; - char *subject; - CamelException ex; - - camel_exception_init(&ex); - - push("creating message %d\n", j); - msg = test_message_create_simple(); - content = g_strdup_printf("Test message %08x contents\n\n", j); - test_message_set_content_simple((CamelMimePart *)msg, 0, "text/plain", - content, strlen(content)); - test_free(content); - subject = g_strdup_printf("Test message %08x subject", j); - camel_mime_message_set_subject(msg, subject); - pull(); - - push("appending simple message %d", j); - camel_folder_append_message(folder, msg, NULL, NULL, &ex); - check_msg(!camel_exception_is_set(&ex), "%s", camel_exception_get_description(&ex)); - pull(); - - check_unref(msg, 1); -} - -struct _threadinfo { - int id; - CamelFolder *folder; -}; - -static void * -worker(void *d) -{ - struct _threadinfo *info = d; - int i, j, id = info->id; - char *sub, *content; - GPtrArray *res; - CamelException *ex = camel_exception_new(); - CamelMimeMessage *msg; - - /* we add a message, search for it, twiddle some flags, delete it */ - /* and flat out */ - for (i=0;ifolder, id+i); - - sub = g_strdup_printf("(match-all (header-contains \"subject\" \"message %08x subject\"))", id+i); - - push("searching for message %d\n\tusing: %s", id+i, sub); - res = camel_folder_search_by_expression(info->folder, sub, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - check_msg(res->len == 1, "res->len = %d", res->len); - pull(); - - push("getting message '%s'", res->pdata[0]); - msg = camel_folder_get_message(info->folder, (char *)res->pdata[0], ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - pull(); - - content = g_strdup_printf("Test message %08x contents\n\n", id+i); - push("comparing content '%s': '%s'", res->pdata[0], content); - test_message_compare_content(camel_medium_get_content_object((CamelMedium *)msg), content, strlen(content)); - test_free(content); - pull(); - - push("deleting message, cleanup"); - j=(100.0*rand()/(RAND_MAX+1.0)); - if (j<=70) { - camel_folder_delete_message(info->folder, res->pdata[0]); - } - - camel_folder_search_free(info->folder, res); - res = NULL; - test_free(sub); - - check_unref(msg, 1); - pull(); - - /* about 1-in 100 calls will expunge */ - j=(200.0*rand()/(RAND_MAX+1.0)); - if (j<=2) { - d(printf("Forcing an expuge\n")); - push("expunging folder"); - camel_folder_expunge(info->folder, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - pull(); - } - } - - camel_exception_free(ex); - - return info; -} - -int main(int argc, char **argv) -{ - CamelSession *session; - CamelException *ex; - int i, j, index; - char *path; - CamelStore *store; - pthread_t threads[MAX_THREADS]; - struct _threadinfo *info; - CamelFolder *folder; - GPtrArray *uids; - - camel_test_init(argc, argv); - - ex = camel_exception_new(); - - /* clear out any camel-test data */ - system("/bin/rm -rf /tmp/camel-test"); - - session = camel_test_session_new ("/tmp/camel-test"); - - for (j=0;jid = i*MAX_MESSAGES; - info->folder = folder; - pthread_create(&threads[i], 0, worker, info); - } - - for (i=0;ilen;i++) { - camel_folder_delete_message(folder, uids->pdata[i]); - } - camel_folder_free_uids(folder, uids); - - camel_folder_expunge(folder, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - - check_unref(folder, 1); - - camel_store_delete_folder(store, "testbox", ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - - check_unref(store, 1); - - pull(); - - camel_test_end(); - } - } - - camel_object_unref((CamelObject *)session); - camel_exception_free(ex); - - return 0; -} diff --git a/camel/tests/folder/test9.c b/camel/tests/folder/test9.c deleted file mode 100644 index 79d34c76a5..0000000000 --- a/camel/tests/folder/test9.c +++ /dev/null @@ -1,229 +0,0 @@ -/* folder/index testing */ - -#include - -#include "camel-test.h" -#include "messages.h" -#include "folders.h" -#include "session.h" - -#include "camel/camel-exception.h" -#include "camel/camel-service.h" -#include "camel/camel-store.h" - -#include "camel/camel-folder.h" -#include "camel/camel-folder-summary.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-filter-driver.h" -#include "camel/camel-stream-fs.h" - -#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) - -struct { - char *name; - CamelFolder *folder; -} mailboxes[] = { - { "INBOX", NULL }, - { "folder1", NULL }, - { "folder2", NULL }, - { "folder3", NULL }, - { "folder4", NULL }, -}; - -struct { - char *name, *match, *action; -} rules[] = { - { "empty1", "(match-all (header-contains \"Frobnitz\"))", "(copy-to \"folder1\")" }, - { "empty2", "(header-contains \"Frobnitz\")", "(copy-to \"folder2\")" }, - { "count11", "(and (header-contains \"subject\" \"Test1\") (header-contains \"subject\" \"subject\"))", "(move-to \"folder3\")" }, - { "empty3", "(and (header-contains \"subject\" \"Test1\") (header-contains \"subject\" \"subject\"))", "(move-to \"folder4\")" }, - { "count1", "(body-contains \"data50\")", "(copy-to \"folder1\")" }, - { "stop", "(body-contains \"data2\")", "(stop)" }, - { "notreached1", "(body-contains \"data2\")", "(move-to \"folder2\")" }, - { "count1", "(body-contains \"data3\")", "(move-to \"folder2\")" }, - { "ustrcasecmp", "(header-matches \"Subject\" \"Test0 message100 subject\")", "(copy-to \"folder2\")" }, -}; - -/* broken match rules */ -struct { - char *name, *match, *action; -} brokens[] = { - { "count1", "(body-contains data50)", "(copy-to \"folder1\")" }, /* non string argument */ - { "count1", "(body-contains-stuff \"data3\")", "(move-to-folder \"folder2\")" }, /* invalid function */ - { "count1", "(or (body-contains \"data3\") (foo))", "(move-to-folder \"folder2\")" }, /* invalid function */ - { "count1", "(or (body-contains \"data3\") (foo)", "(move-to-folder \"folder2\")" }, /* missing ) */ - { "count1", "(and body-contains \"data3\") (foo)", "(move-to-folder \"folder2\")" }, /* missing ( */ - { "count1", "body-contains \"data3\")", "(move-to-folder \"folder2\")" }, /* missing ( */ - { "count1", "body-contains \"data3\"", "(move-to-folder \"folder2\")" }, /* missing ( ) */ - { "count1", "(body-contains \"data3\" ())", "(move-to-folder \"folder2\")" }, /* extra () */ - { "count1", "()", "(move-to-folder \"folder2\")" }, /* invalid () */ - { "count1", "", "(move-to-folder \"folder2\")" }, /* empty */ -}; - -/* broken action rules */ -struct { - char *name, *match, *action; -} brokena[] = { - { "a", "(body-contains \"data2\")", "(body-contains \"help\")" }, /* rule in action */ - { "a", "(body-contains \"data2\")", "(move-to-folder-name \"folder2\")" }, /* unknown function */ - { "a", "(body-contains \"data2\")", "(or (move-to-folder \"folder2\")" }, /* missing ) */ - { "a", "(body-contains \"data2\")", "(or move-to-folder \"folder2\"))" }, /* missing ( */ - { "a", "(body-contains \"data2\")", "move-to-folder \"folder2\")" }, /* missing ( */ - { "a", "(body-contains \"data2\")", "(move-to-folder \"folder2\" ())" }, /* invalid () */ - { "a", "(body-contains \"data2\")", "()" }, /* invalid () */ - { "a", "(body-contains \"data2\")", "" }, /* empty */ -}; - -static CamelFolder *get_folder(CamelFilterDriver *d, const char *uri, void *data, CamelException *ex) -{ - int i; - - for (i=0;i", "David Gutiérrez Magallanes " }, - { 1, "\"=?iso-8859-1?Q?Jos=E9?= Antonio Milke G.\" ", "José Antonio Milke G. " }, - { 1, "\"=?iso-8859-2?Q?Hi-Fi_Internert_market_=3D_1.Virtu=E1ln=ED_Internetov=E9_H?= =?iso-8859-2?Q?i-Fi_Studio?=\" ", "Hi-Fi Internert market = 1.Virtuální Internetové Hi-Fi Studio " }, - { 3, "\"James M. Cape\" , =?iso-8859-1?Q?Joaqu=EDn_Cuenca_Abela?= , gnome-hackers@nuclecu.unam.mx", "James M. Cape , Joaquín Cuenca Abela , gnome-hackers@nuclecu.unam.mx" }, - { 1, "=?ISO-8859-1?Q?David_Guti=E9rrez_Magallanes?= ", "David Gutiérrez Magallanes " }, - { 1, "=?ISO-8859-2?Q?Tomasz_K=B3oczko?= ", "Tomasz Kłoczko " }, - { 1, "=?ISO-8859-2?Q?Vladim=EDr_Solnick=FD?= ", "Vladimír Solnický " }, - { 1, "=?iso-8859-1?Q?=22S=F6rensen=2C_Daniel=22?= ", "\"Sörensen, Daniel\" " }, - { 1, "=?iso-8859-1?Q?=C1=C2=AAQ=A7=CA?= ", "ÁªQ§Ê " }, - { 1, "=?iso-8859-1?Q?=C1=C2=AAQ=A7=CA?= ", "ÁªQ§Ê " }, - { 1, "=?iso-8859-1?Q?=C1kos?= Valentinyi ", "Ákos Valentinyi " }, - { 1, "=?iso-8859-1?Q?Joaqu=EDn?= Cuenca Abela ", "Joaquín Cuenca Abela " }, - { 2, "=?iso-8859-1?Q?Joaqu=EDn?= Cuenca Abela , gnome-hackers@nuclecu.unam.mx", "Joaquín Cuenca Abela , gnome-hackers@nuclecu.unam.mx" }, - { 1, "=?iso-8859-1?Q?Joaqu=EDn_Cuenca_Abela?= ", "Joaquín Cuenca Abela " }, - { 1, "=?iso-8859-1?Q?Juantom=E1s=20Garc=EDa?= ", "Juantomás García " }, - { 1, "=?iso-8859-1?Q?Kenneth_ll=E9phaane_Christiansen?= ", "Kenneth lléphaane Christiansen " }, - { 1, "=?iso-8859-1?Q?Kjell_Tage_=D8hman?= ", "Kjell Tage Øhman " }, - { 1, "=?iso-8859-1?Q?Martin_Norb=E4ck?= ", "Martin Norbäck " }, - { 1, "=?iso-8859-1?Q?P=E5llen?= ", "Pållen " }, - { 1, "=?iso-8859-1?Q?Ville_P=E4tsi?= ", "Ville Pätsi " }, - { 1, "=?iso-8859-1?q?Joaqu=EDn?= Cuenca Abela ", "Joaquín Cuenca Abela " }, - { 1, "=?iso-8859-2?Q?Dra=BEen_Ka=E8ar?= ", "Dražen Kačar " }, - /* yep this is right, this isn't valid so doesn't decode at all */ - { 1, "=?windows-1250?Q? \"Jaka Mo=E8nik\" ?= ", "=?windows-1250?Q? Jaka Mo=E8nik ?= " }, - { 3, "George , Juantomas =?ISO-8859-1?Q?Garc=C3=83=C2=ADa?= , gnome-hackers@gnome.org", "George , Juantomas García , gnome-hackers@gnome.org" }, - { 7, "Jon Trowbridge , gnome-1.4-list@gnome.org, gnome-devel-list@gnome.org, gnome-hackers@gnome.org, Dom Lachowicz , =?iso-8859-1?Q?Joaqu=EDn_Cuenca_Abela?= , sam th ", "Jon Trowbridge , gnome-1.4-list@gnome.org, gnome-devel-list@gnome.org, gnome-hackers@gnome.org, Dom Lachowicz , Joaquín Cuenca Abela , sam th " }, - { 6, "Jon Trowbridge , gnome-1.4-list@gnome.org, gnome-devel-list@gnome.org, gnome-hackers@gnome.org, Dom Lachowicz , =?iso-8859-1?Q?Joaqu=EDn_Cuenca_Abela?= ", "Jon Trowbridge , gnome-1.4-list@gnome.org, gnome-devel-list@gnome.org, gnome-hackers@gnome.org, Dom Lachowicz , Joaquín Cuenca Abela " }, - { 1, "Kai =?iso-8859-1?Q?Gro=DFjohann?= ", "Kai Großjohann " }, - { 1, "Kai.Grossjohann@CS.Uni-Dortmund.DE (Kai =?iso-8859-1?q?Gro=DFjohann?=)", "Kai Großjohann " }, - { 1, "Rickard =?iso-8859-1?Q?Nordstr=F6m?= ", "Rickard Nordström " }, - { 1, "Tomasz =?iso-8859-2?q?K=B3oczko?= ", "Tomasz Kłoczko " }, - { 1, "VALCKE =?iso-8859-1?Q?C=E9dric?= ", "VALCKE Cédric " }, - { 1, "Ville =?iso-8859-1?q?P=E4tsi?= ", "Ville Pätsi " }, - { 1, "david@iiia.csic.es (=?ISO-8859-1?Q?David_Guti=E9rrez_Magallanes?=)", "David Gutiérrez Magallanes " }, - { 1, "kloczek@rudy.mif.pg.gda.pl (=?ISO-8859-2?Q?Tomasz_K=B3oczko?=)", "Tomasz Kłoczko " }, - { 1, "lassehp@imv.aau.dk (Lasse =?ISO-8859-1?Q?Hiller=F8e?= Petersen)", "Lasse Hillerøe Petersen " }, - { 1, "ysato@etl.go.jp (Yutaka Sato =?ISO-2022-JP?B?GyRAOjRGI0stGyhK?=)", "Yutaka Sato 佐藤豊 " }, -}; - -static struct _l { - char *type; - char *line; -} test_lines[] = { - /* commented out unsupported charsets - FIXME: camel should somehow handle this, although it can't really of course */ - /*{ "windows-1251", " .\n ?" },*/ - { "iso-8859-1", "Omple les miniatures de la finestra amb contingut de la pantalla" }, - { "ISO-8859-2", "Sprvce oken hbe s okrajem okna\n(AfterStep, Enlightenment, FVWM, IceWM, Sawmill)" }, - { "ISO-8859-1", "Vindueshndtering flytter dekorationsvindue istedet\n(AfterStep, Enlightenment, FVWM, IceWM, Sawfish)" }, - { "ISO-8859-1", "Vorschaubilder der Fenster mit dem Bildschirminhalt ausfllen" }, - { "iso-8859-7", " (-)" }, - { "iso-8859-1", "You've chosen to disable the startup hint.\nTo re-enable it, choose \"Startup Hint\"\nin the GNOME Control Centre" }, - { "iso-8859-1", "El aplique de reloj muestra en su panel la fecha y la hora de forma simple \ny ligero " }, - { "iso-8859-1", "Applet ei vasta salvestusksule.\nKas peaks ta niisama sulgema, vi veel ootama?" }, - { "iso-8859-1", "Lehio kudeatzaileak lehioaren dekorazaioa mugiarazten\n(AfterStep, Enlightenment, FVWM, IceWM, Sawmill)" }, - { "iso-8859-15", "Nyt sovellukset, joiden ikkunoista on nkyvill vain otsikkopalkki" }, - { "ISO-8859-1", "Afficher les tches qui ne sont pas dans la liste des fentres" }, - { "iso-8859-1", "Nl applet ag tabhair freagra ar iarratas sbhil.\nBain amach an applet n lean ar fnacht?" }, - { "iso-8859-1", "Amosa-las tarefas agochadas da lista de fiestras (SKIP-WINLIST)" }, - { "iso-8859-2", "Az ablakkezel a dekorcit mozgassa az ablak helyett\n(AfterStep, Enlightenment, FVWM, IceWM, SawMill)" }, - { "iso-8859-1", "Riempi la finestra delle anteprime con il contenuto dello schermo" }, - { "euc-jp", "ɥޥ͡Ͼꥦɥư\n(AfterStep, Enlightenment, FVWM, IceWM, Sawfish)" }, - { "euc-kr", "â ڰ ٹ â ̵\n(AfterStep, Enlightenment, FVWM, IceWM, Sawmill)" }, - { "iso-8859-13", "Priedas neatsakinja praym isisaugoti.\nPaalinti pried ar laukti toliau?" }, - { "iso-8859-1", "Window manager verplaatst dekoratie\n(AfterStep, Enlightenment, FVWM, IceWM, Sawmill)" }, - { "iso-8859-1", "Vindushndtereren flytter dekorasjonsvinduet i stedet\n(AfterStep, Enlightenment, FVWM, IceWM, Sawfish)" }, - { "iso-8859-2", "Przemieszczanie dekoracji zamiast okna\n(AfterStep, Enlightenment, FVWM, IceWM, Sawmill)" }, - { "iso-8859-1", "Este programa responsvel por executar outras aplicaes, embeber pequenos applets, a paz no mundo e crashes aleatrios do X." }, - { "iso-8859-1", "Mostrar tarefas que se escondem da lista de janelas (SKIP-WINLIST)" }, - { "koi8-r", " " }, - { "iso-8859-2", "Sprvca okien presva okraje okien\n(AfterStep, Enlightenment, FVWM, IceWM, Sawfish)" }, - { "iso-8859-2", "Kai posle, ki se skrivajo pred upravljalnik oken (SKIP-WINLIST)" }, - { "iso-8859-5", "Window a\n(AfterStep, Enlightenment, FVWM, IceWM, Sawmill)" }, - { "iso-8859-2", "Window menadzeri pomera dekoracioni prozor umesto toga\n(AfterStep, Enlightenment, FVWM, IceWM, Sawmill)" }, - { "iso-8859-1", "Fnsterhanteraren flyttar dekorationsfnstret istllet\n(AfterStep, Enlightenment, FVWM, IceWM, Sawfish)" }, - /*{ "TSCII", "츼- ¡ 츼 (츼--Ţ)" },*/ - { "iso-8859-9", "Kaydetme isteine bir uygulak cevap vermiyor .\nUygula sileyim mi , yoksa bekleyeyim mi ?" }, - { "koi8-u", "ͦ æ ͦ צ\n(AfterStep, Enlightenment, FVWM, IceWM, Sawfish)" }, - { "iso-8859-1", "Cwand on scriftr est bodj fo, li scriftr t totes\nles apliketes dvins sont pierdowes. Bodj ci scriftr chal?" }, - { "gb2312", "ǨƵװδڹ(AfterStep, Enlightenment, FVWM, IceWM, SawMill)" }, - { "big5", "޲z̥uʸ˹\n(AfterStep, Enlightenment, FVWM, IceWM, Sawmill)" }, -}; diff --git a/camel/tests/lib/addresses.c b/camel/tests/lib/addresses.c deleted file mode 100644 index 57275511c4..0000000000 --- a/camel/tests/lib/addresses.c +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -#include - -#include "addresses.h" -#include "camel-test.h" - -void -test_address_compare(CamelInternetAddress *addr, CamelInternetAddress *addr2) -{ - const char *r1, *r2, *a1, *a2; - char *e1, *e2, *f1, *f2; - int j; - - check(camel_address_length(CAMEL_ADDRESS(addr)) == camel_address_length(CAMEL_ADDRESS(addr2))); - for (j=0;j - -/* addresses.c */ -void test_address_compare(CamelInternetAddress *addr, CamelInternetAddress *addr2); diff --git a/camel/tests/lib/camel-test.c b/camel/tests/lib/camel-test.c deleted file mode 100644 index 41622cb3ea..0000000000 --- a/camel/tests/lib/camel-test.c +++ /dev/null @@ -1,355 +0,0 @@ - -#include "camel-test.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* well i dunno, doesn't seem to be in the headers but hte manpage mentions it */ -/* a nonportable checking mutex for glibc, not really needed, just validates - the test harness really */ -# ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP -static pthread_mutex_t lock = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; -# else -static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; -# endif -#define CAMEL_TEST_LOCK pthread_mutex_lock(&lock) -#define CAMEL_TEST_UNLOCK pthread_mutex_unlock(&lock) -#define CAMEL_TEST_ID (pthread_self()) - -static int setup; -static int ok; - -struct _stack { - struct _stack *next; - int fatal; - char *what; -}; - -/* per-thread state */ -struct _state { - char *test; - int nonfatal; - struct _stack *state; -}; - -static GHashTable *info_table; - -int camel_test_verbose; - -static void -dump_action(int id, struct _state *s, void *d) -{ - struct _stack *node; - - printf("\nThread %d:\n", id); - - node = s->state; - if (node) { - printf("Current action:\n"); - while (node) { - printf("\t%s%s\n", node->fatal?"":"[nonfatal]", node->what); - node = node->next; - } - } - printf("\tTest: %s\n", s->test); -} - -static void die(int sig) -{ - static int indie = 0; - - if (!indie) { - indie = 1; - printf("\n\nReceived fatal signal %d\n", sig); - g_hash_table_foreach(info_table, (GHFunc)dump_action, 0); - - if (camel_test_verbose > 2) { - printf("Attach debugger to pid %d to debug\n", getpid()); - sleep(1000); - } - } - - _exit(1); -} - -static struct _state * -current_state(void) -{ - struct _state *info; - - if (info_table == NULL) - info_table = g_hash_table_new(0, 0); - - info = g_hash_table_lookup(info_table, (void *)CAMEL_TEST_ID); - if (info == NULL) { - info = g_malloc0(sizeof(*info)); - g_hash_table_insert(info_table, (void *)CAMEL_TEST_ID, info); - } - return info; -} - - -void camel_test_init(int argc, char **argv) -{ - struct stat st; - char *path; - int i; - - setup = 1; - - /* yeah, we do need ot thread init, even though camel isn't compiled with enable threads */ - g_thread_init (NULL); - - path = g_strdup_printf ("/tmp/camel-test"); - if (mkdir (path, 0700) == -1 && errno != EEXIST) - abort (); - - if (stat (path, &st) == -1) - abort (); - - if (!S_ISDIR (st.st_mode) || access (path, R_OK | W_OK | X_OK) == -1) - abort (); - - camel_init (path, FALSE); - g_free (path); - - camel_type_init (); - - info_table = g_hash_table_new(0, 0); - - signal(SIGSEGV, die); - signal(SIGABRT, die); - - /* default, just say what, how well we did, unless fail, then abort */ - camel_test_verbose = 1; - - for (i=0;itest = g_strdup(what); - - if (camel_test_verbose > 0) { - printf("Test: %s ... ", what); - fflush(stdout); - } - - CAMEL_TEST_UNLOCK; -} - -void camel_test_push(const char *what, ...) -{ - struct _stack *node; - va_list ap; - char *text; - struct _state *s; - - CAMEL_TEST_LOCK; - - s = current_state(); - - va_start(ap, what); - text = g_strdup_vprintf(what, ap); - va_end(ap); - - if (camel_test_verbose > 3) - printf("Start step: %s\n", text); - - node = g_malloc(sizeof(*node)); - node->what = text; - node->next = s->state; - node->fatal = 1; - s->state = node; - - CAMEL_TEST_UNLOCK; -} - -void camel_test_pull(void) -{ - struct _stack *node; - struct _state *s; - - CAMEL_TEST_LOCK; - - s = current_state(); - - g_assert(s->state); - - if (camel_test_verbose > 3) - printf("Finish step: %s\n", s->state->what); - - node = s->state; - s->state = node->next; - if (!node->fatal) - s->nonfatal--; - g_free(node->what); - g_free(node); - - CAMEL_TEST_UNLOCK; -} - -/* where to set breakpoints */ -void camel_test_break(void); - -void camel_test_break(void) -{ -} - -void camel_test_fail(const char *why, ...) -{ - va_list ap; - - va_start(ap, why); - camel_test_failv(why, ap); - va_end(ap); -} - - -void camel_test_failv(const char *why, va_list ap) -{ - char *text; - struct _state *s; - - CAMEL_TEST_LOCK; - - s = current_state(); - - text = g_strdup_vprintf(why, ap); - - if ((s->nonfatal == 0 && camel_test_verbose > 0) - || (s->nonfatal && camel_test_verbose > 1)) { - printf("Failed.\n%s\n", text); - camel_test_break(); - } - - g_free(text); - - if ((s->nonfatal == 0 && camel_test_verbose > 0) - || (s->nonfatal && camel_test_verbose > 2)) { - g_hash_table_foreach(info_table, (GHFunc)dump_action, 0); - } - - if (s->nonfatal == 0) { - exit(1); - } else { - ok=0; - if (camel_test_verbose > 1) { - printf("Known problem (ignored):\n"); - dump_action(CAMEL_TEST_ID, s, 0); - } - } - - CAMEL_TEST_UNLOCK; -} - -void camel_test_nonfatal(const char *what, ...) -{ - struct _stack *node; - va_list ap; - char *text; - struct _state *s; - - CAMEL_TEST_LOCK; - - s = current_state(); - - va_start(ap, what); - text = g_strdup_vprintf(what, ap); - va_end(ap); - - if (camel_test_verbose > 3) - printf("Start nonfatal: %s\n", text); - - node = g_malloc(sizeof(*node)); - node->what = text; - node->next = s->state; - node->fatal = 0; - s->nonfatal++; - s->state = node; - - CAMEL_TEST_UNLOCK; -} - -void camel_test_fatal(void) -{ - camel_test_pull(); -} - -void camel_test_end(void) -{ - if (camel_test_verbose > 0) { - if (ok) - printf("Ok\n"); - else - printf("Partial success\n"); - } - - fflush(stdout); -} - - - - -/* compare strings, ignore whitespace though */ -int string_equal(const char *a, const char *b) -{ - const char *ap, *bp; - - ap = a; - bp = b; - - while (*ap && *bp) { - while (*ap == ' ' || *ap == '\n' || *ap == '\t') - ap++; - while (*bp == ' ' || *bp == '\n' || *bp == '\t') - bp++; - - a = ap; - b = bp; - - while (*ap && *ap != ' ' && *ap != '\n' && *ap != '\t') - ap++; - while (*bp && *bp != ' ' && *bp != '\n' && *bp != '\t') - bp++; - - if (ap - a != bp - a - && ap - 1 > 0 - && memcmp(a, b, ap-a) != 0) { - return 0; - } - } - - return 1; -} - diff --git a/camel/tests/lib/camel-test.h b/camel/tests/lib/camel-test.h deleted file mode 100644 index 986a943fa3..0000000000 --- a/camel/tests/lib/camel-test.h +++ /dev/null @@ -1,68 +0,0 @@ - -/* some utilities for testing */ - -#include "config.h" - -#include -#include - -void camel_test_failv(const char *why, va_list ap); - -/* perform a check assertion */ -#define check(x) do {if (!(x)) { camel_test_fail("%s:%d: %s", __FILE__, __LINE__, #x); } } while (0) -/* check with message */ -#ifdef __GNUC__ -#define check_msg(x, y, z...) do {if (!(x)) { camel_test_fail("%s:%d: %s\n\t" #y, __FILE__, __LINE__, #x, ##z); } } while (0) -#else -static void check_msg(int truth, char *fmt, ...) -{ - /* no gcc, we lose the condition that failed, nm */ - if (!truth) { - va_list ap; - va_start(ap, fmt); - camel_test_failv(fmt, ap); - va_end(ap); - } -} -#endif - -#define check_count(object, expected) do { \ - if (CAMEL_OBJECT(object)->ref_count != expected) { \ - camel_test_fail("%s->ref_count != %s\n\tref_count = %d", #object, #expected, CAMEL_OBJECT(object)->ref_count); \ - } \ -} while (0) - -#define check_unref(object, expected) do { \ - check_count(object, expected); \ - camel_object_unref(CAMEL_OBJECT(object)); \ - if (expected == 1) { \ - object = NULL; \ - } \ -} while (0) - -#define test_free(mem) (g_free(mem), mem=NULL) - -#define push camel_test_push -#define pull camel_test_pull - -void camel_test_init(int argc, char **argv); - -/* start/finish a new test */ -void camel_test_start(const char *what); -void camel_test_end(void); - -/* start/finish a new test part */ -void camel_test_push(const char *what, ...); -void camel_test_pull(void); - -/* fail a test, with a reason why */ -void camel_test_fail(const char *why, ...); -void camel_test_failv(const char *why, va_list ap); - -/* Set whether a failed test quits. May be nested, but must be called in nonfatal/fatal pairs */ -void camel_test_nonfatal(const char *why, ...); -void camel_test_fatal(void); - -/* utility functions */ -/* compare strings, ignore whitespace though */ -int string_equal(const char *a, const char *b); diff --git a/camel/tests/lib/folders.c b/camel/tests/lib/folders.c deleted file mode 100644 index a670576564..0000000000 --- a/camel/tests/lib/folders.c +++ /dev/null @@ -1,568 +0,0 @@ -#include - -#include "camel-test.h" -#include "folders.h" -#include "messages.h" - -#include "camel/camel-exception.h" - -/* check the total/unread is what we think it should be */ -void -test_folder_counts(CamelFolder *folder, int total, int unread) -{ - GPtrArray *s; - int i, myunread; - CamelMessageInfo *info; - - push("test folder counts %d total %d unread", total, unread); - - /* first, use the standard functions */ - check(camel_folder_get_message_count(folder) == total); - check(camel_folder_get_unread_message_count(folder) == total); - - /* next, use the summary */ - s = camel_folder_get_summary(folder); - check(s != NULL); - check(s->len == total); - myunread = s->len; - for (i=0;ilen;i++) { - info = s->pdata[i]; - if (info->flags & CAMEL_MESSAGE_SEEN) - myunread--; - } - check(unread == myunread); - camel_folder_free_summary(folder, s); - - /* last, use the uid list */ - s = camel_folder_get_uids(folder); - check(s != NULL); - check(s->len == total); - myunread = s->len; - for (i=0;ilen;i++) { - info = camel_folder_get_message_info(folder, s->pdata[i]); - if (info->flags & CAMEL_MESSAGE_SEEN) - myunread--; - camel_folder_free_message_info(folder, info); - } - check(unread == myunread); - camel_folder_free_uids(folder, s); - - pull(); -} - -static int -safe_strcmp(const char *a, const char *b) -{ - if (a == NULL && b == NULL) - return 0; - if (a == NULL) - return 1; - if (b == NULL) - return -1; - return strcmp(a, b); -} - -void -test_message_info(CamelMimeMessage *msg, const CamelMessageInfo *info) -{ - check_msg(safe_strcmp(camel_message_info_subject(info), camel_mime_message_get_subject(msg)) == 0, - "info->subject = '%s', get_subject() = '%s'", camel_message_info_subject(info), camel_mime_message_get_subject(msg)); - - /* FIXME: testing from/cc/to, etc is more tricky */ - - check(info->date_sent == camel_mime_message_get_date(msg, NULL)); - - /* date received isn't set for messages that haven't been sent anywhere ... */ - /*check(info->date_received == camel_mime_message_get_date_received(msg, NULL));*/ - - /* so is messageid/references, etc */ -} - -/* check a message is present */ -void -test_folder_message(CamelFolder *folder, const char *uid) -{ - CamelMimeMessage *msg; - CamelMessageInfo *info; - GPtrArray *s; - int i; - CamelException *ex = camel_exception_new(); - int found; - - push("uid %s is in folder", uid); - - /* first try getting info */ - info = camel_folder_get_message_info(folder, uid); - check(info != NULL); - check(strcmp(camel_message_info_uid(info), uid) == 0); - camel_folder_free_message_info(folder, info); - - /* then, getting message */ - msg = camel_folder_get_message(folder, uid, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - check(msg != NULL); - - /* cross check with info */ - test_message_info(msg, info); - - camel_object_unref((CamelObject *)msg); - - /* see if it is in the summary (only once) */ - s = camel_folder_get_summary(folder); - check(s != NULL); - found = 0; - for (i=0;ilen;i++) { - info = s->pdata[i]; - if (strcmp(camel_message_info_uid(info), uid) == 0) - found++; - } - check(found == 1); - camel_folder_free_summary(folder, s); - - /* check it is in the uid list */ - s = camel_folder_get_uids(folder); - check(s != NULL); - found = 0; - for (i=0;ilen;i++) { - if (strcmp(s->pdata[i], uid) == 0) - found++; - } - check(found == 1); - camel_folder_free_uids(folder, s); - - camel_exception_free(ex); - - pull(); -} - -/* check message not present */ -void -test_folder_not_message(CamelFolder *folder, const char *uid) -{ - CamelMimeMessage *msg; - CamelMessageInfo *info; - GPtrArray *s; - int i; - CamelException *ex = camel_exception_new(); - int found; - - push("uid '%s' is not in folder", uid); - - /* first try getting info */ - push("no message info"); - info = camel_folder_get_message_info(folder, uid); - check(info == NULL); - pull(); - - /* then, getting message */ - push("no message"); - msg = camel_folder_get_message(folder, uid, ex); - check(camel_exception_is_set(ex)); - check(msg == NULL); - camel_exception_clear(ex); - pull(); - - /* see if it is not in the summary (only once) */ - push("not in summary list"); - s = camel_folder_get_summary(folder); - check(s != NULL); - found = 0; - for (i=0;ilen;i++) { - info = s->pdata[i]; - if (strcmp(camel_message_info_uid(info), uid) == 0) - found++; - } - check(found == 0); - camel_folder_free_summary(folder, s); - pull(); - - /* check it is not in the uid list */ - push("not in uid list"); - s = camel_folder_get_uids(folder); - check(s != NULL); - found = 0; - for (i=0;ilen;i++) { - if (strcmp(s->pdata[i], uid) == 0) - found++; - } - check(found == 0); - camel_folder_free_uids(folder, s); - pull(); - - camel_exception_free(ex); - - pull(); -} - -/* test basic store operations on folders */ -/* TODO: Add subscription stuff */ -void -test_folder_basic(CamelSession *session, const char *storename, int local, int spool) -{ - CamelStore *store; - CamelException *ex = camel_exception_new(); - CamelFolder *folder; - char *what = g_strdup_printf("testing store: %s", storename); - - camel_test_start(what); - test_free(what); - - push("getting store"); - store = camel_session_get_store(session, storename, ex); - check_msg(!camel_exception_is_set(ex), "getting store: %s", camel_exception_get_description(ex)); - check(store != NULL); - pull(); - - /* local providers == no inbox */ - push("getting inbox folder"); - folder = camel_store_get_inbox(store, ex); - if (local) { - check(camel_exception_is_set(ex)); - check(folder == NULL); - camel_exception_clear(ex); - } else { - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - check(folder != NULL); - check_unref(folder, 2); - } - pull(); - - push("getting a non-existant folder, no create"); - folder = camel_store_get_folder(store, "unknown", 0, ex); - check(camel_exception_is_set(ex)); - check(folder == NULL); - camel_exception_clear(ex); - pull(); - - if (!spool) { - push("getting a non-existant folder, with create"); - folder = camel_store_get_folder(store, "testbox", CAMEL_STORE_FOLDER_CREATE, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - check(folder != NULL); - if (local) - check_unref(folder, 1); - else - check_unref(folder, 2); - pull(); - - push("getting an existing folder"); - folder = camel_store_get_folder(store, "testbox", 0, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - check(folder != NULL); - if (local) - check_unref(folder, 1); - else - check_unref(folder, 2); - pull(); - - push("renaming a non-existant folder"); - camel_store_rename_folder(store, "unknown1", "unknown2", ex); - check(camel_exception_is_set(ex)); - camel_exception_clear(ex); - pull(); - - push("renaming an existing folder"); - camel_store_rename_folder(store, "testbox", "testbox2", ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - pull(); - - push("opening the old name of a renamed folder"); - folder = camel_store_get_folder(store, "testbox", 0, ex); - check(camel_exception_is_set(ex)); - check(folder == NULL); - camel_exception_clear(ex); - pull(); - - push("opening the new name of a renamed folder"); - folder = camel_store_get_folder(store, "testbox2", 0, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - check(folder != NULL); - if (local) - check_unref(folder, 1); - else - check_unref(folder, 2); - pull(); - } - - push("deleting a non-existant folder"); - camel_store_delete_folder(store, "unknown", ex); - check(camel_exception_is_set(ex)); - camel_exception_clear(ex); - pull(); - - if (!spool) { - push("deleting an existing folder"); - camel_store_delete_folder(store, "testbox2", ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - pull(); - } - - push("opening a folder that has been deleted"); - folder = camel_store_get_folder(store, "testbox2", 0, ex); - check(camel_exception_is_set(ex)); - check(folder == NULL); - camel_exception_clear(ex); - pull(); - - check_unref(store, 1); - - camel_test_end(); - - camel_exception_free(ex); -} - - -/* todo: cross-check everything with folder_info checks as well */ -/* this should probably take a folder instead of a session ... */ -void -test_folder_message_ops(CamelSession *session, const char *name, int local, const char *mailbox) -{ - CamelStore *store; - CamelException *ex = camel_exception_new(); - CamelFolder *folder; - CamelMimeMessage *msg; - int j; - int indexed, max; - GPtrArray *uids; - CamelMessageInfo *info; - - max=local?2:1; - - for (indexed = 0;indexedlen == j+1); - if (uids->len > j) - test_folder_message(folder, uids->pdata[j]); - pull(); - - push("checking it is the right message (subject): %s", subject); - if (uids->len > j) { - info = camel_folder_get_message_info(folder, uids->pdata[j]); - check(info != NULL); - check_msg(strcmp(camel_message_info_subject(info), subject)==0, - "info->subject %s", camel_message_info_subject(info)); - camel_folder_free_message_info(folder, info); - } - camel_folder_free_uids(folder, uids); - pull(); - - test_free(subject); - - /*if (!local) - camel_test_fatal();*/ - - check_unref(msg, 1); - pull(); - } - - if (local) - check_unref(folder, 1); - else - check_unref(folder, 2); - pull(); - -#if 0 - push("deleting test folder, with messages in it"); - camel_store_delete_folder(store, mailbox, ex); - check(camel_exception_is_set(ex)); - camel_exception_clear(ex); - pull(); -#endif - - push("re-opening folder"); - folder = camel_store_get_folder(store, mailbox, flags, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - check(folder != NULL); - - /* verify counts */ - test_folder_counts(folder, 10, 10); - - /* re-check uid's, after a reload */ - uids = camel_folder_get_uids(folder); - check(uids != NULL); - check(uids->len == 10); - for (j=0;j<10;j++) { - char *subject = g_strdup_printf("Test message %d", j); - - push("verify reload of %s", subject); - test_folder_message(folder, uids->pdata[j]); - - info = camel_folder_get_message_info(folder, uids->pdata[j]); - check_msg(strcmp(camel_message_info_subject(info), subject)==0, - "info->subject %s", camel_message_info_subject(info)); - test_free(subject); - camel_folder_free_message_info(folder, info); - pull(); - } - - push("deleting first message & expunging"); - camel_folder_delete_message(folder, uids->pdata[0]); - test_folder_counts(folder, 10, 10); - camel_folder_expunge(folder, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - test_folder_not_message(folder, uids->pdata[0]); - test_folder_counts(folder, 9, 9); - - camel_folder_free_uids(folder, uids); - - uids = camel_folder_get_uids(folder); - check(uids != NULL); - check(uids->len == 9); - for (j=0;j<9;j++) { - char *subject = g_strdup_printf("Test message %d", j+1); - - push("verify after expunge of %s", subject); - test_folder_message(folder, uids->pdata[j]); - - info = camel_folder_get_message_info(folder, uids->pdata[j]); - check_msg(strcmp(camel_message_info_subject(info), subject)==0, - "info->subject %s", camel_message_info_subject(info)); - test_free(subject); - camel_folder_free_message_info(folder, info); - pull(); - } - pull(); - - push("deleting last message & expunging"); - camel_folder_delete_message(folder, uids->pdata[8]); - /* sync? */ - test_folder_counts(folder, 9, 9); - camel_folder_expunge(folder, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - test_folder_not_message(folder, uids->pdata[8]); - test_folder_counts(folder, 8, 8); - - camel_folder_free_uids(folder, uids); - - uids = camel_folder_get_uids(folder); - check(uids != NULL); - check(uids->len == 8); - for (j=0;j<8;j++) { - char *subject = g_strdup_printf("Test message %d", j+1); - - push("verify after expunge of %s", subject); - test_folder_message(folder, uids->pdata[j]); - - info = camel_folder_get_message_info(folder, uids->pdata[j]); - check_msg(strcmp(camel_message_info_subject(info), subject)==0, - "info->subject %s", camel_message_info_subject(info)); - test_free(subject); - camel_folder_free_message_info(folder, info); - pull(); - } - pull(); - - push("deleting all messages & expunging"); - for (j=0;j<8;j++) { - camel_folder_delete_message(folder, uids->pdata[j]); - } - /* sync? */ - test_folder_counts(folder, 8, 8); - camel_folder_expunge(folder, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - for (j=0;j<8;j++) { - test_folder_not_message(folder, uids->pdata[j]); - } - test_folder_counts(folder, 0, 0); - - camel_folder_free_uids(folder, uids); - pull(); - - if (local) - check_unref(folder, 1); - else - check_unref(folder, 2); - pull(); /* re-opening folder */ - - if (strcasecmp(mailbox, "INBOX") != 0) { - push("deleting test folder, with no messages in it"); - camel_store_delete_folder(store, mailbox, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - pull(); - } - - if (!local) { - push("disconneect service"); - camel_service_disconnect((CamelService *)store, TRUE, ex); - check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); - pull(); - } - - check_unref(store, 1); - camel_test_end(); - } - - camel_exception_free(ex); -} diff --git a/camel/tests/lib/folders.h b/camel/tests/lib/folders.h deleted file mode 100644 index ae981611d3..0000000000 --- a/camel/tests/lib/folders.h +++ /dev/null @@ -1,20 +0,0 @@ - -#include "camel/camel-session.h" -#include "camel/camel-store.h" - -#include -#include -#include - -/* check the total/unread is what we think it should be, everywhere it can be determined */ -void test_folder_counts(CamelFolder *folder, int total, int unread); -/* cross-check info/msg */ -void test_message_info(CamelMimeMessage *msg, const CamelMessageInfo *info); -/* check a message is present everywhere it should be */ -void test_folder_message(CamelFolder *folder, const char *uid); -/* check message not present everywhere it shouldn't be */ -void test_folder_not_message(CamelFolder *folder, const char *uid); -/* test basic folder ops on a store */ -void test_folder_basic(CamelSession *session, const char *storename, int local, int spool); -/* test basic message operations on a folder */ -void test_folder_message_ops(CamelSession *session, const char *storename, int local, const char *foldername); diff --git a/camel/tests/lib/messages.c b/camel/tests/lib/messages.c deleted file mode 100644 index ff3485f9c2..0000000000 --- a/camel/tests/lib/messages.c +++ /dev/null @@ -1,290 +0,0 @@ -#include -#include -#include - -#include "messages.h" -#include "camel-test.h" - -#include -#include -#include -#include - -CamelMimeMessage * -test_message_create_simple(void) -{ - CamelMimeMessage *msg; - CamelInternetAddress *addr; - - msg = camel_mime_message_new(); - - addr = camel_internet_address_new(); - camel_internet_address_add(addr, "Michael Zucchi", "zed@nowhere.com"); - camel_mime_message_set_from(msg, addr); - camel_address_remove((CamelAddress *)addr, -1); - camel_internet_address_add(addr, "POSTMASTER", "POSTMASTER@somewhere.net"); - camel_mime_message_set_recipients(msg, CAMEL_RECIPIENT_TYPE_TO, addr); - camel_address_remove((CamelAddress *)addr, -1); - camel_internet_address_add(addr, "Michael Zucchi", "zed@nowhere.com"); - camel_mime_message_set_recipients(msg, CAMEL_RECIPIENT_TYPE_CC, addr); - - check_unref(addr, 1); - - camel_mime_message_set_subject(msg, "Simple message subject"); - camel_mime_message_set_date(msg, time(0), 930); - - return msg; -} - -static void -content_finalise(CamelObject *folder, void *crap, void *ba) -{ - g_byte_array_free(ba, TRUE); -} - -void -test_message_set_content_simple(CamelMimePart *part, int how, const char *type, const char *text, int len) -{ - CamelStreamMem *content = NULL; - CamelDataWrapper *dw; - static GByteArray *ba; - - switch (how) { - case 0: - camel_mime_part_set_content(part, text, len, type); - break; - case 1: - content = (CamelStreamMem *)camel_stream_mem_new_with_buffer(text, len); - break; - case 2: - content = (CamelStreamMem *)camel_stream_mem_new(); - camel_stream_mem_set_buffer(content, text, len); - break; - case 3: - ba = g_byte_array_new(); - g_byte_array_append(ba, text, len); - - content = (CamelStreamMem *)camel_stream_mem_new_with_byte_array(ba); - ba = NULL; - break; - case 4: - ba = g_byte_array_new(); - g_byte_array_append(ba, text, len); - - content = (CamelStreamMem *)camel_stream_mem_new(); - camel_stream_mem_set_byte_array(content, ba); - - camel_object_hook_event((CamelObject *)content, "finalize", content_finalise, ba); - break; - } - - if (content != 0) { - dw = camel_data_wrapper_new(); - camel_data_wrapper_set_mime_type (dw, type); - - camel_data_wrapper_construct_from_stream(dw, (CamelStream *)content); - camel_medium_set_content_object((CamelMedium *)part, dw); - - check_unref(content, 2); - check_unref(dw, 2); - } -} - -int -test_message_write_file(CamelMimeMessage *msg, const char *name) -{ - CamelStreamFs *file; - int ret; - - file = (CamelStreamFs *)camel_stream_fs_new_with_name(name, O_CREAT|O_WRONLY, 0600); - camel_data_wrapper_write_to_stream((CamelDataWrapper *)msg, (CamelStream *)file); - ret = camel_stream_close((CamelStream *)file); - - check(((CamelObject *)file)->ref_count == 1); - camel_object_unref((CamelObject *)file); - - return ret; -} - -CamelMimeMessage * -test_message_read_file(const char *name) -{ - CamelStreamFs *file; - CamelMimeMessage *msg2; - - file = (CamelStreamFs *)camel_stream_fs_new_with_name(name, O_RDONLY, 0); - msg2 = camel_mime_message_new(); - - camel_data_wrapper_construct_from_stream((CamelDataWrapper *)msg2, (CamelStream *)file); - /* file's refcount may be > 1 if the message is real big */ - check(CAMEL_OBJECT(file)->ref_count >=1); - camel_object_unref((CamelObject *)file); - - return msg2; -} - -static void -hexdump (const unsigned char *in, int inlen) -{ - const unsigned char *inptr = in, *start = inptr; - const unsigned char *inend = in + inlen; - int octets; - - while (inptr < inend) { - octets = 0; - while (inptr < inend && octets < 16) { - printf ("%.2X ", *inptr++); - octets++; - } - - while (octets < 16) { - printf (" "); - octets++; - } - - printf (" "); - - while (start < inptr) { - fputc (isprint ((int) *start) ? *start : '.', stdout); - start++; - } - - fputc ('\n', stdout); - } -} - -int -test_message_compare_content(CamelDataWrapper *dw, const char *text, int len) -{ - CamelStreamMem *content; - - /* sigh, ok, so i len == 0, dw will probably be 0 too - camel_mime_part_set_content is weird like that */ - if (dw == 0 && len == 0) - return 0; - - content = (CamelStreamMem *)camel_stream_mem_new(); - camel_data_wrapper_decode_to_stream(dw, (CamelStream *)content); - - if (content->buffer->len != len) { - printf ("original text:\n"); - hexdump (text, len); - - printf ("new text:\n"); - hexdump (content->buffer->data, content->buffer->len); - } - - check_msg(content->buffer->len == len, "buffer->len = %d, len = %d", content->buffer->len, len); - check_msg(memcmp(content->buffer->data, text, content->buffer->len) == 0, "len = %d", len); - - check_unref(content, 1); - - return 0; -} - -int -test_message_compare (CamelMimeMessage *msg) -{ - CamelMimeMessage *msg2; - CamelStreamMem *mem1, *mem2; - - mem1 = (CamelStreamMem *) camel_stream_mem_new (); - check_msg(camel_data_wrapper_write_to_stream ((CamelDataWrapper *) msg, (CamelStream *) mem1) != -1, "write_to_stream 1 failed"); - camel_stream_reset ((CamelStream *) mem1); - - msg2 = camel_mime_message_new (); - check_msg(camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) msg2, (CamelStream *) mem1) != -1, "construct_from_stream 1 failed"); - camel_stream_reset ((CamelStream *) mem1); - - mem2 = (CamelStreamMem *) camel_stream_mem_new (); - check_msg(camel_data_wrapper_write_to_stream ((CamelDataWrapper *) msg2, (CamelStream *) mem2) != -1, "write_to_stream 2 failed"); - camel_stream_reset ((CamelStream *) mem2); - - if (mem1->buffer->len != mem2->buffer->len) { - CamelDataWrapper *content; - - printf ("mem1 stream:\n%.*s\n", mem1->buffer->len, mem1->buffer->data); - printf ("mem2 stream:\n%.*s\n\n", mem2->buffer->len, mem2->buffer->data); - - printf("msg1:\n"); - test_message_dump_structure(msg); - printf("msg2:\n"); - test_message_dump_structure(msg2); - - content = camel_medium_get_content_object ((CamelMedium *) msg); - } - - check_unref(msg2, 1); - - check_msg (mem1->buffer->len == mem2->buffer->len, - "mem1->buffer->len = %d, mem2->buffer->len = %d", - mem1->buffer->len, mem2->buffer->len); - - check_msg (memcmp (mem1->buffer->data, mem2->buffer->data, mem1->buffer->len) == 0, "msg/stream compare"); - - camel_object_unref (mem1); - camel_object_unref (mem2); - - return 0; -} - -int -test_message_compare_header(CamelMimeMessage *m1, CamelMimeMessage *m2) -{ - return 0; -} - -int -test_message_compare_messages(CamelMimeMessage *m1, CamelMimeMessage *m2) -{ - return 0; -} - -static void -message_dump_rec(CamelMimeMessage *msg, CamelMimePart *part, int depth) -{ - CamelDataWrapper *containee; - int parts, i; - char *s; - char *mime_type; - - s = alloca(depth+1); - memset(s, ' ', depth); - s[depth] = 0; - - mime_type = camel_data_wrapper_get_mime_type((CamelDataWrapper *)part); - printf("%sPart <%s>\n", s, ((CamelObject *)part)->klass->name); - printf("%sContent-Type: %s\n", s, mime_type); - g_free(mime_type); - printf("%s encoding: %s\n", s, camel_transfer_encoding_to_string(((CamelDataWrapper *)part)->encoding)); - printf("%s part encoding: %s\n", s, camel_transfer_encoding_to_string(part->encoding)); - - containee = camel_medium_get_content_object (CAMEL_MEDIUM (part)); - - if (containee == NULL) - return; - - mime_type = camel_data_wrapper_get_mime_type(containee); - printf("%sContent <%s>\n", s, ((CamelObject *)containee)->klass->name); - printf ("%sContent-Type: %s\n", s, mime_type); - g_free (mime_type); - printf("%s encoding: %s\n", s, camel_transfer_encoding_to_string(((CamelDataWrapper *)containee)->encoding)); - - /* using the object types is more accurate than using the mime/types */ - if (CAMEL_IS_MULTIPART (containee)) { - parts = camel_multipart_get_number (CAMEL_MULTIPART (containee)); - for (i = 0; i < parts; i++) { - CamelMimePart *part = camel_multipart_get_part (CAMEL_MULTIPART (containee), i); - - message_dump_rec(msg, part, depth+1); - } - } else if (CAMEL_IS_MIME_MESSAGE (containee)) { - message_dump_rec(msg, (CamelMimePart *)containee, depth+1); - } -} - -void -test_message_dump_structure(CamelMimeMessage *m) -{ - message_dump_rec(m, (CamelMimePart *)m, 0); -} diff --git a/camel/tests/lib/messages.h b/camel/tests/lib/messages.h deleted file mode 100644 index 1f892c3cc8..0000000000 --- a/camel/tests/lib/messages.h +++ /dev/null @@ -1,15 +0,0 @@ - -#include - -/* how many ways to set the content contents */ -#define SET_CONTENT_WAYS (5) - -/* messages.c */ -CamelMimeMessage *test_message_create_simple(void); -void test_message_set_content_simple(CamelMimePart *part, int how, const char *type, const char *text, int len); -int test_message_write_file(CamelMimeMessage *msg, const char *name); -CamelMimeMessage *test_message_read_file(const char *name); -int test_message_compare_content(CamelDataWrapper *dw, const char *text, int len); -int test_message_compare (CamelMimeMessage *msg); - -void test_message_dump_structure(CamelMimeMessage *m); diff --git a/camel/tests/lib/session.c b/camel/tests/lib/session.c deleted file mode 100644 index bf23fbe377..0000000000 --- a/camel/tests/lib/session.c +++ /dev/null @@ -1,44 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "session.h" - -static void -class_init (CamelTestSessionClass *camel_test_session_class) -{ - CamelSessionClass *camel_session_class = - CAMEL_SESSION_CLASS (camel_test_session_class); -} - -CamelType -camel_test_session_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register ( - camel_session_get_type (), - "CamelTestSession", - sizeof (CamelTestSession), - sizeof (CamelTestSessionClass), - (CamelObjectClassInitFunc) class_init, - NULL, - NULL, - NULL); - } - - return type; -} - -CamelSession * -camel_test_session_new (const char *path) -{ - CamelSession *session; - - session = CAMEL_SESSION (camel_object_new (CAMEL_TEST_SESSION_TYPE)); - - camel_session_construct (session, path); - - return session; -} diff --git a/camel/tests/lib/session.h b/camel/tests/lib/session.h deleted file mode 100644 index e69ef65e2e..0000000000 --- a/camel/tests/lib/session.h +++ /dev/null @@ -1,19 +0,0 @@ -#include - -#define CAMEL_TEST_SESSION_TYPE (camel_test_session_get_type ()) -#define CAMEL_TEST_SESSION(obj) (CAMEL_CHECK_CAST((obj), CAMEL_TEST_SESSION_TYPE, CamelTestSession)) -#define CAMEL_TEST_SESSION_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_TEST_SESSION_TYPE, CamelTestSessionClass)) -#define CAMEL_TEST_IS_SESSION(o) (CAMEL_CHECK_TYPE((o), CAMEL_TEST_SESSION_TYPE)) - -typedef struct _CamelTestSession { - CamelSession parent_object; - -} CamelTestSession; - -typedef struct _CamelTestSessionClass { - CamelSessionClass parent_class; - -} CamelTestSessionClass; - -CamelType camel_test_session_get_type (void); -CamelSession *camel_test_session_new (const char *path); diff --git a/camel/tests/lib/streams.c b/camel/tests/lib/streams.c deleted file mode 100644 index e4dc006363..0000000000 --- a/camel/tests/lib/streams.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - stream tests - - todo: do we need a seek test that seeks beyond the eos, writes, - then reads and checks for 0's in the space? -*/ - -#include - -#include "camel/camel-stream.h" -#include "camel/camel-seekable-stream.h" -#include "camel/camel-seekable-substream.h" - -#include "streams.h" - -#include "camel-test.h" - -static char teststring[] = "\xaa\x55\xc0\x0c\xff\x00"; -static char testbuf[10240]; - -/* pass in an empty read/write stream */ -void -test_stream_seekable_writepart(CamelSeekableStream *s) -{ - off_t end; - int i; - - push("seekable stream test, writing "); - - check(camel_seekable_stream_tell(s) == 0); - check(camel_seekable_stream_seek(s, 0, CAMEL_STREAM_SET) == 0); - check(camel_seekable_stream_tell(s) == 0); - - check(camel_stream_write(CAMEL_STREAM(s), "", 0) == 0); - check(camel_seekable_stream_tell(s) == 0); - check(camel_stream_write(CAMEL_STREAM(s), "\n", 1) == 1); - check(camel_seekable_stream_tell(s) == 1); - - for (i=0;i<10240;i++) { - check(camel_stream_write(CAMEL_STREAM(s), teststring, sizeof(teststring)) == sizeof(teststring)); - check(camel_seekable_stream_tell(s) == 1 + (i+1)*sizeof(teststring)); - } - end = 10240*sizeof(teststring)+1; - - check_msg(camel_seekable_stream_seek(s, 0, CAMEL_STREAM_END) == end, "seek =%d end = %d", - camel_seekable_stream_seek(s, 0, CAMEL_STREAM_END), end); - - check(camel_seekable_stream_seek(s, 0, CAMEL_STREAM_END) == end); - check(camel_seekable_stream_tell(s) == end); - /* need to read 0 first to set eos */ - check(camel_stream_read(CAMEL_STREAM(s), testbuf, 10240) == 0); - check(camel_stream_eos(CAMEL_STREAM(s))); - - pull(); -} - -void -test_stream_seekable_readpart(CamelSeekableStream *s) -{ - off_t off, new, end; - int i, j; - - push("seekable stream test, re-reading"); - - end = 10240*sizeof(teststring)+1; - - check(camel_seekable_stream_seek(s, 0, CAMEL_STREAM_SET) == 0); - check(camel_seekable_stream_tell(s) == 0); - check(!camel_stream_eos(CAMEL_STREAM(s))); - - off = 0; - for (i=0;i<1024;i++) { - - new = i*3; - - /* exercise all seek methods */ - switch(i % 3) { - case 0: - check(camel_seekable_stream_seek(s, new, CAMEL_STREAM_SET) == new); - break; - case 1: - check(camel_seekable_stream_seek(s, new-off, CAMEL_STREAM_CUR) == new); - break; - case 2: - check(camel_seekable_stream_seek(s, new-end, CAMEL_STREAM_END) == new); - break; - } - check(camel_seekable_stream_tell(s) == new); - - check(camel_stream_read(CAMEL_STREAM(s), testbuf, i*3) == i*3); - for (j=0;jparent_stream; - int i, len; - off_t end; - - push("writing substream, type %d", type); - - if (type == 1) { - check(camel_seekable_stream_seek(sp, ss->bound_start, CAMEL_STREAM_SET) == ss->bound_start); - s = (CamelStream *)sp; - } else { - check(camel_seekable_stream_tell(ss) == ss->bound_start); - check(camel_seekable_stream_seek(ss, 0, CAMEL_STREAM_SET) == ss->bound_start); - } - - check(camel_seekable_stream_tell(CAMEL_SEEKABLE_STREAM(s)) == ss->bound_start); - - check(camel_stream_write(s, "", 0) == 0); - check(camel_seekable_stream_tell(CAMEL_SEEKABLE_STREAM(s)) == ss->bound_start); - - /* fill up the bounds with writes */ - if (ss->bound_end != CAMEL_STREAM_UNBOUND) { - for (i=0;i<(ss->bound_end-ss->bound_start)/sizeof(teststring);i++) { - check(camel_stream_write(s, teststring, sizeof(teststring)) == sizeof(teststring)); - check(camel_seekable_stream_tell(CAMEL_SEEKABLE_STREAM(s)) == ss->bound_start + (i+1)*sizeof(teststring)); - } - len = (ss->bound_end-ss->bound_start) % sizeof(teststring); - check(camel_stream_write(s, teststring, len) == len); - check(camel_seekable_stream_tell(CAMEL_SEEKABLE_STREAM(s)) == ss->bound_end); - if (type == 0) { - check(camel_stream_write(s, teststring, sizeof(teststring)) == 0); - check(camel_stream_eos(s)); - check(camel_seekable_stream_tell(CAMEL_SEEKABLE_STREAM(s)) == ss->bound_end); - } - } else { - /* just 10K */ - for (i=0;i<10240;i++) { - check(camel_stream_write(CAMEL_STREAM(s), teststring, sizeof(teststring)) == sizeof(teststring)); - check(camel_seekable_stream_tell(CAMEL_SEEKABLE_STREAM(s)) == ss->bound_start + (i+1)*sizeof(teststring)); - } - - /* we can't really verify any end length here */ - } - - pull(); -} - -void -test_seekable_substream_readpart(CamelStream *s) -{ - CamelSeekableStream *ss = (CamelSeekableStream *)s; - CamelSeekableSubstream *sus = (CamelSeekableSubstream *)s; - CamelSeekableStream *sp = sus->parent_stream; - int i, len; - off_t end; - - push("reading substream"); - - check(camel_seekable_stream_seek(ss, 0, CAMEL_STREAM_SET) == ss->bound_start); - check(camel_seekable_stream_tell(ss) == ss->bound_start); - - check(camel_seekable_stream_seek(sp, ss->bound_start, CAMEL_STREAM_SET) == ss->bound_start); - check(camel_seekable_stream_tell(sp) == ss->bound_start); - - /* check writes, cross check with parent stream */ - if (ss->bound_end != CAMEL_STREAM_UNBOUND) { - for (i=0;i<(ss->bound_end-ss->bound_start)/sizeof(teststring);i++) { - check(camel_stream_read(s, testbuf, sizeof(teststring)) == sizeof(teststring)); - check(memcmp(testbuf, teststring, sizeof(teststring)) == 0); - check(camel_seekable_stream_tell(ss) == ss->bound_start + (i+1)*sizeof(teststring)); - - /* yeah great, the substreams affect the seek ... */ - check(camel_seekable_stream_seek(sp, ss->bound_start + (i)*sizeof(teststring), CAMEL_STREAM_SET) == ss->bound_start + i*sizeof(teststring)); - check(camel_stream_read(CAMEL_STREAM(sp), testbuf, sizeof(teststring)) == sizeof(teststring)); - check(memcmp(testbuf, teststring, sizeof(teststring)) == 0); - check(camel_seekable_stream_tell(sp) == ss->bound_start + (i+1)*sizeof(teststring)); - } - len = (ss->bound_end-ss->bound_start) % sizeof(teststring); - check(camel_stream_read(s, testbuf, len) == len); - check(memcmp(testbuf, teststring, len) == 0); - - check(camel_seekable_stream_seek(sp, ss->bound_end - len, CAMEL_STREAM_SET) == ss->bound_end - len); - check(camel_stream_read(CAMEL_STREAM(sp), testbuf, len) == len); - check(memcmp(testbuf, teststring, len) == 0); - - check(camel_stream_eos(s)); - check(camel_seekable_stream_tell(ss) == ss->bound_end); - check(camel_seekable_stream_tell(sp) == ss->bound_end); - check(camel_stream_read(s, testbuf, 1024) == 0); - check(camel_seekable_stream_tell(ss) == ss->bound_end); - check(camel_seekable_stream_tell(sp) == ss->bound_end); - check(camel_stream_eos(s)); - } else { - /* just 10K */ - for (i=0;i<10240;i++) { - check(camel_stream_read(s, testbuf, sizeof(teststring)) == sizeof(teststring)); - check(memcmp(testbuf, teststring, sizeof(teststring)) == 0); - check(camel_seekable_stream_tell(ss) == ss->bound_start + (i+1)*sizeof(teststring)); - - check(camel_seekable_stream_seek(sp, ss->bound_start + (i)*sizeof(teststring), CAMEL_STREAM_SET) == ss->bound_start + i*sizeof(teststring)); - check(camel_stream_read(CAMEL_STREAM(sp), testbuf, sizeof(teststring)) == sizeof(teststring)); - check(memcmp(testbuf, teststring, sizeof(teststring)) == 0); - check(camel_seekable_stream_tell(sp) == ss->bound_start + (i+1)*sizeof(teststring)); - } - - /* unbound - we dont know the real length */ -#if 0 - end = 10240*sizeof(teststring)+ss->bound_start; - - check(camel_seekable_stream_seek(ss, 0, CAMEL_STREAM_END) == end); - check(camel_seekable_stream_tell(ss) == end); - /* need to read 0 first to set eos */ - check(camel_stream_read(s, testbuf, 10240) == 0); - check(camel_stream_eos(s)); -#endif - } - - pull(); -} diff --git a/camel/tests/lib/streams.h b/camel/tests/lib/streams.h deleted file mode 100644 index df52e283d0..0000000000 --- a/camel/tests/lib/streams.h +++ /dev/null @@ -1,12 +0,0 @@ - -#include "camel/camel-seekable-stream.h" - -/* call one, then the other on the same stream content */ -void test_stream_seekable_writepart(CamelSeekableStream *s); -void test_stream_seekable_readpart(CamelSeekableStream *s); - -/* same, for substreams, multiple ways of writing */ -#define SEEKABLE_SUBSTREAM_WAYS (2) - -void test_seekable_substream_writepart(CamelStream *s, int type); -void test_seekable_substream_readpart(CamelStream *s); diff --git a/camel/tests/message/.cvsignore b/camel/tests/message/.cvsignore deleted file mode 100644 index 4f58c83bd0..0000000000 --- a/camel/tests/message/.cvsignore +++ /dev/null @@ -1,15 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -test1 -test2 -test3 -*.msg -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/tests/message/Makefile.am b/camel/tests/message/Makefile.am deleted file mode 100644 index 32b4294aa2..0000000000 --- a/camel/tests/message/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ - -INCLUDES = \ - -I$(includedir) \ - -I$(top_srcdir) \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/camel/tests/lib \ - -DG_LOG_DOMAIN=\"evolution-tests\" \ - $(CAMEL_CFLAGS) - -LDADD = \ - $(top_builddir)/camel/libcamel.la \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/camel/tests/lib/libcameltest.a \ - $(INTLLIBS) \ - $(EVOLUTION_MAIL_LIBS) - -check_PROGRAMS = \ - test1 \ - test2 \ - test3 \ - test4 - -TESTS = test1 test2 test3 test4 diff --git a/camel/tests/message/README b/camel/tests/message/README deleted file mode 100644 index 4b3c953a63..0000000000 --- a/camel/tests/message/README +++ /dev/null @@ -1,9 +0,0 @@ - -test1 creating, saving, loading simple messages -test2 camelinternetaddress tests, internationalised addresses, etc. -test3 multipart messages -test4 more encompassing mime parser tests that test real-world messages. - Note: In order to test this, though, you'll need to fetch - http://primates.ximian.com/~fejj/camel-mime-tests.tar.gz and - untar it into camel/tests/data/ - diff --git a/camel/tests/message/test1.c b/camel/tests/message/test1.c deleted file mode 100644 index 8dcf84c92c..0000000000 --- a/camel/tests/message/test1.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - test1.c - - Create a message, save it. - - Retrieve message, compare content. - - - Operations: - writing/loading from different types of streams - reading/writing different content - reading/writing different encodings - reading/writing different charsets - - Just testing streams: - different stream types - different file ops - seek, eof, etc. -*/ - -#include "camel-test.h" -#include "messages.h" - -/* for stat */ -#include -#include -#include - -#include -#include -#include - -struct _text { - char *text; - int len; -}; - -#define MAX_TEXTS (14) -struct _text texts[MAX_TEXTS]; - -static void -setup(void) -{ - int i, j; - char *p; - - /* setup various edge and other general cases */ - texts[0].text = ""; - texts[0].len = 0; - texts[1].text = ""; - texts[1].len = 1; - texts[2].text = "\n"; - texts[2].len = 1; - texts[3].text = "A"; - texts[3].len = 1; - texts[4].text = "This is a test.\n."; - texts[4].len = strlen(texts[4].text); - texts[5].text = "This is a test.\n\n.\n"; - texts[5].len = strlen(texts[5].text); - texts[6].text = g_malloc0(1024); - texts[6].len = 1024; - texts[7].text = g_malloc0(102400); - texts[7].len = 102400; - texts[8].text = g_malloc(1024); - memset(texts[8].text, '\n', 1024); - texts[8].len = 1024; - texts[9].text = g_malloc(102400); - memset(texts[9].text, '\n', 102400); - texts[9].len = 102400; - texts[10].text = g_malloc(1024); - memset(texts[10].text, ' ', 1024); - texts[10].len = 1024; - texts[11].text = g_malloc(102400); - memset(texts[11].text, ' ', 102400); - texts[11].len = 102400; - - srand(42); - p = texts[12].text = g_malloc(1024); - for (i=0;i<1024;i++) { - j = rand(); - if (j -#include -#include -#include -#include - -#include -#include - -#include "address-data.h" - -static char *convert(const char *in, const char *from, const char *to) -{ - iconv_t ic = iconv_open(to, from); - char *out, *outp; - const char *inp; - int inlen, outlen; - - if (ic == (iconv_t)-1) - return g_strdup(in); - - inlen = strlen(in); - outlen = inlen*5 + 16; - - outp = out = g_malloc(outlen); - inp = in; - - if (iconv(ic, &inp, &inlen, &outp, &outlen) == -1) { - test_free(out); - iconv_close(ic); - return g_strdup(in); - } - - if (iconv(ic, NULL, 0, &outp, &outlen) == -1) { - test_free(out); - iconv_close(ic); - return g_strdup(in); - } - - iconv_close(ic); - - *outp = 0; - -#if 0 - /* lets see if we can convert back again? */ - { - char *nout, *noutp; - iconv_t ic = iconv_open(from, to); - - inp = out; - inlen = strlen(out); - outlen = inlen*5 + 16; - noutp = nout = g_malloc(outlen); - if (iconv(ic, &inp, &inlen, &noutp, &outlen) == -1 - || iconv(ic, NULL, 0, &noutp, &outlen) == -1) { - g_warning("Cannot convert '%s' \n from %s to %s: %s\n", in, to, from, strerror(errno)); - } - iconv_close(ic); - } - - /* and lets see what camel thinks out optimal charset is */ - { - printf("Camel thinks the best encoding of '%s' is %s, although we converted from %s\n", - in, camel_charset_best(out, strlen(out)), from); - } -#endif - - return out; -} - -#define to_utf8(in, type) convert(in, type, "utf-8") -#define from_utf8(in, type) convert(in, "utf-8", type) - -#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) - -int main(int argc, char **argv) -{ - int i; - CamelInternetAddress *addr, *addr2; - char *name; - char *charset; - const char *real, *where; - char *enc, *enc2, *format, *format2; - - camel_test_init(argc, argv); - - camel_test_start("CamelInternetAddress, basics"); - - addr = camel_internet_address_new(); - - push("Test blank address"); - check(camel_address_length(CAMEL_ADDRESS(addr)) == 0); - check(camel_internet_address_get(addr, 0, &real, &where) == FALSE); - pull(); - - push("Test blank clone"); - addr2 = CAMEL_INTERNET_ADDRESS(camel_address_new_clone(CAMEL_ADDRESS(addr))); - test_address_compare(addr, addr2); - check_unref(addr2, 1); - pull(); - - push("Test add 1"); - camel_internet_address_add(addr, "Zed", "nowhere@here.com.au"); - check(camel_address_length(CAMEL_ADDRESS(addr)) == 1); - check(camel_internet_address_get(addr, 0, &real, &where) == TRUE); - check_msg(string_equal("Zed", real), "real = '%s'", real); - check(strcmp(where, "nowhere@here.com.au") == 0); - pull(); - - push("Test clone 1"); - addr2 = CAMEL_INTERNET_ADDRESS(camel_address_new_clone(CAMEL_ADDRESS(addr))); - test_address_compare(addr, addr2); - check_unref(addr2, 1); - pull(); - - push("Test add many"); - for (i=1;i<10;i++) { - char name[16], a[32]; - sprintf(name, "Zed %d", i); - sprintf(a, "nowhere@here-%d.com.au", i); - camel_internet_address_add(addr, name, a); - check(camel_address_length(CAMEL_ADDRESS(addr)) == i+1); - check(camel_internet_address_get(addr, i, &real, &where) == TRUE); - check_msg(string_equal(name, real), "name = '%s' real = '%s'", name, real); - check(strcmp(where, a) == 0); - } - pull(); - - /* put a few of these in to make it look like its doing something impressive ... :) */ - camel_test_end(); - camel_test_start("CamelInternetAddress, search"); - - push("Test search"); - camel_test_nonfatal("Address comparisons should ignore whitespace??"); - check(camel_internet_address_find_name(addr, "Zed 1", &where) == 1); - check(camel_internet_address_find_name(addr, "Zed 9", &where) == 9); - check(camel_internet_address_find_name(addr, "Zed", &where) == 0); - check(camel_internet_address_find_name(addr, " Zed", &where) == 0); - check(camel_internet_address_find_name(addr, "Zed ", &where) == 0); - check(camel_internet_address_find_name(addr, " Zed ", &where) == 0); - check(camel_internet_address_find_name(addr, "Zed 20", &where) == -1); - check(camel_internet_address_find_name(addr, "", &where) == -1); - /* interface dont handle nulls :) */ - /*check(camel_internet_address_find_name(addr, NULL, &where) == -1);*/ - - check(camel_internet_address_find_address(addr, "nowhere@here-1.com.au", &where) == 1); - check(camel_internet_address_find_address(addr, "nowhere@here-1 . com.au", &where) == 1); - check(camel_internet_address_find_address(addr, "nowhere@here-2 .com.au ", &where) == 2); - check(camel_internet_address_find_address(addr, " nowhere @here-3.com.au", &where) == 3); - check(camel_internet_address_find_address(addr, "nowhere@here-20.com.au ", &where) == -1); - check(camel_internet_address_find_address(addr, "", &where) == -1); - /*check(camel_internet_address_find_address(addr, NULL, &where) == -1);*/ - camel_test_fatal(); - pull(); - - camel_test_end(); - camel_test_start("CamelInternetAddress, copy/cat/clone"); - - push("Test clone many"); - addr2 = CAMEL_INTERNET_ADDRESS(camel_address_new_clone(CAMEL_ADDRESS(addr))); - test_address_compare(addr, addr2); - pull(); - - push("Test remove items"); - camel_address_remove(CAMEL_ADDRESS(addr2), 0); - check(camel_address_length(CAMEL_ADDRESS(addr2)) == 9); - camel_address_remove(CAMEL_ADDRESS(addr2), 0); - check(camel_address_length(CAMEL_ADDRESS(addr2)) == 8); - camel_address_remove(CAMEL_ADDRESS(addr2), 5); - check(camel_address_length(CAMEL_ADDRESS(addr2)) == 7); - camel_address_remove(CAMEL_ADDRESS(addr2), 10); - check(camel_address_length(CAMEL_ADDRESS(addr2)) == 7); - camel_address_remove(CAMEL_ADDRESS(addr2), -1); - check(camel_address_length(CAMEL_ADDRESS(addr2)) == 0); - check_unref(addr2, 1); - pull(); - - push("Testing copy/cat"); - push("clone + cat"); - addr2 = CAMEL_INTERNET_ADDRESS(camel_address_new_clone(CAMEL_ADDRESS(addr))); - camel_address_cat(CAMEL_ADDRESS(addr2), CAMEL_ADDRESS(addr)); - check(camel_address_length(CAMEL_ADDRESS(addr)) == 10); - check(camel_address_length(CAMEL_ADDRESS(addr2)) == 20); - check_unref(addr2, 1); - pull(); - - push("cat + cat + copy"); - addr2 = camel_internet_address_new(); - camel_address_cat(CAMEL_ADDRESS(addr2), CAMEL_ADDRESS(addr)); - test_address_compare(addr, addr2); - camel_address_cat(CAMEL_ADDRESS(addr2), CAMEL_ADDRESS(addr)); - check(camel_address_length(CAMEL_ADDRESS(addr)) == 10); - check(camel_address_length(CAMEL_ADDRESS(addr2)) == 20); - camel_address_copy(CAMEL_ADDRESS(addr2), CAMEL_ADDRESS(addr)); - test_address_compare(addr, addr2); - check_unref(addr2, 1); - pull(); - - push("copy"); - addr2 = camel_internet_address_new(); - camel_address_copy(CAMEL_ADDRESS(addr2), CAMEL_ADDRESS(addr)); - test_address_compare(addr, addr2); - check_unref(addr2, 1); - pull(); - - pull(); - - check_unref(addr, 1); - - camel_test_end(); - - camel_test_start("CamelInternetAddress, I18N"); - - for (i=0;i -#include -#include - -#include -#include -#include -#include "camel/camel-multipart.h" - -int main(int argc, char **argv) -{ - CamelMimeMessage *msg, *msg2, *msg3; - CamelMultipart *mp, *mp2; - CamelMimePart *part, *part2, *part3; - - camel_test_init(argc, argv); - - camel_test_start("multipart message"); - - push("building message"); - msg = test_message_create_simple(); - mp = camel_multipart_new(); - - /* Hrm, this should be able to set its own boundary, no? */ - camel_multipart_set_boundary(mp, "_=,.XYZ_Kangaroo_Meat_is_!_ABADF00D"); - check(strcmp(camel_multipart_get_boundary(mp), "_=,.XYZ_Kangaroo_Meat_is_!_ABADF00D") == 0); - - camel_medium_set_content_object((CamelMedium *)msg, (CamelDataWrapper *)mp); - check(camel_multipart_get_number(mp) == 0); - check(camel_multipart_get_part(mp, 0) == NULL); - check(camel_multipart_get_part(mp, 1) == NULL); - - push("adding/removing parts"); - part = camel_mime_part_new(); - test_message_set_content_simple(part, 0, "text/plain", "content part 1", strlen("content part 1")); - camel_multipart_add_part(mp, part); - check(CAMEL_OBJECT(part)->ref_count == 2); - check(camel_multipart_get_number(mp) == 1); - check(camel_multipart_get_part(mp, 0) == part); - check(camel_multipart_get_part(mp, 1) == NULL); - - camel_multipart_remove_part(mp, part); - check(CAMEL_OBJECT(part)->ref_count == 1); - check(camel_multipart_get_number(mp) == 0); - check(camel_multipart_get_part(mp, 0) == NULL); - check(camel_multipart_get_part(mp, 1) == NULL); - - camel_multipart_add_part_at(mp, part, 0); - check(CAMEL_OBJECT(part)->ref_count == 2); - check(camel_multipart_get_number(mp) == 1); - check(camel_multipart_get_part(mp, 0) == part); - check(camel_multipart_get_part(mp, 1) == NULL); - - check(camel_multipart_remove_part_at(mp, 1) == NULL); - check(CAMEL_OBJECT(part)->ref_count == 2); - check(camel_multipart_get_number(mp) == 1); - check(camel_multipart_get_part(mp, 0) == part); - check(camel_multipart_get_part(mp, 1) == NULL); - - check(camel_multipart_remove_part_at(mp, 0) == part); - check(CAMEL_OBJECT(part)->ref_count == 1); - check(camel_multipart_get_number(mp) == 0); - check(camel_multipart_get_part(mp, 0) == NULL); - check(camel_multipart_get_part(mp, 1) == NULL); - - camel_multipart_add_part(mp, part); - check(CAMEL_OBJECT(part)->ref_count == 2); - check(camel_multipart_get_number(mp) == 1); - check(camel_multipart_get_part(mp, 0) == part); - check(camel_multipart_get_part(mp, 1) == NULL); - - part2 = camel_mime_part_new(); - test_message_set_content_simple(part2, 0, "text/plain", "content part 2", strlen("content part 2")); - camel_multipart_add_part(mp, part2); - check(CAMEL_OBJECT(part2)->ref_count == 2); - check(camel_multipart_get_number(mp) == 2); - check(camel_multipart_get_part(mp, 0) == part); - check(camel_multipart_get_part(mp, 1) == part2); - - part3 = camel_mime_part_new(); - test_message_set_content_simple(part3, 0, "text/plain", "content part 3", strlen("content part 3")); - camel_multipart_add_part_at(mp, part3, 1); - check(CAMEL_OBJECT(part3)->ref_count == 2); - check(camel_multipart_get_number(mp) == 3); - check(camel_multipart_get_part(mp, 0) == part); - check(camel_multipart_get_part(mp, 1) == part3); - check(camel_multipart_get_part(mp, 2) == part2); - pull(); - - push("save message to test3.msg"); - unlink("test3.msg"); - test_message_write_file(msg, "test3.msg"); - pull(); - - push("read from test3.msg"); - msg2 = test_message_read_file("test3.msg"); - pull(); - - push("compre content of multipart"); - mp2 = (CamelMultipart *)camel_medium_get_content_object((CamelMedium *)msg2); - check(mp2 != NULL); - check(CAMEL_IS_MULTIPART(mp2)); - check(camel_multipart_get_number(mp2) == 3); - - check(strcmp(camel_multipart_get_boundary(mp2), "_=,.XYZ_Kangaroo_Meat_is_!_ABADF00D") == 0); - check(mp2->preface == NULL || strlen(mp2->preface) == 0); - - /* FIXME */ - camel_test_nonfatal("postface may gain a single \\n?"); - check_msg(mp2->postface == NULL || strlen(mp2->postface) == 0, "postface: '%s'", mp2->postface); - camel_test_fatal(); - - test_message_compare_content(camel_medium_get_content_object(CAMEL_MEDIUM(camel_multipart_get_part(mp2, 0))), - "content part 1", strlen("content part 1")); - test_message_compare_content(camel_medium_get_content_object(CAMEL_MEDIUM(camel_multipart_get_part(mp2, 1))), - "content part 3", strlen("content part 3")); - test_message_compare_content(camel_medium_get_content_object(CAMEL_MEDIUM(camel_multipart_get_part(mp2, 2))), - "content part 2", strlen("content part 2")); - pull(); - - push("writing again, & re-reading"); - unlink("test3-2.msg"); - test_message_write_file(msg2, "test3-2.msg"); - msg3 = test_message_read_file("test3-2.msg"); - - push("comparing again"); - mp2 = (CamelMultipart *)camel_medium_get_content_object((CamelMedium *)msg3); - check(mp2 != NULL); - check(CAMEL_IS_MULTIPART(mp2)); - check(camel_multipart_get_number(mp2) == 3); - - check(strcmp(camel_multipart_get_boundary(mp2), "_=,.XYZ_Kangaroo_Meat_is_!_ABADF00D") == 0); - check(mp2->preface == NULL || strlen(mp2->preface) == 0); - - /* FIXME */ - camel_test_nonfatal("postface may gain a single \\n?"); - check_msg(mp2->postface == NULL || strlen(mp2->postface) == 0, "postface: '%s'", mp2->postface); - camel_test_fatal(); - - test_message_compare_content(camel_medium_get_content_object(CAMEL_MEDIUM(camel_multipart_get_part(mp2, 0))), - "content part 1", strlen("content part 1")); - test_message_compare_content(camel_medium_get_content_object(CAMEL_MEDIUM(camel_multipart_get_part(mp2, 1))), - "content part 3", strlen("content part 3")); - test_message_compare_content(camel_medium_get_content_object(CAMEL_MEDIUM(camel_multipart_get_part(mp2, 2))), - "content part 2", strlen("content part 2")); - pull(); - pull(); - - check_unref(msg2, 1); - check_unref(msg3, 1); - - push("testing pre/post text"); - camel_multipart_set_preface(mp, "pre-text\nLines."); - camel_multipart_set_postface(mp, "post-text, no lines.\nOne line.\n"); - - check(strcmp(mp->preface, "pre-text\nLines.") == 0); - check(strcmp(mp->postface, "post-text, no lines.\nOne line.\n") == 0); - - push("writing /re-reading"); - unlink("test3-3.msg"); - test_message_write_file(msg, "test3-3.msg"); - msg2 = test_message_read_file("test3-3.msg"); - - mp2 = (CamelMultipart *)camel_medium_get_content_object((CamelMedium *)msg2); - check(mp2 != NULL); - check(CAMEL_IS_MULTIPART(mp2)); - check(camel_multipart_get_number(mp2) == 3); - - check(strcmp(camel_multipart_get_boundary(mp2), "_=,.XYZ_Kangaroo_Meat_is_!_ABADF00D") == 0); - check(strcmp(mp2->preface, "pre-text\nLines.") == 0); - check(strcmp(mp2->postface, "post-text, no lines.\nOne line.\n") == 0); - test_message_compare_content(camel_medium_get_content_object(CAMEL_MEDIUM(camel_multipart_get_part(mp2, 0))), - "content part 1", strlen("content part 1")); - test_message_compare_content(camel_medium_get_content_object(CAMEL_MEDIUM(camel_multipart_get_part(mp2, 1))), - "content part 3", strlen("content part 3")); - test_message_compare_content(camel_medium_get_content_object(CAMEL_MEDIUM(camel_multipart_get_part(mp2, 2))), - "content part 2", strlen("content part 2")); - pull(); - check_unref(msg2, 1); - pull(); - - check_unref(msg, 1); - check_unref(mp, 1); - check_unref(part, 1); - check_unref(part2, 1); - check_unref(part3, 1); - - camel_test_end(); - - return 0; -} diff --git a/camel/tests/message/test4.c b/camel/tests/message/test4.c deleted file mode 100644 index ff3b08af30..0000000000 --- a/camel/tests/message/test4.c +++ /dev/null @@ -1,129 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#include -#include -#include -#include -#include -#include - -#include "camel-test.h" -#include "messages.h" - -#include -#include -#include -#include - - -#if 0 -static void -dump_mime_struct (CamelMimePart *mime_part, int depth) -{ - CamelDataWrapper *content; - char *mime_type; - int i = 0; - - while (i < depth) { - printf (" "); - i++; - } - - content = camel_medium_get_content_object ((CamelMedium *) mime_part); - - mime_type = camel_data_wrapper_get_mime_type (content); - printf ("Content-Type: %s\n", mime_type); - g_free (mime_type); - - if (CAMEL_IS_MULTIPART (content)) { - guint num, index = 0; - - num = camel_multipart_get_number ((CamelMultipart *) content); - while (index < num) { - mime_part = camel_multipart_get_part ((CamelMultipart *) content, index); - dump_mime_struct (mime_part, depth + 1); - index++; - } - } else if (CAMEL_IS_MIME_MESSAGE (content)) { - dump_mime_struct ((CamelMimePart *) content, depth + 1); - } -} -#endif - -int main (int argc, char **argv) -{ - struct dirent *dent; - DIR *dir; - int fd; - - camel_test_init (argc, argv); - - camel_test_start ("Message Test Suite"); - - if (!(dir = opendir ("../data/messages"))) - return 77; - - while ((dent = readdir (dir)) != NULL) { - CamelMimeMessage *message; - CamelStream *stream; - char *filename; - struct stat st; - - if (dent->d_name[0] == '.') - continue; - - filename = g_strdup_printf ("../data/messages/%s", dent->d_name); - if (stat (filename, &st) == -1 || !S_ISREG (st.st_mode)) { - g_free (filename); - continue; - } - - if ((fd = open (filename, O_RDONLY)) == -1) { - g_free (filename); - continue; - } - - push ("testing message `%s`", filename); - g_free (filename); - - stream = camel_stream_fs_new_with_fd (fd); - message = camel_mime_message_new (); - camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream); - camel_stream_reset (stream); - - /*dump_mime_struct ((CamelMimePart *) message, 0);*/ - test_message_compare (message); - - camel_object_unref (message); - camel_object_unref (stream); - - pull (); - } - - closedir (dir); - - camel_test_end (); - - return 0; -} diff --git a/camel/tests/mime-filter/.cvsignore b/camel/tests/mime-filter/.cvsignore deleted file mode 100644 index f8d627b581..0000000000 --- a/camel/tests/mime-filter/.cvsignore +++ /dev/null @@ -1,8 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -*.lo -*.la -test-crlf -test-charset \ No newline at end of file diff --git a/camel/tests/mime-filter/Makefile.am b/camel/tests/mime-filter/Makefile.am deleted file mode 100644 index 21635f839f..0000000000 --- a/camel/tests/mime-filter/Makefile.am +++ /dev/null @@ -1,36 +0,0 @@ - -INCLUDES = \ - -I$(includedir) \ - -I$(top_srcdir) \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/camel/tests/lib \ - -DG_LOG_DOMAIN=\"evolution-tests\" \ - -DSOURCEDIR=\"$(srcdir)\" \ - $(CAMEL_CFLAGS) - -LDADD = \ - $(top_builddir)/camel/libcamel.la \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/camel/tests/lib/libcameltest.a \ - $(INTLLIBS) \ - $(EVOLUTION_MAIL_LIBS) - -EXTRA_DIST = \ - crlf-1.in \ - crlf-1.out \ - charset-iso-2022-jp.0.in \ - charset-iso-2022-jp.0.out \ - charset-gb2312.0.in \ - charset-gb2312.0.out - -check_PROGRAMS = \ - test-crlf \ - test-charset \ - test-tohtml - -TESTS = test-crlf test-charset test-tohtml - - - diff --git a/camel/tests/mime-filter/charset-gb2312.0.in b/camel/tests/mime-filter/charset-gb2312.0.in deleted file mode 100644 index 82520ac916..0000000000 --- a/camel/tests/mime-filter/charset-gb2312.0.in +++ /dev/null @@ -1,448 +0,0 @@ - - - - -һվʽóס漰ƹϵͳ An all-in-one solution for trading, inventory, accounting management - - - - - - - - - - - - - - - - -
-

- - - - - TRADEdotNET - -  
-
һվʽóס漰ƹϵͳܶʼ롢ݴ౨ۡƱ֡ռʡƱļЧعóס漰

-

- - - - - TRADEdotNET - -  
- What's the most annoying part during your - work? -
Endless repetitive data - entry, calculation and paper work on quotation, invoice, inventory - management, daily voucher, journal and reporting? Once you have installed - TRADEdotNET, all of these - annoying work will never appear in your office again!
- TRADEdotNET
is an all-in-one solution for trading, inventory, - accounting management. In the TRADEdotNET  - environment, all data can be continuously retrieved and reused. This will - help you for minimizing time consumed on data entry and enhancing - efficiency.

- - TRADEdotNET - ֱϵͳɣó׶ϵͳ - - TRADEdotNET - Containing Trading Management - Module, Inventory Management Module and Accounting Management Module.
-

-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - TRADEdotNET - ŵ
-
-  ϵͳ - -
-
-

- IJͼʾϵͳҪ̣û˳ÿһ衣ûֻ밴ͼͼ񣬼ϵͳݷʽɽضĹܻ档
- - -

- - - - - TRADEdotNET - Highlights :
-
- -  Easy Access - -
-
-

- A Road Map showing the user-friendly system - flow guides users throughout all steps. User can click on the menu icons, - which act as shortcuts, and enter into the desired function.

-
-  ƵIJѯѰ - -
-
-
-
- Աشͻѯ򷢳ʱ׼¼̲˷ʱ䣬һش׼ȷӴʧȥⱦĿͻѯѰֲͬʵʱѯܣܿѰݼ¼ֻҪûͻšƷšƱڵһѰѰ漴ʾ
-
- -  Perfect On-line Enquiry - -
-
-
-
- Under many circumstances, staff also need to - retrieve past transaction history for handing customer enquiry or placing - an order, however they cannot get the required information immediately and - this may drive away the customers. On-line Enquiry engine enables staff to - check past transaction with searching parameters such as key words, client - code, item code, invoice date. -
-  ļ -
-
- ϵͳʽӿԳõĴƱΪûʱӦͬռʸʽܸЧʵشճ
- -  Input - Template -
-
- The data entry journal interface is similar - to paper voucher, so that users can handle their daily accounting - transaction as they used to, yet more efficient.
- -  ޼¼  
-
- ϵͳǿ󣬲¼ޣûʱκʱڵĽ׼¼ -
-
- - -  Unlimited - Data Record  
-
- The system can store unlimited number of - records, so that users can retrieve data of any time whenever they need - it.
-  ϵͳ -
-
-
- Ƚĵϵͳ()ֻȨûģϵͳԱӦûְ趨ûȨޡ
- -  Login Control -
-
-
- Advanced access control ensures access right - is only granted to authorized users. System administrator can also define - access level of each user according to their capacity, so that confidential - information can only be retrieved and viewed by senior management.
-  ѡʽ -
-
-
- ϵͳԿʽƣֻҪSeagate Crystal Report ()Ʊʽӱ
- -  Customize Report -
-
-
- The system is designed with an open architecture - format. When the system is used with  Seagate Crystal Report Software, Users can - customize report content and format of the system.
- -  Ѕn
-
-
-
- 80%ıMS Excel/WordʽҪͼݷ֮á
- MS Excel/WordȸʽԵʸ͸йԱ
- -  Multi-Report Export Tools
-
-
-
- Over 80% of reports can be exported to MS - Excel /  Word and data can be translated into graphs and tables for - further analysis.
- Reports can also be export to MS Excel / Word format independently or send - to email client with attachment directly.
-  ʻ֧ -
-
-
-
- Ϊϲó׹˾ڹڻ賧ֹ˾Ҫݻͨ
TRADEdotNET - - ṩȫ氲ȫƽ̨װ TRADEdotNET ָ֧͸ûʱ԰װ - TRADEdotNET - - ı׼ MS ϵͳʹá
- -  Internet Ready -
-
-
-
- To facilitate data exchange between trading companies and their offices in - the Mainland China or Southeast Asia Country,
- - Install and makes use of TRADEdotNET - Internet Kit  to provide a secured platform enabling user - to access the data from different locations anytime through the internet - with TRADEdotNET - - system.
-  ݿ֧ -
-
-
-
- ΪϲͬС˾ıҪ
TRADEdotNET ṩͬݿ汾ԹѡƳ MS AccessMS SQLƳ Oracle ݿ⡣
-
- -  Multi-Database Format -
-
-
-
-
TRADEdotNET - - enables user to select - different database format versions to fit their company requirements. Now - users can choose from MS - Access and MS SQL version.  Oracle and other database formats are coming soon.
-  ֹ֧ -
-
-
- ֶ֧ûֶ֧๫˾ֶ֧ңֶ֧棬ֶ֧(/Ӣ) -
- -  Multiple Functionality -
-
-
- Support multi-users, multi-companies, - multi-currencies, multi-inventory, multi-languages (Chinese / English).
- - -  ϵͳҪ - -
-

- ̨
- Intel Pentium II () Processor PC
- Windows 98, ME, 2000 Windows NT 4.0
- 64 MB RAMƼ128MB
- 256ɫ֮SVGAʾ
- 50MBӲ̿ռ
- Windows 98, ME, 2000 Windows NT 4.0 ֧֮ӡ
- - - -  System - Requirements - - -
-

- - Workstation
- Intel Pentium II (or above) Processor PC
- Windows 98, ME, 2000 or Windows NT 4.0
- 64MB RAM - minimum 128MB - recommended
- 256 color SVGA display or higher
- 50MB free Hard Disk
- Printers - supported by - Windows 98, ME, 2000 Windows NT 4.0
-
- -  Χ - -
-
- ϵͳʾ
-      ϵͳʾ -
-
- ϵͳװ
-      ϵͳװɱ˾רҵʦ -
-
- ݱݼԭ
-      Ϊͻ趨ݱݼԭťϿͻ֮豸
-
- ļʽ
-      Ϊͻļʽ߹˾()
-
- ϵͳִ
-      Ϊ趨ϵͳ̱ŵִ -
-
- ûѵ
-      ûѵڿͻ칫ңҲ޴ -
-
- ϵͳѯ
-      ṩЧֱӵѯ񣬴ϵͳ -
-
- ϵͳ
-      ѱ -
-      ڱΪͻϵͳ -
- -  Services - Provided - -
-
- System Demonstration
-      Free-of-charge system demonstration in client's office
-
- System Installation
-      - On-site - installation - by our - professional - engineers
-
- Backup/Restore
-      Setups of backup and restore icons associated with client's backup device (e.g. Zip Drive, MO)
-
- Tailored Format
-      Tailored designs on document formats to highlight and promote company image
-
- System Implementation
-      - Implementation - procedures - customized for - each - organization
-
- User Training
-      Unlimited training is provided in the client's office -
-
- Hot-line Enquiry
-      Efficient hot-line support for all system enquiries
-
- System Maintenance
-      Half-a-year free maintenance
-      Free - upgrade - services - throughout - warranty - periods
-
-
- - - - -
-
- ӭ Ԥ Լ ʾ   : (852) 2591 9377

Ѷ - ˾  Superdata International Ltd.
- Tel: (852) 2591 9377

-

- - - *All prices, - conditions and - system - specifications - are subject to - change without - prior notice. - м۸漰ϵͳ֮޸ģ֪ͨ - -

- - diff --git a/camel/tests/mime-filter/charset-gb2312.0.out b/camel/tests/mime-filter/charset-gb2312.0.out deleted file mode 100644 index 8dcae6bdfc..0000000000 --- a/camel/tests/mime-filter/charset-gb2312.0.out +++ /dev/null @@ -1,448 +0,0 @@ - - - - -一站式的贸易、库存及会计管理系统 An all-in-one solution for trading, inventory, accounting management - - - - - - - - - - - - - - - - -
-

- - - - - TRADEdotNET - -  
-
是一站式的贸易、库存及会计管理系统,助您精简周而复始的资料输入、数据处理及各类报价、发票、存仓、日记帐、传票、报表等所需的文件行政工作,让您更有效地管理贸易、库存及会计事务。

-

- - - - - TRADEdotNET - -  
- What's the most annoying part during your - work? -
Endless repetitive data - entry, calculation and paper work on quotation, invoice, inventory - management, daily voucher, journal and reporting? Once you have installed - TRADEdotNET, all of these - annoying work will never appear in your office again!
- TRADEdotNET
is an all-in-one solution for trading, inventory, - accounting management. In the TRADEdotNET  - environment, all data can be continuously retrieved and reused. This will - help you for minimizing time consumed on data entry and enhancing - efficiency.

- - TRADEdotNET - 分别由组系统组成:贸易订单管理、库存管理及会计系统 - - TRADEdotNET - Containing Trading Management - Module, Inventory Management Module and Accounting Management Module.
-

-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - TRADEdotNET - 的优点
-
-  简易系统登入 - -
-
-

- 简单易明的操作流程图显示整个系统的主要流程,引导用户顺利完成每一个步骤。用户只须按下流程图的图像,即系统快捷方式,便可进入特定的功能画面。
- - -

- - - - - TRADEdotNET - Highlights :
-
- -  Easy Access - -
-
-

- A Road Map showing the user-friendly system - flow guides users throughout all steps. User can click on the menu icons, - which act as shortcuts, and enter into the desired function.

-
-  完善的查询搜寻器 - -
-
-
-
- 当员工回答客户查询或发出订单,经常需时翻查以往交易纪录,这个过程不仅浪费时间,万一回答不准确,更可能令您从此失去这宝贵的客户。查询搜寻器多种不同的实时查询功能,能快速搜寻所需的数据纪录,只要用户输入客户编号、货品编号、发票日期等其中一项搜寻参数,搜寻结果随即显示。
-
- -  Perfect On-line Enquiry - -
-
-
-
- Under many circumstances, staff also need to - retrieve past transaction history for handing customer enquiry or placing - an order, however they cannot get the required information immediately and - this may drive away the customers. On-line Enquiry engine enables staff to - check past transaction with searching parameters such as key words, client - code, item code, invoice date. -
-  文件输入 -
-
- 系统的总帐接口设计以常用的传票为蓝本,用户无需费时重新适应不同日记帐格式,而且能更有效率地处理日常会计帐项数据输入程序。
- -  Input - Template -
-
- The data entry journal interface is similar - to paper voucher, so that users can handle their daily accounting - transaction as they used to, yet more efficient.
- -  无限纪录储存  
-
- 系统容量强大,不设纪录储存年期上限,因此用户可以随时查阅任何时期的交易纪录。 -
-
- - -  Unlimited - Data Record  
-
- The system can store unlimited number of - records, so that users can retrieve data of any time whenever they need - it.
-  系统登入监控 -
-
-
- 先进的登入监控系统保障(机密)数据只供授权用户查阅,系统管理员亦可以因应用户的职级而设定个别用户的阅览权限。
- -  Login Control -
-
-
- Advanced access control ensures access right - is only granted to authorized users. System administrator can also define - access level of each user according to their capacity, so that confidential - information can only be retrieved and viewed by senior management.
-  自选报表格式 -
-
-
- 系统报表以开放式设计,只需要配合Seagate Crystal Report (另购),即可自行设计报表格式或增加报表。
- -  Customize Report -
-
-
- The system is designed with an open architecture - format. When the system is used with  Seagate Crystal Report Software, Users can - customize report content and format of the system.
- -  多向列n报表工具
-
-
-
- 超过80%的报表可以MS Excel/Word格式输出,按需要而制作图表供数据分析之用。
- 报表可以MS Excel/Word等格式独立输出或以电邮附带传送给有关人员。
- -  Multi-Report Export Tools
-
-
-
- Over 80% of reports can be exported to MS - Excel /  Word and data can be translated into graphs and tables for - further analysis.
- Reports can also be export to MS Excel / Word format independently or send - to email client with attachment directly.
-  国际互联支持 -
-
-
-
- 为了配合不少贸易公司于国内或东南亚设厂或分公司而需要数据数据互通,
TRADEdotNET - - 提供全面安全的整合平台,安装 TRADEdotNET 互联网支持附件,透过互联网,用户即可随时随地以安装了 - TRADEdotNET - - 的标准 MS 操作系统登入使用。
- -  Internet Ready -
-
-
-
- To facilitate data exchange between trading companies and their offices in - the Mainland China or Southeast Asia Country,
- - Install and makes use of TRADEdotNET - Internet Kit  to provide a secured platform enabling user - to access the data from different locations anytime through the internet - with TRADEdotNET - - system.
-  多种数据库支持 -
-
-
-
- 为了配合不同大小公司的本身需要,
TRADEdotNET 提供不同数据库版本以供选择。已推出有 MS Access、MS SQL,即将推出有 Oracle 及其它数据库。
-  
- -  Multi-Database Format -
-
-
-
-
TRADEdotNET - - enables user to select - different database format versions to fit their company requirements. Now - users can choose from MS - Access and MS SQL version.  Oracle and other database formats are coming soon.
-  其它支持功能 -
-
-
- 支持多用户,支持多公司,支持多货币,支持多库存,支持多语言(中文/英文) -
- -  Multiple Functionality -
-
-
- Support multi-users, multi-companies, - multi-currencies, multi-inventory, multi-languages (Chinese / English).
- - -  系统要求 - -
-

- 工作台
- Intel Pentium II (或以上) Processor PC
- Windows 98, ME, 2000 或 Windows NT 4.0
- 最少用 64 MB RAM,推荐用128MB
- 256色或以上之SVGA显示器
- 50MB硬盘空间
- Windows 98, ME, 2000 或 Windows NT 4.0 支持之打印机
- - - -  System - Requirements - - -
-

- - Workstation
- Intel Pentium II (or above) Processor PC
- Windows 98, ME, 2000 or Windows NT 4.0
- 64MB RAM - minimum, 128MB - recommended
- 256 color SVGA display or higher
- 50MB free Hard Disk
- Printers - supported by - Windows 98, ME, 2000 或 Windows NT 4.0
-  
- -  服务范围 - -
-
- 系统示范
-      免费上门作系统示范 - 。
-
- 系统安装
-      系统安装会由本公司专业工程师负责 - 。
-
- 数据备份及还原
-      免费为客户设定数据备份及还原按钮,以配合客户之‘备份设备’。
-
- 度身订做文件式样
-      为客户度身订做文件式样,提高公司形象(另费)。
-
- 系统执行
-      为各机构设定系统流程表及监察各部门的执行情况 - 。
-
- 用户培训
-      用户培训可设在客户办公室,而且不限次数 - 。
-
- 系统咨询热线
-      提供有效直接的热线咨询服务,处理系统疑难 - 。
-
- 系统保养
-      半年免费保养 - ;
-      于保养期内免费为客户作系统提升 - 。
- -  Services - Provided - -
-
- System Demonstration
-      Free-of-charge system demonstration in client's office
-
- System Installation
-      - On-site - installation - by our - professional - engineers
-
- Backup/Restore
-      Setups of backup and restore icons associated with client's backup device (e.g. Zip Drive, MO)
-
- Tailored Format
-      Tailored designs on document formats to highlight and promote company image
-
- System Implementation
-      - Implementation - procedures - customized for - each - organization
-
- User Training
-      Unlimited training is provided in the client's office -
-
- Hot-line Enquiry
-      Efficient hot-line support for all system enquiries
-
- System Maintenance
-      Half-a-year free maintenance
-      Free - upgrade - services - throughout - warranty - periods
-
-
- - - - -
-
- 欢 迎 预 约 示 范 请电 : (852) 2591 9377

精 讯 国 际 有 - 限 公 司  Superdata International Ltd.
- Tel: (852) 2591 9377

-

- - - *All prices, - conditions and - system - specifications - are subject to - change without - prior notice. - 所有价格,条规及系统规格之修改,将不另行通知。 - - 

- - diff --git a/camel/tests/mime-filter/charset-iso-2022-jp.0.in b/camel/tests/mime-filter/charset-iso-2022-jp.0.in deleted file mode 100644 index 8c23b208ce..0000000000 --- a/camel/tests/mime-filter/charset-iso-2022-jp.0.in +++ /dev/null @@ -1,5 +0,0 @@ -$B$($m$$#t#y$&$H$&$#$&$$$(#y$F#r$A$&$(#r#y$H#y#r$H$($D$*#3#9#4#5#0#9#8#0#9#4$($$#r(B -$B$H$($D$*$($&$H$($k$H$&#t(B - -Thanks & Regards, -Sures diff --git a/camel/tests/mime-filter/charset-iso-2022-jp.0.out b/camel/tests/mime-filter/charset-iso-2022-jp.0.out deleted file mode 100644 index c66c5f79ce..0000000000 --- a/camel/tests/mime-filter/charset-iso-2022-jp.0.out +++ /dev/null @@ -1,5 +0,0 @@ -えろいtyうとうぃういえyてrちうえryとyrとえつお3945098094えいr -とえつおえうとえるとうt - -Thanks & Regards, -Sures diff --git a/camel/tests/mime-filter/crlf-1.in b/camel/tests/mime-filter/crlf-1.in deleted file mode 100644 index d98703c725..0000000000 --- a/camel/tests/mime-filter/crlf-1.in +++ /dev/null @@ -1,19 +0,0 @@ -This is some text to filter and stuff. Hopefully that . will not become '..' -when the filter is run on this text. It should, however, '..' the next line -. The previous . should become .. in the output file, or so I hope... - -. -.. -... -.... - -Once this text is decoded again, the above set of dots should look like: - - . - .. - ... - .... - -Only it shouldn't be indented, obviously. - -Jeff \ No newline at end of file diff --git a/camel/tests/mime-filter/crlf-1.out b/camel/tests/mime-filter/crlf-1.out deleted file mode 100644 index c0b688f334..0000000000 --- a/camel/tests/mime-filter/crlf-1.out +++ /dev/null @@ -1,19 +0,0 @@ -This is some text to filter and stuff. Hopefully that . will not become '..' -when the filter is run on this text. It should, however, '..' the next line -.. The previous . should become .. in the output file, or so I hope... - -.. -... -.... -..... - -Once this text is decoded again, the above set of dots should look like: - - . - .. - ... - .... - -Only it shouldn't be indented, obviously. - -Jeff \ No newline at end of file diff --git a/camel/tests/mime-filter/data/html.0.in b/camel/tests/mime-filter/data/html.0.in deleted file mode 100644 index 217f85b4ff..0000000000 --- a/camel/tests/mime-filter/data/html.0.in +++ /dev/null @@ -1,10 +0,0 @@ - -College of Engineering Students, - -We are contacting you to request that you consider nominating a College -of Engineering faculty member for the College's 2003 Excellence in -Teaching Award. The award criteria and nomination form are attached. -They can also be found on the web at: - - - diff --git a/camel/tests/mime-filter/data/html.0.out b/camel/tests/mime-filter/data/html.0.out deleted file mode 100644 index 3f19310dd4..0000000000 --- a/camel/tests/mime-filter/data/html.0.out +++ /dev/null @@ -1,10 +0,0 @@ - -College of Engineering Students, - -We are contacting you to request that you consider nominating a College -of Engineering faculty member for the College's 2003 Excellence in -Teaching Award. The award criteria and nomination form are attached. -They can also be found on the web at: - - <http://www.ce.udel.edu/teaching_award.html> - <http://www.ce.udel.edu/nomination_form.html> diff --git a/camel/tests/mime-filter/data/html.1.in b/camel/tests/mime-filter/data/html.1.in deleted file mode 100644 index 8dece6113d..0000000000 --- a/camel/tests/mime-filter/data/html.1.in +++ /dev/null @@ -1,10 +0,0 @@ - -College of Engineering Students, - -We are contacting you to request that you consider nominating a College -of Engineering faculty member for the College's 2003 Excellence in -Teaching Award. The award criteria and nomination form are attached. -They can also be found on the web at: - - - \ No newline at end of file diff --git a/camel/tests/mime-filter/data/html.1.out b/camel/tests/mime-filter/data/html.1.out deleted file mode 100644 index 71a977e7ff..0000000000 --- a/camel/tests/mime-filter/data/html.1.out +++ /dev/null @@ -1,10 +0,0 @@ - -College of Engineering Students, - -We are contacting you to request that you consider nominating a College -of Engineering faculty member for the College's 2003 Excellence in -Teaching Award. The award criteria and nomination form are attached. -They can also be found on the web at: - - <http://www.ce.udel.edu/teaching_award.html> - <http://www.ce.udel.edu/nomination_form.html> \ No newline at end of file diff --git a/camel/tests/mime-filter/test-charset.c b/camel/tests/mime-filter/test-charset.c deleted file mode 100644 index 301cf3b2b7..0000000000 --- a/camel/tests/mime-filter/test-charset.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - test-crlf.c - - Test the CamelMimeFilterCharset class -*/ - -#include -#include -#include -#include - -#include "camel-test.h" - -#include -#include -#include -#include - -#define d(x) x - -#define CHUNK_SIZE 4096 - -int -main (int argc, char **argv) -{ - ssize_t comp_progress, comp_correct_chunk, comp_filter_chunk; - char comp_correct[CHUNK_SIZE], comp_filter[CHUNK_SIZE]; - CamelStream *source; - CamelStream *correct; - CamelStreamFilter *filter; - CamelMimeFilter *f; - struct dirent *dent; - int i, test = 0; - DIR *dir; - - camel_test_init(argc, argv); - - dir = opendir (SOURCEDIR); - - while ((dent = readdir (dir))) { - char *outfile, *charset, *work; - const char *ext; - - ext = strrchr (dent->d_name, '.'); - if (!(!strncmp (dent->d_name, "charset-", 8) && ext && !strcmp (ext, ".in"))) - continue; - - work = g_strdup_printf ("Charset filter, test case %d (%s)", test++, dent->d_name); - camel_test_start (work); - g_free (work); - - if (!(source = camel_stream_fs_new_with_name (dent->d_name, 0, O_RDONLY))) { - camel_test_fail ("Failed to open input case in \"%s\"", dent->d_name); - continue; - } - - outfile = g_strdup_printf ("%.*s.out", ext - dent->d_name, dent->d_name); - - if (!(correct = camel_stream_fs_new_with_name (outfile, 0, O_RDONLY))) { - camel_test_fail ("Failed to open correct output in \"%s\"", outfile); - g_free (outfile); - continue; - } - g_free (outfile); - - if (!(filter = camel_stream_filter_new_with_stream (CAMEL_STREAM (source)))) { - camel_test_fail ("Couldn't create CamelStreamFilter??"); - continue; - } - - charset = g_strdup (dent->d_name + 8); - ext = strchr (charset, '.'); - *((char *) ext) = '\0'; - - if (!(f = (CamelMimeFilter *) camel_mime_filter_charset_new_convert (charset, "UTF-8"))) { - camel_test_fail ("Couldn't create CamelMimeFilterCharset??"); - g_free (charset); - continue; - } - g_free (charset); - - camel_stream_filter_add (filter, f); - camel_object_unref (f); - - camel_test_push ("Running filter and comparing to correct result"); - - comp_progress = 0; - - while (1) { - comp_correct_chunk = camel_stream_read (correct, comp_correct, CHUNK_SIZE); - comp_filter_chunk = 0; - - if (comp_correct_chunk == 0) - break; - - while (comp_filter_chunk < comp_correct_chunk) { - ssize_t delta; - - delta = camel_stream_read (CAMEL_STREAM (filter), - comp_filter + comp_filter_chunk, - CHUNK_SIZE - comp_filter_chunk); - - if (delta == 0) { - camel_test_fail ("Chunks are different sizes: correct is %d, " - "filter is %d, %d bytes into stream", - comp_correct_chunk, comp_filter_chunk, comp_progress); - } - - comp_filter_chunk += delta; - } - - for (i = 0; i < comp_filter_chunk; i++) { - if (comp_correct[i] != comp_filter[i]) { - camel_test_fail ("Difference: correct is %c, filter is %c, " - "%d bytes into stream", - comp_correct[i], - comp_filter[i], - comp_progress + i); - } - } - - comp_progress += comp_filter_chunk; - } - - camel_test_pull (); - - /* inefficient */ - camel_test_push ("Cleaning up"); - camel_object_unref (CAMEL_OBJECT (filter)); - camel_object_unref (CAMEL_OBJECT (correct)); - camel_object_unref (CAMEL_OBJECT (source)); - camel_test_pull (); - - camel_test_end (); - } - - closedir (dir); - - return 0; -} diff --git a/camel/tests/mime-filter/test-crlf.c b/camel/tests/mime-filter/test-crlf.c deleted file mode 100644 index bbf443be09..0000000000 --- a/camel/tests/mime-filter/test-crlf.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - test-crlf.c - - Test the CamelMimeFilterCrlf class -*/ - -#include -#include - -#include "camel-test.h" - -#include -#include -#include -#include - -#define d(x) x - -#define NUM_CASES 1 -#define CHUNK_SIZE 4096 - -enum { - CRLF_ENCODE, - CRLF_DECODE, - CRLF_DONE -}; - -int -main (int argc, char **argv) -{ - CamelStream *source; - CamelStream *correct; - CamelStreamFilter *filter; - CamelMimeFilter *sh; - char *work; - int i; - ssize_t comp_progress, comp_correct_chunk, comp_filter_chunk; - int comp_i; - char comp_correct[CHUNK_SIZE], comp_filter[CHUNK_SIZE]; - - camel_test_init(argc, argv); - - for (i = 0; i < NUM_CASES; i++) { - int j; - - work = g_strdup_printf ("CRLF/DOT filter, test case %d", i); - camel_test_start (work); - g_free (work); - - for (j = CRLF_ENCODE; j < CRLF_DONE; j++) { - CamelMimeFilterCRLFDirection direction; - char *infile = NULL, *outfile = NULL; - - switch (j) { - case CRLF_ENCODE: - camel_test_push ("Test of the encoder"); - direction = CAMEL_MIME_FILTER_CRLF_ENCODE; - infile = g_strdup_printf ("%s/crlf-%d.in", SOURCEDIR, i + 1); - outfile = g_strdup_printf ("%s/crlf-%d.out", SOURCEDIR, i + 1); - break; - case CRLF_DECODE: - camel_test_push ("Test of the decoder"); - direction = CAMEL_MIME_FILTER_CRLF_DECODE; - infile = g_strdup_printf ("%s/crlf-%d.out", SOURCEDIR, i + 1); - outfile = g_strdup_printf ("%s/crlf-%d.in", SOURCEDIR, i + 1); - break; - default: - break; - } - - camel_test_push ("Initializing objects"); - source = camel_stream_fs_new_with_name (infile, 0, O_RDONLY); - if (!source) { - camel_test_fail ("Failed to open input case in \"%s\"", infile); - g_free (infile); - continue; - } - g_free (infile); - - correct = camel_stream_fs_new_with_name (outfile, 0, O_RDONLY); - if (!correct) { - camel_test_fail ("Failed to open correct output in \"%s\"", outfile); - g_free (outfile); - continue; - } - g_free (outfile); - - filter = camel_stream_filter_new_with_stream (CAMEL_STREAM (source)); - if (!filter) { - camel_test_fail ("Couldn't create CamelStreamFilter??"); - continue; - } - - sh = camel_mime_filter_crlf_new (direction, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS); - if (!sh) { - camel_test_fail ("Couldn't create CamelMimeFilterCrlf??"); - continue; - } - - camel_stream_filter_add (filter, sh); - camel_test_pull (); - - camel_test_push ("Running filter and comparing to correct result"); - - comp_progress = 0; - - while (1) { - comp_correct_chunk = camel_stream_read (correct, comp_correct, CHUNK_SIZE); - comp_filter_chunk = 0; - - if (comp_correct_chunk == 0) - break; - - while (comp_filter_chunk < comp_correct_chunk) { - ssize_t delta; - - delta = camel_stream_read (CAMEL_STREAM (filter), - comp_filter + comp_filter_chunk, - CHUNK_SIZE - comp_filter_chunk); - - if (delta == 0) { - camel_test_fail ("Chunks are different sizes: correct is %d, " - "filter is %d, %d bytes into stream", - comp_correct_chunk, comp_filter_chunk, comp_progress); - } - - comp_filter_chunk += delta; - } - - for (comp_i = 0; comp_i < comp_filter_chunk; comp_i++) { - if (comp_correct[comp_i] != comp_filter[comp_i]) { - camel_test_fail ("Difference: correct is %c, filter is %c, " - "%d bytes into stream", - comp_correct[comp_i], - comp_filter[comp_i], - comp_progress + comp_i); - } - } - - comp_progress += comp_filter_chunk; - } - - camel_test_pull (); - - /* inefficient */ - camel_test_push ("Cleaning up"); - camel_object_unref (CAMEL_OBJECT (filter)); - camel_object_unref (CAMEL_OBJECT (correct)); - camel_object_unref (CAMEL_OBJECT (source)); - camel_object_unref (CAMEL_OBJECT (sh)); - camel_test_pull (); - - camel_test_pull (); - } - - camel_test_end (); - } - - return 0; -} diff --git a/camel/tests/mime-filter/test-tohtml.c b/camel/tests/mime-filter/test-tohtml.c deleted file mode 100644 index 5b7842fefe..0000000000 --- a/camel/tests/mime-filter/test-tohtml.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - test-html.c - - Test the CamelMimeFilterToHTML class -*/ - -#include -#include - -#include -#include -#include -#include - -#include "camel-test.h" - -#include -#include -#include -#include - -#define d(x) x - -#define CHUNK_SIZE 4096 - -static void -test_filter(CamelMimeFilter *f, const char *inname, const char *outname) -{ - CamelStreamMem *in, *out; - CamelStream *indisk, *outdisk, *filter; - int id; - - camel_test_push("Data file `%s'", inname); - - camel_test_push("setup"); - - indisk = camel_stream_fs_new_with_name(inname, O_RDONLY, 0); - check(indisk); - outdisk = camel_stream_fs_new_with_name(outname, O_RDONLY, 0); - check(outdisk); - - out = (CamelStreamMem *)camel_stream_mem_new(); - check(camel_stream_write_to_stream(outdisk, (CamelStream *)out) > 0); - - camel_test_pull(); - - camel_test_push("reading through filter stream"); - - in = (CamelStreamMem *)camel_stream_mem_new(); - - filter = (CamelStream *)camel_stream_filter_new_with_stream(indisk); - check_count(indisk, 2); - id = camel_stream_filter_add((CamelStreamFilter *)filter, f); - check_count(f, 2); - - check(camel_stream_write_to_stream(filter, (CamelStream *)in) > 0); - check_msg(in->buffer->len == out->buffer->len - && memcmp(in->buffer->data, out->buffer->data, in->buffer->len) == 0, - "Buffer content mismatch, %d != %d, in = '%.*s' != out = '%.*s'", in->buffer->len, out->buffer->len, - in->buffer->len, in->buffer->data, out->buffer->len, out->buffer->data); - - camel_test_pull(); - - camel_stream_filter_remove((CamelStreamFilter *)filter, id); - check_count(f, 1); - camel_mime_filter_reset(f); - - check_unref(filter, 1); - check_count(indisk, 1); - check_count(f, 1); - check_unref(in, 1); - - check(camel_stream_reset(indisk) == 0); - - camel_test_push("writing through filter stream"); - - in = (CamelStreamMem *)camel_stream_mem_new(); - filter = (CamelStream *)camel_stream_filter_new_with_stream((CamelStream *)in); - check_count(in, 2); - id = camel_stream_filter_add((CamelStreamFilter *)filter, f); - check_count(f, 2); - - check(camel_stream_write_to_stream(indisk, filter) > 0); - check(camel_stream_flush(filter) == 0); - check_msg(in->buffer->len == out->buffer->len - && memcmp(in->buffer->data, out->buffer->data, in->buffer->len) == 0, - "Buffer content mismatch, %d != %d, in = '%.*s' != out = '%.*s'", in->buffer->len, out->buffer->len, - in->buffer->len, in->buffer->data, out->buffer->len, out->buffer->data); - - camel_stream_filter_remove((CamelStreamFilter *)filter, id); - check_unref(filter, 1); - check_unref(in, 1); - check_unref(indisk, 1); - check_unref(outdisk, 1); - check_unref(out, 1); - - camel_test_pull(); - - camel_test_pull(); -} - -int -main (int argc, char **argv) -{ - int i; - - camel_test_init(argc, argv); - - camel_test_start("HTML Stream filtering"); - - for (i=0;i<100;i++) { - char inname[32], outname[32]; - CamelMimeFilter *f; - struct stat st; - - sprintf(inname, "data/html.%d.in", i); - sprintf(outname, "data/html.%d.out", i); - - if (stat(inname, &st) == -1) - break; - - f = camel_mime_filter_tohtml_new(CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); - - test_filter(f, inname, outname); - - check_unref(f, 1); - } - - camel_test_end(); - - return 0; -} diff --git a/camel/tests/misc/.cvsignore b/camel/tests/misc/.cvsignore deleted file mode 100644 index fbb8316a8b..0000000000 --- a/camel/tests/misc/.cvsignore +++ /dev/null @@ -1,14 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov -split -url -utf7 \ No newline at end of file diff --git a/camel/tests/misc/Makefile.am b/camel/tests/misc/Makefile.am deleted file mode 100644 index d3ed29f2e6..0000000000 --- a/camel/tests/misc/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ - -INCLUDES = \ - -I$(includedir) \ - -I$(top_srcdir) \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/camel/tests/lib \ - -DG_LOG_DOMAIN=\"evolution-tests\" \ - $(CAMEL_CFLAGS) - -LDADD = \ - $(top_builddir)/camel/libcamel.la \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/camel/tests/lib/libcameltest.a \ - $(INTLLIBS) \ - $(EVOLUTION_MAIL_LIBS) - -check_PROGRAMS = \ - url \ - utf7 \ - split - -TESTS = url utf7 split - - - diff --git a/camel/tests/misc/README b/camel/tests/misc/README deleted file mode 100644 index e92f579cf6..0000000000 --- a/camel/tests/misc/README +++ /dev/null @@ -1,4 +0,0 @@ - -url URL parsing -utf7 UTF7 and UTF8 processing -split word splitting for searching diff --git a/camel/tests/misc/split.c b/camel/tests/misc/split.c deleted file mode 100644 index 254b91974f..0000000000 --- a/camel/tests/misc/split.c +++ /dev/null @@ -1,113 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "camel-test.h" - -/* TODO: should put utf8 stuff here too */ - -static struct { - char *word; - int count; - struct { - char *word; - int type; - } splits[5]; -} split_tests[] = { - { "simple", 1, { { "simple", CAMEL_SEARCH_WORD_SIMPLE } } }, - { "two words", 2, { { "two", CAMEL_SEARCH_WORD_SIMPLE }, {"words" , CAMEL_SEARCH_WORD_SIMPLE } } }, - { "compl;ex", 1, { { "compl;ex", CAMEL_SEARCH_WORD_COMPLEX } } }, - { "compl;ex simple", 2, { { "compl;ex", CAMEL_SEARCH_WORD_COMPLEX} , {"simple", CAMEL_SEARCH_WORD_SIMPLE} } }, - { "\"quoted\"", 1, { { "quoted", CAMEL_SEARCH_WORD_SIMPLE } } }, - { "\"quoted double\"", 1, { { "quoted double", CAMEL_SEARCH_WORD_COMPLEX } } }, - { "\"quoted double\" compl;ex", 2, { { "quoted double", CAMEL_SEARCH_WORD_COMPLEX }, { "compl;ex", CAMEL_SEARCH_WORD_COMPLEX } } }, - { "\"quoted double \\\" escaped\"", 1, { { "quoted double \" escaped", CAMEL_SEARCH_WORD_COMPLEX } } }, - { "\"quoted\\\"double\" \\\" escaped\\\"", 3, { { "quoted\"double", CAMEL_SEARCH_WORD_COMPLEX }, {"\"", CAMEL_SEARCH_WORD_COMPLEX}, { "escaped\"", CAMEL_SEARCH_WORD_COMPLEX } } }, - { "\\\"escaped", 1, { { "\"escaped", CAMEL_SEARCH_WORD_COMPLEX } } }, - -}; -#define SPLIT_LENGTH (sizeof(split_tests)/sizeof(split_tests[0])) - -static struct { - char *word; - int count; - struct { - char *word; - int type; - } splits[5]; -} simple_tests[] = { - { "simple", 1, { {"simple", CAMEL_SEARCH_WORD_SIMPLE } } }, - { "simpleCaSe", 1, { { "simplecase", CAMEL_SEARCH_WORD_SIMPLE } } }, - { "two words", 2, { { "two", CAMEL_SEARCH_WORD_SIMPLE }, { "words", CAMEL_SEARCH_WORD_SIMPLE } } }, - { "two wordscAsE", 2, { { "two", CAMEL_SEARCH_WORD_SIMPLE} , { "wordscase", CAMEL_SEARCH_WORD_SIMPLE } } }, - { "compl;ex", 2, { { "compl", CAMEL_SEARCH_WORD_SIMPLE }, { "ex", CAMEL_SEARCH_WORD_SIMPLE } } }, - { "compl;ex simple", 3, { { "compl", CAMEL_SEARCH_WORD_SIMPLE }, { "ex", CAMEL_SEARCH_WORD_SIMPLE }, { "simple", CAMEL_SEARCH_WORD_SIMPLE } } }, - { "\"quoted compl;ex\" simple", 4, { { "quoted", CAMEL_SEARCH_WORD_SIMPLE}, { "compl", CAMEL_SEARCH_WORD_SIMPLE }, { "ex", CAMEL_SEARCH_WORD_SIMPLE }, { "simple", CAMEL_SEARCH_WORD_SIMPLE } } }, - { "\\\" \"quoted\"compl;ex\" simple", 4, { { "quoted", CAMEL_SEARCH_WORD_SIMPLE}, { "compl", CAMEL_SEARCH_WORD_SIMPLE }, { "ex", CAMEL_SEARCH_WORD_SIMPLE }, { "simple", CAMEL_SEARCH_WORD_SIMPLE } } }, -}; - -#define SIMPLE_LENGTH (sizeof(simple_tests)/sizeof(simple_tests[0])) - -int -main (int argc, char **argv) -{ - int i, j; - struct _camel_search_words *words, *tmp; - - camel_test_init(argc, argv); - - camel_test_start("Search splitting"); - - for (i=0; ilen == split_tests[i].count, "words->len = %d, count = %d", words->len, split_tests[i].count); - - for (j=0;jlen;j++) { - check_msg(strcmp(split_tests[i].splits[j].word, words->words[j]->word) == 0, - "'%s' != '%s'", split_tests[i].splits[j].word, words->words[j]->word); - check(split_tests[i].splits[j].type == words->words[j]->type); - } - - camel_search_words_free(words); - camel_test_pull(); - } - - camel_test_end(); - - camel_test_start("Search splitting - simple"); - - for (i=0; ilen == simple_tests[i].count, "words->len = %d, count = %d", words->len, simple_tests[i].count); - - for (j=0;jlen;j++) { - check_msg(strcmp(simple_tests[i].splits[j].word, words->words[j]->word) == 0, - "'%s' != '%s'", simple_tests[i].splits[j].word, words->words[j]->word); - check(simple_tests[i].splits[j].type == words->words[j]->type); - } - - camel_search_words_free(words); - camel_search_words_free(tmp); - camel_test_pull(); - } - - camel_test_end(); - - return 0; -} diff --git a/camel/tests/misc/url.c b/camel/tests/misc/url.c deleted file mode 100644 index c2db806621..0000000000 --- a/camel/tests/misc/url.c +++ /dev/null @@ -1,123 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include - -#include "camel-test.h" - -char *base = "http://a/b/c/d;p?q#f"; - -struct { - char *url_string, *result; -} tests[] = { - { "g:h", "g:h" }, - { "g", "http://a/b/c/g" }, - { "./g", "http://a/b/c/g" }, - { "g/", "http://a/b/c/g/" }, - { "/g", "http://a/g" }, - { "//g", "http://g" }, - { "?y", "http://a/b/c/d;p?y" }, - { "g?y", "http://a/b/c/g?y" }, - { "g?y/./x", "http://a/b/c/g?y/./x" }, - { "#s", "http://a/b/c/d;p?q#s" }, - { "g#s", "http://a/b/c/g#s" }, - { "g#s/./x", "http://a/b/c/g#s/./x" }, - { "g?y#s", "http://a/b/c/g?y#s" }, - { ";x", "http://a/b/c/d;x" }, - { "g;x", "http://a/b/c/g;x" }, - { "g;x?y#s", "http://a/b/c/g;x?y#s" }, - { ".", "http://a/b/c/" }, - { "./", "http://a/b/c/" }, - { "..", "http://a/b/" }, - { "../", "http://a/b/" }, - { "../g", "http://a/b/g" }, - { "../..", "http://a/" }, - { "../../", "http://a/" }, - { "../../g", "http://a/g" }, - { "", "http://a/b/c/d;p?q#f" }, - { "../../../g", "http://a/../g" }, - { "../../../../g", "http://a/../../g" }, - { "/./g", "http://a/./g" }, - { "/../g", "http://a/../g" }, - { "g.", "http://a/b/c/g." }, - { ".g", "http://a/b/c/.g" }, - { "g..", "http://a/b/c/g.." }, - { "..g", "http://a/b/c/..g" }, - { "./../g", "http://a/b/g" }, - { "./g/.", "http://a/b/c/g/" }, - { "g/./h", "http://a/b/c/g/h" }, - { "g/../h", "http://a/b/c/h" }, - { "http:g", "http:g" }, - { "http:", "http:" }, - - /* (not from rfc 1808) */ - { "sendmail:", "sendmail:" }, - { "mbox:/var/mail/user", "mbox:/var/mail/user" }, - { "pop://user@host", "pop://user@host" }, - { "pop://user@host:99", "pop://user@host:99" }, - { "pop://user:password@host", "pop://user:password@host" }, - { "pop://user:password@host:99", "pop://user:password@host:99" }, - { "pop://user;auth=APOP@host", "pop://user;auth=APOP@host" }, - { "pop://user@host/;keep_on_server", "pop://user@host/;keep_on_server" }, - { "pop://user@host/;keep_on_server=1", "pop://user@host/;keep_on_server=1" }, - { "pop://us%65r@host", "pop://user@host" }, - { "pop://us%40r@host", "pop://us%40r@host" }, - { "pop://us%3ar@host", "pop://us%3ar@host" }, - { "pop://us%2fr@host", "pop://us%2fr@host" } -}; -int num_tests = sizeof (tests) / sizeof (tests[0]); - -int -main (int argc, char **argv) -{ - CamelURL *base_url, *url; - CamelException ex; - char *url_string; - int i; - - camel_test_init (argc, argv); - - camel_test_start ("URL parsing"); - - camel_test_push ("base URL parsing"); - camel_exception_init (&ex); - base_url = camel_url_new (base, &ex); - if (!base_url) { - camel_test_fail ("Could not parse %s: %s\n", base, - camel_exception_get_description (&ex)); - } - camel_test_pull (); - - camel_test_push ("base URL unparsing"); - url_string = camel_url_to_string (base_url, 0); - if (strcmp (url_string, base) != 0) { - camel_test_fail ("URL <%s> unparses to <%s>\n", - base, url_string); - } - camel_test_pull (); - g_free (url_string); - - for (i = 0; i < num_tests; i++) { - camel_test_push ("<%s> + <%s> = <%s>?", base, tests[i].url_string, tests[i].result); - url = camel_url_new_with_base (base_url, tests[i].url_string); - if (!url) { - camel_test_fail ("could not parse"); - camel_test_pull (); - continue; - } - - url_string = camel_url_to_string (url, 0); - if (strcmp (url_string, tests[i].result) != 0) - camel_test_fail ("got <%s>!", url_string); - g_free (url_string); - camel_test_pull (); - } - - camel_test_end (); - - return 0; -} diff --git a/camel/tests/misc/utf7.c b/camel/tests/misc/utf7.c deleted file mode 100644 index dec0f4b7e5..0000000000 --- a/camel/tests/misc/utf7.c +++ /dev/null @@ -1,106 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "camel-test.h" - -static struct { - unsigned char *utf8; - char *utf7; - guint32 unicode[200]; -} tests[] = { - /* the escape char */ - { "&", "&-", - { 0x0026, } }, - /* part of set D */ - { "+", "+", - { 0x002b, } }, - { "plain ascii text", "plain ascii text", - { 0x0070, 0x006c, 0x0061, 0x0069, 0x006e, 0x0020, 0x0061, 0x0073, 0x0063, 0x0069, 0x0069, 0x0020, 0x0074, 0x0065, 0x0078, 0x0074, } }, - /* part of set O */ - { "'(),-./:?", "'(),-./:?", - { 0x0027, 0x0028, 0x0029, 0x002c, 0x002d, 0x002e, 0x002f, 0x003a, 0x003f, } }, - { "!\"#$%*+-;<=>@[]^_`{|}", "!\"#$%*+-;<=>@[]^_`{|}", - { 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x002a, 0x002b, 0x002d, 0x003b, 0x003c, 0x003d, 0x003e, 0x0040, 0x005b, 0x005d, 0x005e, 0x005f, 0x0060, 0x007b, 0x007c, 0x007d, } }, - /* example strings from rfc1642 (modified for imap utf7) */ - { "A\xe2\x89\xa2\xce\x91" ".", "A&ImIDkQ-.", - { 0x0041, 0x2262, 0x0391, 0x002e, } }, - { "Hi Mum \xe2\x98\xba!", "Hi Mum &Jjo-!", - { 0x0048, 0x0069, 0x0020, 0x004d, 0x0075, 0x006d, 0x0020, 0x263a, 0x0021, } }, - { "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e", "&ZeVnLIqe-", - { 0x65e5, 0x672c, 0x8a9e, } }, - { "Item 3 is \xc2\xa3" "1.", "Item 3 is &AKM-1.", - { 0x0049, 0x0074, 0x0065, 0x006d, 0x0020, 0x0033, 0x0020, 0x0069, 0x0073, 0x0020, 0x00a3, 0x0031, 0x002e, } }, - { "\"The sayings of Confucius,\" James R. Ware, trans. \xe5\x8f\xb0\xe5\x8c\x97:\xe6\x96\x87\xe8\x87\xb4\xe5\x87\xba\xe7\x89\x88\xe7\xa4\xbe, 1980. (Chinese text with English translation)\xe5\x9b\x9b\xe6\x9b\xb8\xe4\xba\x94\xe7\xb6\x93, \xe5\xae\x8b\xe5\x85\x83\xe4\xba\xba\xe6\xb3\xa8, \xe5\x8c\x97\xe4\xba\xac: \xe4\xb8\xad\xe5\x9c\x8b\xe6\x9b\xb8\xe5\xba\x97, 1990.", - "\"The sayings of Confucius,\" James R. Ware, trans. &U,BTFw-:&ZYeB9FH6ckh5Pg-, 1980. (Chinese text with English translation)&Vttm+E6UfZM-, &W4tRQ066bOg-, &UxdOrA-: &Ti1XC2b4Xpc-, 1990.", - { 0x0022, 0x0054, 0x0068, 0x0065, 0x0020, 0x0073, 0x0061, 0x0079, 0x0069, 0x006e, 0x0067, 0x0073, 0x0020, 0x006f, 0x0066, 0x0020, 0x0043, 0x006f, 0x006e, 0x0066, 0x0075, 0x0063, 0x0069, 0x0075, 0x0073, 0x002c, 0x0022, 0x0020, 0x004a, 0x0061, 0x006d, 0x0065, 0x0073, 0x0020, 0x0052, 0x002e, 0x0020, 0x0057, 0x0061, 0x0072, 0x0065, 0x002c, 0x0020, 0x0074, 0x0072, 0x0061, 0x006e, 0x0073, 0x002e, 0x0020, 0x0020, 0x53f0, 0x5317, 0x003a, 0x6587, 0x81f4, 0x51fa, 0x7248, 0x793e, 0x002c, 0x0020, 0x0031, 0x0039, 0x0038, 0x0030, 0x002e, 0x0020, 0x0020, 0x0028, 0x0043, 0x0068, 0x0069, 0x006e, 0x0065, 0x0073, 0x0065, 0x0020, 0x0074, 0x0065, 0x0078, 0x0074, 0x0020, 0x0077, 0x0069, 0x0074, 0x0068, 0x0020, 0x0045, 0x006e, 0x0067, 0x006c, 0x0069, 0x0073, 0x0068, 0x0020, 0x0074, 0x0072, 0x0061, 0x006e, 0x0073, 0x006c, 0x0061, 0x0074, 0x0069, 0x006f, 0x006e, 0x0029, 0x56db, 0x66f8, 0x4e94, 0x7d93, 0x002c, 0x0020, 0x5b8b, 0x5143, 0x4eba, 0x6ce8, 0x002c, 0x0020, 0x5317, 0x4eac, 0x003a, 0x0020, 0x0020, 0x4e2d, 0x570b, 0x66f8, 0x5e97, 0x002c, 0x0020, 0x0031, 0x0039, 0x0039, 0x0030, 0x002e, } }, -}; -#define TESTS_LENGTH (sizeof(tests)/sizeof(tests[0])) - -int -main (int argc, char **argv) -{ - char *utf8, *utf7, *p; - int i, j; - guint32 u; - char utf8enc[256]; - GString *out; - - camel_test_init(argc, argv); - - out = g_string_new(""); - - camel_test_start("UTF8, UTF7 RFC1642+RFC2060"); - - for (i=0; iutf8", i, tests[i].utf7); - utf8 = camel_utf7_utf8(tests[i].utf7); - check_msg(strcmp(utf8, tests[i].utf8) == 0, "utf8 = '%s'", utf8); - camel_test_pull(); - - camel_test_push("%2d: %s utf7->utf8->utf7", i, tests[i].utf7); - utf7 = camel_utf8_utf7(utf8); - check_msg(strcmp(utf7, tests[i].utf7) == 0, "utf7 = '%s'", utf7); - camel_test_pull(); - - g_free(utf7); - g_free(utf8); - - camel_test_push("%2d: %s utf8 encode", i, tests[i].utf7); - - g_string_truncate(out, 0); - p = utf8enc; - j = 0; - do { - u = tests[i].unicode[j++]; - camel_utf8_putc((unsigned char **)&p, u); - g_string_append_u(out, u); - } while (u); - - check(strcmp(utf8enc, out->str) == 0); - check(strcmp(utf8enc, tests[i].utf8) == 0); - - camel_test_pull(); - } - - camel_test_end(); - - return 0; -} diff --git a/camel/tests/smime/.cvsignore b/camel/tests/smime/.cvsignore deleted file mode 100644 index c0feca5888..0000000000 --- a/camel/tests/smime/.cvsignore +++ /dev/null @@ -1,5 +0,0 @@ -.deps -.libs -Makefile* -pgp -pgp-mime diff --git a/camel/tests/smime/Makefile.am b/camel/tests/smime/Makefile.am deleted file mode 100644 index b14d804dc3..0000000000 --- a/camel/tests/smime/Makefile.am +++ /dev/null @@ -1,24 +0,0 @@ - -INCLUDES = \ - -I$(includedir) \ - -I$(top_srcdir) \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/camel/tests/lib \ - -DG_LOG_DOMAIN=\"evolution-tests\" \ - $(CAMEL_CFLAGS) - -LDADD = \ - $(top_builddir)/camel/libcamel.la \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/camel/tests/lib/libcameltest.a \ - $(INTLLIBS) \ - $(EVOLUTION_MAIL_LIBS) - -check_PROGRAMS = \ - pgp -# pgp-mime -# pkcs7 - -TESTS = pgp #pgp-mime pkcs7 diff --git a/camel/tests/smime/README b/camel/tests/smime/README deleted file mode 100644 index baad91ba00..0000000000 --- a/camel/tests/smime/README +++ /dev/null @@ -1,2 +0,0 @@ -pgp PGP test suite - diff --git a/camel/tests/smime/pgp-mime.c b/camel/tests/smime/pgp-mime.c deleted file mode 100644 index 102092679a..0000000000 --- a/camel/tests/smime/pgp-mime.c +++ /dev/null @@ -1,214 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "camel-test.h" -#include "session.h" - -static char test_msg[] = "Since we need to make sure that\nFrom lines work okay, we should test that" -"as well as test 8bit chars and other fun stuff? 8bit chars: Draen Kaar\n\nOkay, I guess that covers" -"the basics at least...\n"; - - -#define CAMEL_PGP_SESSION_TYPE (camel_pgp_session_get_type ()) -#define CAMEL_PGP_SESSION(obj) (CAMEL_CHECK_CAST((obj), CAMEL_PGP_SESSION_TYPE, CamelPgpSession)) -#define CAMEL_PGP_SESSION_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_PGP_SESSION_TYPE, CamelPgpSessionClass)) -#define CAMEL_PGP_IS_SESSION(o) (CAMEL_CHECK_TYPE((o), CAMEL_PGP_SESSION_TYPE)) - - -typedef struct _CamelPgpSession { - CamelSession parent_object; - -} CamelPgpSession; - -typedef struct _CamelPgpSessionClass { - CamelSessionClass parent_class; - -} CamelPgpSessionClass; - - -static char *get_password (CamelSession *session, const char *prompt, - gboolean reprompt, gboolean secret, - CamelService *service, const char *item, - CamelException *ex); - -static void -init (CamelPgpSession *session) -{ - ; -} - -static void -class_init (CamelPgpSessionClass *camel_pgp_session_class) -{ - CamelSessionClass *camel_session_class = - CAMEL_SESSION_CLASS (camel_pgp_session_class); - - /* virtual method override */ - camel_session_class->get_password = get_password; -} - -static CamelType -camel_pgp_session_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register ( - camel_test_session_get_type (), - "CamelPgpSession", - sizeof (CamelPgpSession), - sizeof (CamelPgpSessionClass), - (CamelObjectClassInitFunc) class_init, - NULL, - (CamelObjectInitFunc) init, - NULL); - } - - return type; -} - -static char * -get_password (CamelSession *session, const char *prompt, gboolean reprompt, gboolean secret, - CamelService *service, const char *item, CamelException *ex) -{ - return g_strdup ("no.secret"); -} - -static CamelSession * -camel_pgp_session_new (const char *path) -{ - CamelSession *session; - - session = CAMEL_SESSION (camel_object_new (CAMEL_PGP_SESSION_TYPE)); - - camel_session_construct (session, path); - - return session; -} - - -int main (int argc, char **argv) -{ - CamelSession *session; - CamelCipherContext *ctx; - CamelException *ex; - CamelCipherValidity *valid; - CamelMimePart *mime_part; - CamelMultipartSigned *mps; - CamelMultipartEncrypted *mpe; - GPtrArray *recipients; - int ret; - - camel_test_init (argc, argv); - - /* clear out any camel-test data */ - system ("/bin/rm -rf /tmp/camel-test"); - system ("/bin/mkdir /tmp/camel-test"); - setenv ("GNUPGHOME", "/tmp/camel-test/.gnupg", 1); - - /* import the gpg keys */ - if ((ret = system ("gpg < /dev/null > /dev/null 2>&1")) == -1) - return 77; - else if (WEXITSTATUS (ret) == 127) - return 77; - - system ("gpg --import ../data/camel-test.gpg.pub > /dev/null 2>&1"); - system ("gpg --import ../data/camel-test.gpg.sec > /dev/null 2>&1"); - - session = camel_pgp_session_new ("/tmp/camel-test"); - - ex = camel_exception_new (); - - ctx = camel_gpg_context_new (session); - camel_gpg_context_set_always_trust (CAMEL_GPG_CONTEXT (ctx), TRUE); - - camel_test_start ("Test of PGP/MIME functions"); - - mime_part = camel_mime_part_new (); - camel_mime_part_set_content (mime_part, test_msg, strlen (test_msg), "text/plain"); - camel_mime_part_set_description (mime_part, "Test of PGP/MIME multipart/signed stuff"); - - camel_test_push ("PGP/MIME signing"); - mps = camel_multipart_signed_new (); - camel_multipart_signed_sign (mps, ctx, mime_part, "no.user@no.domain", CAMEL_CIPHER_HASH_SHA1, ex); - check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); - camel_test_pull (); - - camel_object_unref (mime_part); - camel_exception_clear (ex); - - camel_test_push ("PGP/MIME verify"); - valid = camel_multipart_signed_verify (mps, ctx, ex); - check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); - check_msg (camel_cipher_validity_get_valid (valid), "%s", camel_cipher_validity_get_description (valid)); - camel_cipher_validity_free (valid); - camel_test_pull (); - - camel_object_unref (mps); - camel_exception_clear (ex); - - mime_part = camel_mime_part_new (); - camel_mime_part_set_content (mime_part, test_msg, strlen (test_msg), "text/plain"); - camel_mime_part_set_description (mime_part, "Test of PGP/MIME multipart/encrypted stuff"); - - camel_test_push ("PGP/MIME encrypt"); - recipients = g_ptr_array_new (); - g_ptr_array_add (recipients, "no.user@no.domain"); - - mpe = camel_multipart_encrypted_new (); - camel_multipart_encrypted_encrypt (mpe, mime_part, ctx, "no.user@no.domain", recipients, ex); - check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); - g_ptr_array_free (recipients, TRUE); - camel_test_pull (); - - camel_exception_clear (ex); - camel_object_unref (mime_part); - - camel_test_push ("PGP/MIME decrypt"); - mime_part = camel_multipart_encrypted_decrypt (mpe, ctx, ex); - check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); - camel_object_unref (mime_part); - camel_object_unref (mpe); - camel_test_pull (); - - camel_object_unref (CAMEL_OBJECT (ctx)); - camel_object_unref (CAMEL_OBJECT (session)); - - camel_test_end (); - - return 0; -} diff --git a/camel/tests/smime/pgp.c b/camel/tests/smime/pgp.c deleted file mode 100644 index 81ea6fabdf..0000000000 --- a/camel/tests/smime/pgp.c +++ /dev/null @@ -1,246 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2003 Ximian, Inc. (www.ximian.com) - * - * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "camel-test.h" -#include "session.h" - -#define CAMEL_PGP_SESSION_TYPE (camel_pgp_session_get_type ()) -#define CAMEL_PGP_SESSION(obj) (CAMEL_CHECK_CAST((obj), CAMEL_PGP_SESSION_TYPE, CamelPgpSession)) -#define CAMEL_PGP_SESSION_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_PGP_SESSION_TYPE, CamelPgpSessionClass)) -#define CAMEL_PGP_IS_SESSION(o) (CAMEL_CHECK_TYPE((o), CAMEL_PGP_SESSION_TYPE)) - - -typedef struct _CamelPgpSession { - CamelSession parent_object; - -} CamelPgpSession; - -typedef struct _CamelPgpSessionClass { - CamelSessionClass parent_class; - -} CamelPgpSessionClass; - - -static char *get_password (CamelSession *session, const char *prompt, - gboolean reprompt, gboolean secret, - CamelService *service, const char *item, - CamelException *ex); - -static void -init (CamelPgpSession *session) -{ - ; -} - -static void -class_init (CamelPgpSessionClass *camel_pgp_session_class) -{ - CamelSessionClass *camel_session_class = - CAMEL_SESSION_CLASS (camel_pgp_session_class); - - /* virtual method override */ - camel_session_class->get_password = get_password; -} - -static CamelType -camel_pgp_session_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register ( - camel_test_session_get_type (), - "CamelPgpSession", - sizeof (CamelPgpSession), - sizeof (CamelPgpSessionClass), - (CamelObjectClassInitFunc) class_init, - NULL, - (CamelObjectInitFunc) init, - NULL); - } - - return type; -} - -static char * -get_password (CamelSession *session, const char *prompt, gboolean reprompt, gboolean secret, - CamelService *service, const char *item, CamelException *ex) -{ - return g_strdup ("no.secret"); -} - -static CamelSession * -camel_pgp_session_new (const char *path) -{ - CamelSession *session; - - session = CAMEL_SESSION (camel_object_new (CAMEL_PGP_SESSION_TYPE)); - - camel_session_construct (session, path); - - return session; -} - - -int main (int argc, char **argv) -{ - CamelSession *session; - CamelCipherContext *ctx; - CamelException *ex; - CamelCipherValidity *valid; - CamelStream *stream1, *stream2; - struct _CamelMimePart *sigpart, *conpart, *encpart, *outpart; - CamelDataWrapper *dw; - GPtrArray *recipients; - GByteArray *buf; - char *before, *after; - int ret; - - camel_test_init (argc, argv); - - /* clear out any camel-test data */ - system ("/bin/rm -rf /tmp/camel-test"); - system ("/bin/mkdir /tmp/camel-test"); - setenv ("GNUPGHOME", "/tmp/camel-test/.gnupg", 1); - - /* import the gpg keys */ - if ((ret = system ("gpg < /dev/null > /dev/null 2>&1")) == -1) - return 77; - else if (WEXITSTATUS (ret) == 127) - return 77; - - system ("gpg --import ../data/camel-test.gpg.pub > /dev/null 2>&1"); - system ("gpg --import ../data/camel-test.gpg.sec > /dev/null 2>&1"); - - session = camel_pgp_session_new ("/tmp/camel-test"); - - ex = camel_exception_new (); - - ctx = camel_gpg_context_new (session); - camel_gpg_context_set_always_trust (CAMEL_GPG_CONTEXT (ctx), TRUE); - - camel_test_start ("Test of PGP functions"); - - stream1 = camel_stream_mem_new (); - camel_stream_write (stream1, "Hello, I am a test stream.\n", 27); - camel_stream_reset (stream1); - - conpart = camel_mime_part_new(); - dw = camel_data_wrapper_new(); - camel_data_wrapper_construct_from_stream(dw, stream1); - camel_medium_set_content_object((CamelMedium *)conpart, dw); - camel_object_unref(stream1); - camel_object_unref(dw); - - sigpart = camel_mime_part_new(); - - camel_test_push ("PGP signing"); - camel_cipher_sign (ctx, "no.user@no.domain", CAMEL_CIPHER_HASH_SHA1, conpart, sigpart, ex); - check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); - camel_test_pull (); - - camel_exception_clear (ex); - - camel_test_push ("PGP verify"); - valid = camel_cipher_verify (ctx, sigpart, ex); - check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); - check_msg (camel_cipher_validity_get_valid (valid), "%s", camel_cipher_validity_get_description (valid)); - camel_cipher_validity_free (valid); - camel_test_pull (); - - camel_object_unref(conpart); - camel_object_unref(sigpart); - - stream1 = camel_stream_mem_new (); - camel_stream_write (stream1, "Hello, I am a test of encryption/decryption.", 44); - camel_stream_reset (stream1); - - conpart = camel_mime_part_new(); - dw = camel_data_wrapper_new(); - camel_stream_reset(stream1); - camel_data_wrapper_construct_from_stream(dw, stream1); - camel_medium_set_content_object((CamelMedium *)conpart, dw); - camel_object_unref(stream1); - camel_object_unref(dw); - - encpart = camel_mime_part_new(); - - camel_exception_clear (ex); - - camel_test_push ("PGP encrypt"); - recipients = g_ptr_array_new (); - g_ptr_array_add (recipients, "no.user@no.domain"); - camel_cipher_encrypt (ctx, "no.user@no.domain", recipients, conpart, encpart, ex); - check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); - g_ptr_array_free (recipients, TRUE); - camel_test_pull (); - - camel_exception_clear (ex); - - camel_test_push ("PGP decrypt"); - outpart = camel_mime_part_new(); - valid = camel_cipher_decrypt (ctx, encpart, outpart, ex); - check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); - check_msg (valid->encrypt.status == CAMEL_CIPHER_VALIDITY_ENCRYPT_ENCRYPTED, "%s", valid->encrypt.description); - - stream1 = camel_stream_mem_new(); - stream2 = camel_stream_mem_new(); - - camel_data_wrapper_write_to_stream((CamelDataWrapper *)conpart, stream1); - camel_data_wrapper_write_to_stream((CamelDataWrapper *)outpart, stream2); - - buf = CAMEL_STREAM_MEM (stream1)->buffer; - before = g_strndup (buf->data, buf->len); - buf = CAMEL_STREAM_MEM (stream2)->buffer; - after = g_strndup (buf->data, buf->len); - check_msg (string_equal (before, after), "before = '%s', after = '%s'", before, after); - g_free (before); - g_free (after); - - camel_object_unref(stream1); - camel_object_unref(stream2); - camel_object_unref(conpart); - camel_object_unref(encpart); - camel_object_unref(outpart); - - camel_test_pull (); - - camel_object_unref (CAMEL_OBJECT (ctx)); - camel_object_unref (CAMEL_OBJECT (session)); - - camel_test_end (); - - return 0; -} diff --git a/camel/tests/smime/pkcs7.c b/camel/tests/smime/pkcs7.c deleted file mode 100644 index 2248d8656d..0000000000 --- a/camel/tests/smime/pkcs7.c +++ /dev/null @@ -1,178 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -#include "camel-test.h" - - -#define CAMEL_TEST_SESSION_TYPE (camel_test_session_get_type ()) -#define CAMEL_TEST_SESSION(obj) (CAMEL_CHECK_CAST((obj), CAMEL_TEST_SESSION_TYPE, CamelTestSession)) -#define CAMEL_TEST_SESSION_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_TEST_SESSION_TYPE, CamelTestSessionClass)) -#define CAMEL_TEST_IS_SESSION(o) (CAMEL_CHECK_TYPE((o), CAMEL_TEST_SESSION_TYPE)) - - -typedef struct _CamelTestSession { - CamelSession parent_object; - -} CamelTestSession; - -typedef struct _CamelTestSessionClass { - CamelSessionClass parent_class; - -} CamelTestSessionClass; - - -static char *get_password (CamelSession *session, const char *prompt, - gboolean secret, CamelService *service, - const char *item, CamelException *ex); - -static void -init (CamelTestSession *session) -{ - ; -} - -static void -class_init (CamelTestSessionClass *camel_test_session_class) -{ - CamelSessionClass *camel_session_class = - CAMEL_SESSION_CLASS (camel_test_session_class); - - /* virtual method override */ - camel_session_class->get_password = get_password; -} - -static CamelType -camel_test_session_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register ( - camel_test_session_get_type (), - "CamelTestSession", - sizeof (CamelTestSession), - sizeof (CamelTestSessionClass), - (CamelObjectClassInitFunc) class_init, - NULL, - (CamelObjectInitFunc) init, - NULL); - } - - return type; -} - -static char * -get_password (CamelSession *session, const char *prompt, gboolean secret, - CamelService *service, const char *item, CamelException *ex) -{ - return g_strdup ("S/MIME v3 is rfc263x, now go and read them."); -} - -static CamelSession * -camel_test_session_new (const char *path) -{ - CamelSession *session; - - session = CAMEL_SESSION (camel_object_new (CAMEL_TEST_SESSION_TYPE)); - - camel_session_construct (session, path); - - return session; -} - - -int main (int argc, char **argv) -{ - CamelSession *session; - CamelSMimeContext *ctx; - CamelException *ex; - CamelCipherValidity *valid; - CamelStream *stream1, *stream2, *stream3; - GPtrArray *recipients; - GByteArray *buf; - char *before, *after; - - camel_test_init (argc, argv); - - ex = camel_exception_new (); - - /* clear out any camel-test data */ - system ("/bin/rm -rf /tmp/camel-test"); - - session = camel_test_session_new ("/tmp/camel-test"); - - ctx = camel_smime_context_new (session); - - camel_test_start ("Test of S/MIME PKCS7 functions"); - - stream1 = camel_stream_mem_new (); - camel_stream_write (stream1, "Hello, I am a test stream.", 25); - camel_stream_reset (stream1); - - stream2 = camel_stream_mem_new (); - - camel_test_push ("PKCS7 signing"); - camel_smime_sign (ctx, "smime@xtorshun.org", CAMEL_CIPHER_HASH_SHA1, - stream1, stream2, ex); - check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); - camel_test_pull (); - - camel_exception_clear (ex); - - camel_test_push ("PKCS7 verify"); - camel_stream_reset (stream1); - camel_stream_reset (stream2); - valid = camel_smime_verify (ctx, CAMEL_CIPHER_HASH_SHA1, stream1, stream2, ex); - check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); - check_msg (camel_cipher_validity_get_valid (valid), "%s", camel_cipher_validity_get_description (valid)); - camel_cipher_validity_free (valid); - camel_test_pull (); - - camel_object_unref (CAMEL_OBJECT (stream1)); - camel_object_unref (CAMEL_OBJECT (stream2)); - - stream1 = camel_stream_mem_new (); - stream2 = camel_stream_mem_new (); - stream3 = camel_stream_mem_new (); - - camel_stream_write (stream1, "Hello, I am a test of encryption/decryption.", 44); - camel_stream_reset (stream1); - - camel_exception_clear (ex); - - camel_test_push ("PKCS7 encrypt"); - recipients = g_ptr_array_new (); - g_ptr_array_add (recipients, "smime@xtorshun.org"); - camel_smime_encrypt (ctx, FALSE, "smime@xtorshun.org", recipients, - stream1, stream2, ex); - check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); - g_ptr_array_free (recipients, TRUE); - camel_test_pull (); - - camel_stream_reset (stream2); - camel_exception_clear (ex); - - camel_test_push ("PKCS7 decrypt"); - camel_smime_decrypt (ctx, stream2, stream3, ex); - check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); - buf = CAMEL_STREAM_MEM (stream1)->buffer; - before = g_strndup (buf->data, buf->len); - buf = CAMEL_STREAM_MEM (stream3)->buffer; - after = g_strndup (buf->data, buf->len); - check_msg (string_equal (before, after), "before = '%s', after = '%s'", before, after); - g_free (before); - g_free (after); - camel_test_pull (); - - camel_object_unref (CAMEL_OBJECT (ctx)); - camel_object_unref (CAMEL_OBJECT (session)); - - camel_test_end (); - - return 0; -} diff --git a/camel/tests/stream/.cvsignore b/camel/tests/stream/.cvsignore deleted file mode 100644 index 36f9336c1d..0000000000 --- a/camel/tests/stream/.cvsignore +++ /dev/null @@ -1,14 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov -test1 -test2 -test3 diff --git a/camel/tests/stream/Makefile.am b/camel/tests/stream/Makefile.am deleted file mode 100644 index 25bd84eafd..0000000000 --- a/camel/tests/stream/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ - -INCLUDES = \ - -I$(includedir) \ - -I$(top_srcdir) \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/camel/tests/lib \ - -DG_LOG_DOMAIN=\"evolution-tests\" \ - $(CAMEL_CFLAGS) - -LDADD = \ - $(top_builddir)/camel/libcamel.la \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/camel/tests/lib/libcameltest.a \ - $(INTLLIBS) \ - $(EVOLUTION_MAIL_LIBS) - -check_PROGRAMS = \ - test1 test2 test3 - -TESTS = test1 test2 test3 - - - diff --git a/camel/tests/stream/README b/camel/tests/stream/README deleted file mode 100644 index 8ca6a9602d..0000000000 --- a/camel/tests/stream/README +++ /dev/null @@ -1,4 +0,0 @@ - -test1 camelstreamfs, creating, read/write, eos, refcounting -test2 camelstreammem, creating, read/write, eos, refcounting -test3 camelseekablesubstream diff --git a/camel/tests/stream/test1.c b/camel/tests/stream/test1.c deleted file mode 100644 index 452d45274f..0000000000 --- a/camel/tests/stream/test1.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - test ... camelstreamfs */ - -#include "camel-test.h" -#include "streams.h" - -#include -#include -#include - -#include "camel/camel-stream-fs.h" - -int main(int argc, char **argv) -{ - CamelSeekableStream *ss = NULL; - int i; - int fd = -1; - struct stat st; - int size; - char buffer[1024]; - - camel_test_init(argc, argv); - - camel_test_start("CamelStream fs, open, seek, read, write, eos"); - for (i=0;i<2;i++) { - - (void)unlink("stream.txt"); - - push("trying to open a nonexistant stream, method %d", i); - switch(i) { - case 0: - ss = (CamelSeekableStream *)camel_stream_fs_new_with_name("stream.txt", O_RDWR, 0); - break; - case 1: - fd = open("stream.txt", O_RDWR, 0); - ss = (CamelSeekableStream *)camel_stream_fs_new_with_fd(fd); - break; - } - check(ss == NULL && errno == ENOENT); - check(stat("stream.txt", &st) == -1 && errno == ENOENT); - pull(); - - push("Creating stream using method %d", i); - switch(i) { - case 0: - ss = (CamelSeekableStream *)camel_stream_fs_new_with_name("stream.txt", O_CREAT|O_RDWR|O_TRUNC, 0600); - fd = ((CamelStreamFs *)ss)->fd; - break; - case 1: - fd = open("stream.txt", O_CREAT|O_RDWR|O_TRUNC, 0600); - ss = (CamelSeekableStream *)camel_stream_fs_new_with_fd(fd); - break; - } - check(ss != NULL); - check(stat("stream.txt", &st) == 0 && (st.st_mode&0777) == 0600 && S_ISREG(st.st_mode) && st.st_size == 0); - pull(); - - test_stream_seekable_writepart(ss); - test_stream_seekable_readpart(ss); - - push("getting filesize"); - check(stat("stream.txt", &st) == 0 && (st.st_mode&0777) == 0600 && S_ISREG(st.st_mode)); - size = st.st_size; - pull(); - - push("checking close closes"); - check_unref(ss, 1); - check(close(fd) == -1); - pull(); - - push("re-opening stream"); - switch(i) { - case 0: - ss = (CamelSeekableStream *)camel_stream_fs_new_with_name("stream.txt", O_RDWR, 0); - fd = ((CamelStreamFs *)ss)->fd; - break; - case 1: - fd = open("stream.txt", O_RDWR, 0); - ss = (CamelSeekableStream *)camel_stream_fs_new_with_fd(fd); - break; - } - check(ss != NULL); - check(stat("stream.txt", &st) == 0 && (st.st_mode&0777) == 0600 && S_ISREG(st.st_mode) && st.st_size == size); - - test_stream_seekable_readpart(ss); - - check_unref(ss, 1); - check(close(fd) == -1); - pull(); - - push("re-opening stream with truncate"); - switch(i) { - case 0: - ss = (CamelSeekableStream *)camel_stream_fs_new_with_name("stream.txt", O_RDWR|O_TRUNC, 0); - fd = ((CamelStreamFs *)ss)->fd; - break; - case 1: - fd = open("stream.txt", O_RDWR|O_TRUNC, 0); - ss = (CamelSeekableStream *)camel_stream_fs_new_with_fd(fd); - break; - } - check(ss != NULL); - check(stat("stream.txt", &st) == 0 && (st.st_mode&0777) == 0600 && S_ISREG(st.st_mode) && st.st_size == 0); - - /* read has to return 0 before eos is set */ - check(camel_stream_read(CAMEL_STREAM(ss), buffer, 1) == 0); - check(camel_stream_eos(CAMEL_STREAM(ss))); - - check_unref(ss, 1); - check(close(fd) == -1); - pull(); - - (void)unlink("stream.txt"); - } - - camel_test_end(); - - return 0; -} diff --git a/camel/tests/stream/test2.c b/camel/tests/stream/test2.c deleted file mode 100644 index 02ad88e95c..0000000000 --- a/camel/tests/stream/test2.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - test ... camelstreammem */ - -#include "camel-test.h" -#include "streams.h" - -#include -#include -#include - -#include "camel/camel-stream-mem.h" - -int main(int argc, char **argv) -{ - CamelSeekableStream *ss = NULL; - int i; - int fd = -1; - struct stat st; - int size; - char buffer[1024]; - GByteArray *ba; - - camel_test_init(argc, argv); - - camel_test_start("CamelStream mem, create, seek, read, write, eos"); - for (i=0;i<3;i++) { - - push("Creating stream using method %d", i); - switch(i) { - case 0: - ss = (CamelSeekableStream *)camel_stream_mem_new(); - break; - case 1: - ba = g_byte_array_new(); - ss = (CamelSeekableStream *)camel_stream_mem_new_with_byte_array(ba); - break; - case 2: - ss = (CamelSeekableStream *)camel_stream_mem_new_with_buffer("", 0); - break; - } - check(ss != NULL); - - test_stream_seekable_writepart(ss); - test_stream_seekable_readpart(ss); - - check_unref(ss, 1); - pull(); - } - - camel_test_end(); - - return 0; -} diff --git a/camel/tests/stream/test3.c b/camel/tests/stream/test3.c deleted file mode 100644 index f85a8ce105..0000000000 --- a/camel/tests/stream/test3.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - test ... camelseekablesubstream */ - -#include "camel-test.h" -#include "streams.h" - -#include -#include -#include - -#include "camel/camel-stream-mem.h" -#include "camel/camel-stream-fs.h" -#include "camel/camel-seekable-substream.h" - -#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) - -struct { - off_t lower, upper; -} ranges[] = { - { 3, 10241 }, - { 0, 1024 }, - { 0, 0 }, - { 0, 1 }, - { 0, 2 }, - { 0, 3 }, - { 0, 7 }, - { 1, 8 }, - { 1, 9 }, - { 10245, 10300 }, - { 0, CAMEL_STREAM_UNBOUND }, -/* { 1, CAMEL_STREAM_UNBOUND }, - { 2, CAMEL_STREAM_UNBOUND }, - { 3, CAMEL_STREAM_UNBOUND }, these take too long to run - { 7, CAMEL_STREAM_UNBOUND },*/ - { 10245, CAMEL_STREAM_UNBOUND }, -}; - -int main(int argc, char **argv) -{ - CamelSeekableStream *ss = NULL; - int i, j; - CamelSeekableSubstream *sus, *sus2; - - camel_test_init(argc, argv); - - camel_test_start("CamelSeekableSubstream, mem backing"); - for (j=0;j