From f8da9c83029a5e7c36f6df3eaa0b28871112ec07 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Sun, 24 Jan 2021 01:01:10 +0900 Subject: [PATCH] Import maildir-utils_1.4.15.orig.tar.gz [dgit import orig maildir-utils_1.4.15.orig.tar.gz] --- .dir-locals.el | 2 + .editorconfig | 36 + .github/issue_template.md | 20 + .gitignore | 123 + .mailmap | 1 + .travis.yml | 35 + AUTHORS | 1 + COPYING | 674 +++ ChangeLog | 1 + HACKING | 144 + Makefile.am | 61 + NEWS | 2 + NEWS.org | 868 +++ README | 25 + TODO | 159 + autogen.sh | 34 + build-aux/config.rpath | 0 c.cfg | 1578 ++++++ configure.ac | 360 ++ contrib/Makefile.am | 31 + contrib/gmime-test.c | 275 + contrib/mu-completion.zsh | 124 + contrib/mu-sexp-convert | 204 + contrib/mu.spec | 129 + gtest.mk | 34 + guile/Makefile.am | 79 + guile/examples/Makefile.am | 23 + guile/examples/contacts-export | 85 + guile/examples/msg-graphs | 133 + guile/examples/mu-biff | 59 + guile/examples/org2mu4e | 78 + guile/fdl.texi | 451 ++ guile/mu-guile-message.c | 627 +++ guile/mu-guile-message.h | 39 + guile/mu-guile.c | 256 + guile/mu-guile.h | 99 + guile/mu-guile.texi | 995 ++++ guile/mu.scm | 318 ++ guile/mu/Makefile.am | 28 + guile/mu/README | 207 + guile/mu/contact.scm | 4 + guile/mu/message.scm | 4 + guile/mu/part.scm | 4 + guile/mu/plot.scm | 80 + guile/mu/script.scm | 57 + guile/mu/stats.scm | 165 + guile/scripts/Makefile.am | 29 + guile/scripts/find-dups.scm | 119 + guile/scripts/msgs-count.scm | 40 + guile/scripts/msgs-per-day.scm | 49 + guile/scripts/msgs-per-hour.scm | 49 + guile/scripts/msgs-per-month.scm | 50 + guile/scripts/msgs-per-year-month.scm | 52 + guile/scripts/msgs-per-year.scm | 48 + guile/tests/Makefile.am | 52 + guile/tests/test-mu-guile.c | 134 + guile/tests/test-mu-guile.scm | 124 + guile/texi.texi.in | 3 + lib/Makefile.am | 285 + lib/doxyfile.in | 181 + lib/mu-bookmarks.c | 146 + lib/mu-bookmarks.h | 86 + lib/mu-contacts.cc | 299 ++ lib/mu-contacts.hh | 207 + lib/mu-container.c | 691 +++ lib/mu-container.h | 224 + lib/mu-flags.c | 241 + lib/mu-flags.h | 184 + lib/mu-index.c | 475 ++ lib/mu-index.h | 193 + lib/mu-maildir.c | 943 ++++ lib/mu-maildir.h | 223 + lib/mu-msg-crypto.c | 374 ++ lib/mu-msg-doc.cc | 124 + lib/mu-msg-doc.h | 96 + lib/mu-msg-fields.c | 425 ++ lib/mu-msg-fields.h | 292 ++ lib/mu-msg-file.c | 815 +++ lib/mu-msg-file.h | 105 + lib/mu-msg-iter.cc | 437 ++ lib/mu-msg-iter.h | 246 + lib/mu-msg-json.c | 524 ++ lib/mu-msg-part.c | 1009 ++++ lib/mu-msg-part.h | 268 + lib/mu-msg-prio.c | 65 + lib/mu-msg-prio.h | 84 + lib/mu-msg-priv.h | 140 + lib/mu-msg-sexp.c | 635 +++ lib/mu-msg.c | 1013 ++++ lib/mu-msg.h | 654 +++ lib/mu-query.cc | 524 ++ lib/mu-query.h | 136 + lib/mu-runtime.cc | 118 + lib/mu-runtime.h | 67 + lib/mu-script.c | 360 ++ lib/mu-script.h | 132 + lib/mu-store.cc | 1433 +++++ lib/mu-store.hh | 568 ++ lib/mu-threader.c | 455 ++ lib/mu-threader.h | 56 + lib/query/Makefile.am | 99 + lib/query/mu-data.hh | 155 + lib/query/mu-parser.cc | 344 ++ lib/query/mu-parser.hh | 89 + lib/query/mu-proc-iface.hh | 132 + lib/query/mu-tokenizer.cc | 133 + lib/query/mu-tokenizer.hh | 140 + lib/query/mu-tree.hh | 111 + lib/query/mu-xapian.cc | 116 + lib/query/mu-xapian.hh | 40 + lib/query/parse.cc | 41 + lib/query/test-parser.cc | 146 + lib/query/test-tokenizer.cc | 158 + lib/query/tokenize.cc | 38 + lib/test-mu-common.c | 93 + lib/test-mu-common.h | 61 + lib/test-mu-contacts.cc | 91 + lib/test-mu-container.c | 83 + lib/test-mu-date.c | 93 + lib/test-mu-flags.c | 193 + lib/test-mu-maildir.c | 693 +++ lib/test-mu-msg-fields.c | 134 + lib/test-mu-msg.c | 598 +++ lib/test-mu-store.c | 206 + .../cur/1220863042.12663_1.mindcrime!2,S | 146 + .../cur/1220863060.12663_3.mindcrime!2,S | 230 + .../cur/1220863087.12663_15.mindcrime!2,PS | 136 + .../cur/1220863087.12663_19.mindcrime!2,S | 77 + .../cur/1220863087.12663_5.mindcrime!2,S | 84 + .../cur/1220863087.12663_7.mindcrime!2,RS | 138 + .../cur/1252168370_3.14675.cthulhu!2,S | 21 + lib/testdir/cur/1283599333.1840_11.cthulhu!2, | 16 + .../cur/1305664394.2171_402.cthulhu!2, | 17 + lib/testdir/cur/encrypted!2,S | 56 + lib/testdir/cur/multimime!2,FS | 27 + lib/testdir/cur/multirecip!2,S | 11 + lib/testdir/cur/signed!2,S | 36 + lib/testdir/cur/signed-encrypted!2,S | 54 + lib/testdir/cur/special!2,Sabc | 10 + lib/testdir/new/1220863087.12663_21.mindcrime | 111 + lib/testdir/new/1220863087.12663_23.mindcrime | 105 + lib/testdir/new/1220863087.12663_25.mindcrime | 98 + lib/testdir/new/1220863087.12663_9.mindcrime | 209 + lib/testdir/tmp/1220863087.12663.ignore | 98 + lib/testdir2/Foo/cur/arto.eml | 448 ++ lib/testdir2/Foo/cur/fraiche.eml | 10 + lib/testdir2/Foo/cur/mail5 | 625 +++ lib/testdir2/Foo/new/.noindex | 0 lib/testdir2/Foo/tmp/.noindex | 0 lib/testdir2/bar/cur/181736.eml | 42 + lib/testdir2/bar/cur/mail1 | 38 + lib/testdir2/bar/cur/mail2 | 14 + lib/testdir2/bar/cur/mail3 | 34 + lib/testdir2/bar/cur/mail4 | 29 + lib/testdir2/bar/cur/mail5 | 7 + lib/testdir2/bar/cur/mail6 | 18 + lib/testdir2/bar/new/.noindex | 0 lib/testdir2/bar/tmp/.noindex | 0 lib/testdir2/wom_bat/cur/atomic | 20 + lib/testdir2/wom_bat/cur/rfc822.1 | 44 + lib/testdir2/wom_bat/cur/rfc822.2 | 44 + lib/testdir3/cycle/cur/cycle0 | 7 + lib/testdir3/cycle/cur/cycle0.0 | 8 + lib/testdir3/cycle/cur/cycle0.0.0 | 8 + lib/testdir3/cycle/cur/rogue0 | 8 + lib/testdir3/cycle/new/.noindex | 0 lib/testdir3/cycle/tmp/.noindex | 0 .../sort/1st-child-promotes-thread/cur/A | 7 + .../sort/1st-child-promotes-thread/cur/B | 7 + .../sort/1st-child-promotes-thread/cur/C | 7 + .../sort/1st-child-promotes-thread/cur/D | 9 + .../1st-child-promotes-thread/new/.noindex | 0 .../1st-child-promotes-thread/tmp/.noindex | 0 .../sort/2nd-child-promotes-thread/cur/A | 7 + .../sort/2nd-child-promotes-thread/cur/B | 7 + .../sort/2nd-child-promotes-thread/cur/C | 9 + .../sort/2nd-child-promotes-thread/cur/D | 7 + .../sort/2nd-child-promotes-thread/cur/E | 9 + .../2nd-child-promotes-thread/new/.noindex | 0 .../2nd-child-promotes-thread/tmp/.noindex | 0 .../sort/child-does-not-promote-thread/cur/A | 9 + .../sort/child-does-not-promote-thread/cur/X | 7 + .../sort/child-does-not-promote-thread/cur/Y | 7 + .../sort/child-does-not-promote-thread/cur/Z | 7 + .../new/.noindex | 0 .../tmp/.noindex | 0 .../grandchild-promotes-only-subthread/cur/A | 7 + .../grandchild-promotes-only-subthread/cur/B | 7 + .../grandchild-promotes-only-subthread/cur/C | 9 + .../grandchild-promotes-only-subthread/cur/D | 9 + .../grandchild-promotes-only-subthread/cur/E | 9 + .../grandchild-promotes-only-subthread/cur/F | 9 + .../grandchild-promotes-only-subthread/cur/G | 7 + .../new/.noindex | 0 .../tmp/.noindex | 0 .../sort/grandchild-promotes-thread/cur/A | 7 + .../sort/grandchild-promotes-thread/cur/B | 7 + .../sort/grandchild-promotes-thread/cur/C | 9 + .../sort/grandchild-promotes-thread/cur/D | 7 + .../sort/grandchild-promotes-thread/cur/E | 9 + .../grandchild-promotes-thread/new/.noindex | 0 .../grandchild-promotes-thread/tmp/.noindex | 0 lib/testdir3/tree/cur/child0.0 | 9 + lib/testdir3/tree/cur/child0.1 | 9 + lib/testdir3/tree/cur/child0.1.0 | 9 + lib/testdir3/tree/cur/child2.0.0 | 12 + lib/testdir3/tree/cur/child3.0.0.0.0 | 9 + lib/testdir3/tree/cur/child4.0 | 9 + lib/testdir3/tree/cur/child4.1 | 9 + lib/testdir3/tree/cur/root0 | 7 + lib/testdir3/tree/cur/root1 | 7 + lib/testdir3/tree/cur/root2 | 7 + lib/testdir3/tree/new/.noindex | 0 lib/testdir3/tree/tmp/.noindex | 0 lib/testdir4/1220863042.12663_1.mindcrime!2,S | 146 + .../1220863087.12663_19.mindcrime!2,S | 77 + lib/testdir4/1252168370_3.14675.cthulhu!2,S | 22 + lib/testdir4/1283599333.1840_11.cthulhu!2, | 15 + lib/testdir4/1305664394.2171_402.cthulhu!2, | 17 + lib/testdir4/181736.eml | 42 + lib/testdir4/encrypted!2,S | 57 + lib/testdir4/mail1 | 38 + lib/testdir4/mail5 | 624 +++ lib/testdir4/multimime!2,FS | 27 + lib/testdir4/signed!2,S | 36 + lib/testdir4/signed-bad!2,S | 35 + lib/testdir4/signed-encrypted!2,S | 54 + lib/testdir4/special!2,Sabc | 10 + lib/utils/Makefile.am | 109 + lib/utils/mu-command-parser.cc | 196 + lib/utils/mu-command-parser.hh | 157 + lib/utils/mu-date.c | 87 + lib/utils/mu-date.h | 67 + lib/utils/mu-error.hh | 137 + lib/utils/mu-log.c | 319 ++ lib/utils/mu-log.h | 99 + lib/utils/mu-sexp-parser.cc | 175 + lib/utils/mu-sexp-parser.hh | 115 + lib/utils/mu-str.c | 453 ++ lib/utils/mu-str.h | 221 + lib/utils/mu-util.c | 495 ++ lib/utils/mu-util.h | 444 ++ lib/utils/mu-utils.cc | 471 ++ lib/utils/mu-utils.hh | 271 + lib/utils/test-command-parser.cc | 147 + lib/utils/test-mu-str.c | 275 + lib/utils/test-mu-util.c | 248 + lib/utils/test-sexp-parser.cc | 76 + lib/utils/test-utils.cc | 206 + m4/Makefile.am | 47 + m4/ax_ac_append_to_file.m4 | 32 + m4/ax_ac_print_to_file.m4 | 32 + m4/ax_add_am_macro_static.m4 | 28 + m4/ax_am_macros_static.m4 | 38 + m4/ax_append_compile_flags.m4 | 46 + m4/ax_append_flag.m4 | 50 + m4/ax_append_link_flags.m4 | 44 + m4/ax_check_compile_flag.m4 | 53 + m4/ax_check_enable_debug.m4 | 124 + m4/ax_check_gnu_make.m4 | 95 + m4/ax_check_link_flag.m4 | 53 + m4/ax_code_coverage.m4 | 272 + m4/ax_compiler_flags.m4 | 158 + m4/ax_compiler_flags_cflags.m4 | 161 + m4/ax_compiler_flags_cxxflags.m4 | 136 + m4/ax_compiler_flags_gir.m4 | 60 + m4/ax_compiler_flags_ldflags.m4 | 111 + m4/ax_cxx_compile_stdcxx.m4 | 948 ++++ m4/ax_cxx_compile_stdcxx_14.m4 | 34 + m4/ax_file_escapes.m4 | 30 + m4/ax_is_release.m4 | 80 + m4/ax_lib_readline.m4 | 107 + m4/ax_require_defined.m4 | 37 + m4/ax_valgrind_check.m4 | 239 + m4/guile-2.2.m4 | 394 ++ m4/host-cpu-c-abi.m4 | 675 +++ m4/lib-ld.m4 | 168 + m4/lib-link.m4 | 774 +++ m4/lib-prefix.m4 | 249 + man/Makefile.am | 37 + man/mu-add.1 | 48 + man/mu-bookmarks.5 | 36 + man/mu-cfind.1 | 133 + man/mu-easy.1 | 313 ++ man/mu-extract.1 | 100 + man/mu-find.1 | 389 ++ man/mu-help.1 | 34 + man/mu-index.1 | 188 + man/mu-info.1 | 46 + man/mu-init.1 | 69 + man/mu-mkdir.1 | 45 + man/mu-query.7 | 358 ++ man/mu-remove.1 | 49 + man/mu-script.1 | 83 + man/mu-server.1 | 61 + man/mu-verify.1 | 79 + man/mu-view.1 | 54 + man/mu.1 | 182 + mu/Makefile.am | 120 + mu/mu-cmd-cfind.c | 470 ++ mu/mu-cmd-extract.c | 428 ++ mu/mu-cmd-find.c | 768 +++ mu/mu-cmd-index.c | 318 ++ mu/mu-cmd-script.c | 204 + mu/mu-cmd-server.cc | 1334 +++++ mu/mu-cmd.c | 732 +++ mu/mu-cmd.h | 111 + mu/mu-config.c | 809 +++ mu/mu-config.h | 260 + mu/mu-help-strings.awk | 69 + mu/mu-help-strings.txt | 198 + mu/mu-memcheck.in | 6 + mu/mu.cc | 131 + mu/test-mu-cmd-cfind.c | 362 ++ mu/test-mu-cmd.c | 910 ++++ mu/test-mu-query.c | 767 +++ mu/test-mu-runtime.c | 98 + mu/test-mu-threads.c | 462 ++ mu4e/Makefile.am | 62 + mu4e/TODO | 19 + mu4e/fdl.texi | 451 ++ mu4e/mu4e-about.org | 15 + mu4e/mu4e-actions.el | 371 ++ mu4e/mu4e-compose.el | 944 ++++ mu4e/mu4e-context.el | 183 + mu4e/mu4e-contrib.el | 222 + mu4e/mu4e-draft.el | 606 +++ mu4e/mu4e-headers.el | 1868 +++++++ mu4e/mu4e-icalendar.el | 189 + mu4e/mu4e-lists.el | 102 + mu4e/mu4e-main.el | 326 ++ mu4e/mu4e-mark.el | 468 ++ mu4e/mu4e-message.el | 352 ++ mu4e/mu4e-meta.el.in | 11 + mu4e/mu4e-org.el | 162 + mu4e/mu4e-proc.el | 488 ++ mu4e/mu4e-speedbar.el | 134 + mu4e/mu4e-utils.el | 1247 +++++ mu4e/mu4e-vars.el | 1094 ++++ mu4e/mu4e-view.el | 1856 +++++++ mu4e/mu4e.el | 67 + mu4e/mu4e.texi | 4667 +++++++++++++++++ mu4e/org-mu4e.el | 230 + toys/Makefile.am | 24 + toys/msg2pdf/Makefile.am | 53 + toys/msg2pdf/msg2pdf.c | 315 ++ toys/mug/Makefile.am | 98 + toys/mug/mu-msg-attach-view.c | 296 ++ toys/mug/mu-msg-attach-view.h | 67 + toys/mug/mu-msg-body-view.c | 379 ++ toys/mug/mu-msg-body-view.h | 69 + toys/mug/mu-msg-header-view.c | 188 + toys/mug/mu-msg-header-view.h | 69 + toys/mug/mu-msg-view.c | 242 + toys/mug/mu-msg-view.h | 68 + toys/mug/mu-widget-util.c | 94 + toys/mug/mu-widget-util.h | 39 + toys/mug/mug-msg-list-view.c | 473 ++ toys/mug/mug-msg-list-view.h | 82 + toys/mug/mug-msg-view.c | 152 + toys/mug/mug-msg-view.h | 58 + toys/mug/mug-query-bar.c | 112 + toys/mug/mug-query-bar.h | 52 + toys/mug/mug-shortcuts.c | 153 + toys/mug/mug-shortcuts.h | 68 + toys/mug/mug.c | 422 ++ toys/mug/mug.svg | 443 ++ www/cheatsheet.md | 148 + www/graph01.png | Bin 0 -> 8702 bytes www/index.md | 179 + www/mu-guile.md | 164 + www/mu-guile.org | 177 + www/mu-small.png | Bin 0 -> 6613 bytes www/mu.css | 116 + www/mu.jpg | Bin 0 -> 19806 bytes www/mu.png | Bin 0 -> 27501 bytes www/mu4e-1.png | Bin 0 -> 48158 bytes www/mu4e-2.png | Bin 0 -> 132879 bytes www/mu4e-3.png | Bin 0 -> 72474 bytes www/mu4e-splitview-small.png | Bin 0 -> 62377 bytes www/mu4e-splitview.png | Bin 0 -> 273304 bytes www/mu4e.md | 59 + www/mu4egraph.png | Bin 0 -> 366402 bytes www/mug-full.png | Bin 0 -> 577326 bytes www/mug-thumb.png | Bin 0 -> 43922 bytes www/mug.org | 39 + www/old-news.md | 90 + 387 files changed, 75573 insertions(+) create mode 100644 .dir-locals.el create mode 100644 .editorconfig create mode 100644 .github/issue_template.md create mode 100644 .gitignore create mode 100644 .mailmap create mode 100644 .travis.yml create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 HACKING create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 NEWS.org create mode 100644 README create mode 100644 TODO create mode 100755 autogen.sh create mode 100644 build-aux/config.rpath create mode 100644 c.cfg create mode 100644 configure.ac create mode 100644 contrib/Makefile.am create mode 100644 contrib/gmime-test.c create mode 100644 contrib/mu-completion.zsh create mode 100755 contrib/mu-sexp-convert create mode 100644 contrib/mu.spec create mode 100644 gtest.mk create mode 100644 guile/Makefile.am create mode 100644 guile/examples/Makefile.am create mode 100755 guile/examples/contacts-export create mode 100755 guile/examples/msg-graphs create mode 100755 guile/examples/mu-biff create mode 100755 guile/examples/org2mu4e create mode 100644 guile/fdl.texi create mode 100644 guile/mu-guile-message.c create mode 100644 guile/mu-guile-message.h create mode 100644 guile/mu-guile.c create mode 100644 guile/mu-guile.h create mode 100644 guile/mu-guile.texi create mode 100644 guile/mu.scm create mode 100644 guile/mu/Makefile.am create mode 100644 guile/mu/README create mode 100644 guile/mu/contact.scm create mode 100644 guile/mu/message.scm create mode 100644 guile/mu/part.scm create mode 100644 guile/mu/plot.scm create mode 100644 guile/mu/script.scm create mode 100644 guile/mu/stats.scm create mode 100644 guile/scripts/Makefile.am create mode 100755 guile/scripts/find-dups.scm create mode 100755 guile/scripts/msgs-count.scm create mode 100755 guile/scripts/msgs-per-day.scm create mode 100755 guile/scripts/msgs-per-hour.scm create mode 100755 guile/scripts/msgs-per-month.scm create mode 100755 guile/scripts/msgs-per-year-month.scm create mode 100755 guile/scripts/msgs-per-year.scm create mode 100644 guile/tests/Makefile.am create mode 100644 guile/tests/test-mu-guile.c create mode 100755 guile/tests/test-mu-guile.scm create mode 100644 guile/texi.texi.in create mode 100644 lib/Makefile.am create mode 100644 lib/doxyfile.in create mode 100644 lib/mu-bookmarks.c create mode 100644 lib/mu-bookmarks.h create mode 100644 lib/mu-contacts.cc create mode 100644 lib/mu-contacts.hh create mode 100644 lib/mu-container.c create mode 100644 lib/mu-container.h create mode 100644 lib/mu-flags.c create mode 100644 lib/mu-flags.h create mode 100644 lib/mu-index.c create mode 100644 lib/mu-index.h create mode 100644 lib/mu-maildir.c create mode 100644 lib/mu-maildir.h create mode 100644 lib/mu-msg-crypto.c create mode 100644 lib/mu-msg-doc.cc create mode 100644 lib/mu-msg-doc.h create mode 100644 lib/mu-msg-fields.c create mode 100644 lib/mu-msg-fields.h create mode 100644 lib/mu-msg-file.c create mode 100644 lib/mu-msg-file.h create mode 100644 lib/mu-msg-iter.cc create mode 100644 lib/mu-msg-iter.h create mode 100644 lib/mu-msg-json.c create mode 100644 lib/mu-msg-part.c create mode 100644 lib/mu-msg-part.h create mode 100644 lib/mu-msg-prio.c create mode 100644 lib/mu-msg-prio.h create mode 100644 lib/mu-msg-priv.h create mode 100644 lib/mu-msg-sexp.c create mode 100644 lib/mu-msg.c create mode 100644 lib/mu-msg.h create mode 100644 lib/mu-query.cc create mode 100644 lib/mu-query.h create mode 100644 lib/mu-runtime.cc create mode 100644 lib/mu-runtime.h create mode 100644 lib/mu-script.c create mode 100644 lib/mu-script.h create mode 100644 lib/mu-store.cc create mode 100644 lib/mu-store.hh create mode 100644 lib/mu-threader.c create mode 100644 lib/mu-threader.h create mode 100644 lib/query/Makefile.am create mode 100644 lib/query/mu-data.hh create mode 100644 lib/query/mu-parser.cc create mode 100644 lib/query/mu-parser.hh create mode 100644 lib/query/mu-proc-iface.hh create mode 100644 lib/query/mu-tokenizer.cc create mode 100644 lib/query/mu-tokenizer.hh create mode 100644 lib/query/mu-tree.hh create mode 100644 lib/query/mu-xapian.cc create mode 100644 lib/query/mu-xapian.hh create mode 100644 lib/query/parse.cc create mode 100644 lib/query/test-parser.cc create mode 100644 lib/query/test-tokenizer.cc create mode 100644 lib/query/tokenize.cc create mode 100644 lib/test-mu-common.c create mode 100644 lib/test-mu-common.h create mode 100644 lib/test-mu-contacts.cc create mode 100644 lib/test-mu-container.c create mode 100644 lib/test-mu-date.c create mode 100644 lib/test-mu-flags.c create mode 100644 lib/test-mu-maildir.c create mode 100644 lib/test-mu-msg-fields.c create mode 100644 lib/test-mu-msg.c create mode 100644 lib/test-mu-store.c create mode 100644 lib/testdir/cur/1220863042.12663_1.mindcrime!2,S create mode 100644 lib/testdir/cur/1220863060.12663_3.mindcrime!2,S create mode 100644 lib/testdir/cur/1220863087.12663_15.mindcrime!2,PS create mode 100644 lib/testdir/cur/1220863087.12663_19.mindcrime!2,S create mode 100644 lib/testdir/cur/1220863087.12663_5.mindcrime!2,S create mode 100644 lib/testdir/cur/1220863087.12663_7.mindcrime!2,RS create mode 100644 lib/testdir/cur/1252168370_3.14675.cthulhu!2,S create mode 100644 lib/testdir/cur/1283599333.1840_11.cthulhu!2, create mode 100644 lib/testdir/cur/1305664394.2171_402.cthulhu!2, create mode 100644 lib/testdir/cur/encrypted!2,S create mode 100644 lib/testdir/cur/multimime!2,FS create mode 100644 lib/testdir/cur/multirecip!2,S create mode 100644 lib/testdir/cur/signed!2,S create mode 100644 lib/testdir/cur/signed-encrypted!2,S create mode 100644 lib/testdir/cur/special!2,Sabc create mode 100644 lib/testdir/new/1220863087.12663_21.mindcrime create mode 100644 lib/testdir/new/1220863087.12663_23.mindcrime create mode 100644 lib/testdir/new/1220863087.12663_25.mindcrime create mode 100644 lib/testdir/new/1220863087.12663_9.mindcrime create mode 100644 lib/testdir/tmp/1220863087.12663.ignore create mode 100644 lib/testdir2/Foo/cur/arto.eml create mode 100644 lib/testdir2/Foo/cur/fraiche.eml create mode 100644 lib/testdir2/Foo/cur/mail5 create mode 100644 lib/testdir2/Foo/new/.noindex create mode 100644 lib/testdir2/Foo/tmp/.noindex create mode 100644 lib/testdir2/bar/cur/181736.eml create mode 100644 lib/testdir2/bar/cur/mail1 create mode 100644 lib/testdir2/bar/cur/mail2 create mode 100644 lib/testdir2/bar/cur/mail3 create mode 100644 lib/testdir2/bar/cur/mail4 create mode 100644 lib/testdir2/bar/cur/mail5 create mode 100644 lib/testdir2/bar/cur/mail6 create mode 100644 lib/testdir2/bar/new/.noindex create mode 100644 lib/testdir2/bar/tmp/.noindex create mode 100644 lib/testdir2/wom_bat/cur/atomic create mode 100644 lib/testdir2/wom_bat/cur/rfc822.1 create mode 100644 lib/testdir2/wom_bat/cur/rfc822.2 create mode 100644 lib/testdir3/cycle/cur/cycle0 create mode 100644 lib/testdir3/cycle/cur/cycle0.0 create mode 100644 lib/testdir3/cycle/cur/cycle0.0.0 create mode 100644 lib/testdir3/cycle/cur/rogue0 create mode 100644 lib/testdir3/cycle/new/.noindex create mode 100644 lib/testdir3/cycle/tmp/.noindex create mode 100644 lib/testdir3/sort/1st-child-promotes-thread/cur/A create mode 100644 lib/testdir3/sort/1st-child-promotes-thread/cur/B create mode 100644 lib/testdir3/sort/1st-child-promotes-thread/cur/C create mode 100644 lib/testdir3/sort/1st-child-promotes-thread/cur/D create mode 100644 lib/testdir3/sort/1st-child-promotes-thread/new/.noindex create mode 100644 lib/testdir3/sort/1st-child-promotes-thread/tmp/.noindex create mode 100644 lib/testdir3/sort/2nd-child-promotes-thread/cur/A create mode 100644 lib/testdir3/sort/2nd-child-promotes-thread/cur/B create mode 100644 lib/testdir3/sort/2nd-child-promotes-thread/cur/C create mode 100644 lib/testdir3/sort/2nd-child-promotes-thread/cur/D create mode 100644 lib/testdir3/sort/2nd-child-promotes-thread/cur/E create mode 100644 lib/testdir3/sort/2nd-child-promotes-thread/new/.noindex create mode 100644 lib/testdir3/sort/2nd-child-promotes-thread/tmp/.noindex create mode 100644 lib/testdir3/sort/child-does-not-promote-thread/cur/A create mode 100644 lib/testdir3/sort/child-does-not-promote-thread/cur/X create mode 100644 lib/testdir3/sort/child-does-not-promote-thread/cur/Y create mode 100644 lib/testdir3/sort/child-does-not-promote-thread/cur/Z create mode 100644 lib/testdir3/sort/child-does-not-promote-thread/new/.noindex create mode 100644 lib/testdir3/sort/child-does-not-promote-thread/tmp/.noindex create mode 100644 lib/testdir3/sort/grandchild-promotes-only-subthread/cur/A create mode 100644 lib/testdir3/sort/grandchild-promotes-only-subthread/cur/B create mode 100644 lib/testdir3/sort/grandchild-promotes-only-subthread/cur/C create mode 100644 lib/testdir3/sort/grandchild-promotes-only-subthread/cur/D create mode 100644 lib/testdir3/sort/grandchild-promotes-only-subthread/cur/E create mode 100644 lib/testdir3/sort/grandchild-promotes-only-subthread/cur/F create mode 100644 lib/testdir3/sort/grandchild-promotes-only-subthread/cur/G create mode 100644 lib/testdir3/sort/grandchild-promotes-only-subthread/new/.noindex create mode 100644 lib/testdir3/sort/grandchild-promotes-only-subthread/tmp/.noindex create mode 100644 lib/testdir3/sort/grandchild-promotes-thread/cur/A create mode 100644 lib/testdir3/sort/grandchild-promotes-thread/cur/B create mode 100644 lib/testdir3/sort/grandchild-promotes-thread/cur/C create mode 100644 lib/testdir3/sort/grandchild-promotes-thread/cur/D create mode 100644 lib/testdir3/sort/grandchild-promotes-thread/cur/E create mode 100644 lib/testdir3/sort/grandchild-promotes-thread/new/.noindex create mode 100644 lib/testdir3/sort/grandchild-promotes-thread/tmp/.noindex create mode 100644 lib/testdir3/tree/cur/child0.0 create mode 100644 lib/testdir3/tree/cur/child0.1 create mode 100644 lib/testdir3/tree/cur/child0.1.0 create mode 100644 lib/testdir3/tree/cur/child2.0.0 create mode 100644 lib/testdir3/tree/cur/child3.0.0.0.0 create mode 100644 lib/testdir3/tree/cur/child4.0 create mode 100644 lib/testdir3/tree/cur/child4.1 create mode 100644 lib/testdir3/tree/cur/root0 create mode 100644 lib/testdir3/tree/cur/root1 create mode 100644 lib/testdir3/tree/cur/root2 create mode 100644 lib/testdir3/tree/new/.noindex create mode 100644 lib/testdir3/tree/tmp/.noindex create mode 100644 lib/testdir4/1220863042.12663_1.mindcrime!2,S create mode 100644 lib/testdir4/1220863087.12663_19.mindcrime!2,S create mode 100644 lib/testdir4/1252168370_3.14675.cthulhu!2,S create mode 100644 lib/testdir4/1283599333.1840_11.cthulhu!2, create mode 100644 lib/testdir4/1305664394.2171_402.cthulhu!2, create mode 100644 lib/testdir4/181736.eml create mode 100644 lib/testdir4/encrypted!2,S create mode 100644 lib/testdir4/mail1 create mode 100644 lib/testdir4/mail5 create mode 100644 lib/testdir4/multimime!2,FS create mode 100644 lib/testdir4/signed!2,S create mode 100644 lib/testdir4/signed-bad!2,S create mode 100644 lib/testdir4/signed-encrypted!2,S create mode 100644 lib/testdir4/special!2,Sabc create mode 100644 lib/utils/Makefile.am create mode 100644 lib/utils/mu-command-parser.cc create mode 100644 lib/utils/mu-command-parser.hh create mode 100644 lib/utils/mu-date.c create mode 100644 lib/utils/mu-date.h create mode 100644 lib/utils/mu-error.hh create mode 100644 lib/utils/mu-log.c create mode 100644 lib/utils/mu-log.h create mode 100644 lib/utils/mu-sexp-parser.cc create mode 100644 lib/utils/mu-sexp-parser.hh create mode 100644 lib/utils/mu-str.c create mode 100644 lib/utils/mu-str.h create mode 100644 lib/utils/mu-util.c create mode 100644 lib/utils/mu-util.h create mode 100644 lib/utils/mu-utils.cc create mode 100644 lib/utils/mu-utils.hh create mode 100644 lib/utils/test-command-parser.cc create mode 100644 lib/utils/test-mu-str.c create mode 100644 lib/utils/test-mu-util.c create mode 100644 lib/utils/test-sexp-parser.cc create mode 100644 lib/utils/test-utils.cc create mode 100644 m4/Makefile.am create mode 100644 m4/ax_ac_append_to_file.m4 create mode 100644 m4/ax_ac_print_to_file.m4 create mode 100644 m4/ax_add_am_macro_static.m4 create mode 100644 m4/ax_am_macros_static.m4 create mode 100644 m4/ax_append_compile_flags.m4 create mode 100644 m4/ax_append_flag.m4 create mode 100644 m4/ax_append_link_flags.m4 create mode 100644 m4/ax_check_compile_flag.m4 create mode 100644 m4/ax_check_enable_debug.m4 create mode 100644 m4/ax_check_gnu_make.m4 create mode 100644 m4/ax_check_link_flag.m4 create mode 100644 m4/ax_code_coverage.m4 create mode 100644 m4/ax_compiler_flags.m4 create mode 100644 m4/ax_compiler_flags_cflags.m4 create mode 100644 m4/ax_compiler_flags_cxxflags.m4 create mode 100644 m4/ax_compiler_flags_gir.m4 create mode 100644 m4/ax_compiler_flags_ldflags.m4 create mode 100644 m4/ax_cxx_compile_stdcxx.m4 create mode 100644 m4/ax_cxx_compile_stdcxx_14.m4 create mode 100644 m4/ax_file_escapes.m4 create mode 100644 m4/ax_is_release.m4 create mode 100644 m4/ax_lib_readline.m4 create mode 100644 m4/ax_require_defined.m4 create mode 100644 m4/ax_valgrind_check.m4 create mode 100644 m4/guile-2.2.m4 create mode 100644 m4/host-cpu-c-abi.m4 create mode 100644 m4/lib-ld.m4 create mode 100644 m4/lib-link.m4 create mode 100644 m4/lib-prefix.m4 create mode 100644 man/Makefile.am create mode 100644 man/mu-add.1 create mode 100644 man/mu-bookmarks.5 create mode 100644 man/mu-cfind.1 create mode 100644 man/mu-easy.1 create mode 100644 man/mu-extract.1 create mode 100644 man/mu-find.1 create mode 100644 man/mu-help.1 create mode 100644 man/mu-index.1 create mode 100644 man/mu-info.1 create mode 100644 man/mu-init.1 create mode 100644 man/mu-mkdir.1 create mode 100644 man/mu-query.7 create mode 100644 man/mu-remove.1 create mode 100644 man/mu-script.1 create mode 100644 man/mu-server.1 create mode 100644 man/mu-verify.1 create mode 100644 man/mu-view.1 create mode 100644 man/mu.1 create mode 100644 mu/Makefile.am create mode 100644 mu/mu-cmd-cfind.c create mode 100644 mu/mu-cmd-extract.c create mode 100644 mu/mu-cmd-find.c create mode 100644 mu/mu-cmd-index.c create mode 100644 mu/mu-cmd-script.c create mode 100644 mu/mu-cmd-server.cc create mode 100644 mu/mu-cmd.c create mode 100644 mu/mu-cmd.h create mode 100644 mu/mu-config.c create mode 100644 mu/mu-config.h create mode 100644 mu/mu-help-strings.awk create mode 100644 mu/mu-help-strings.txt create mode 100644 mu/mu-memcheck.in create mode 100644 mu/mu.cc create mode 100644 mu/test-mu-cmd-cfind.c create mode 100644 mu/test-mu-cmd.c create mode 100644 mu/test-mu-query.c create mode 100644 mu/test-mu-runtime.c create mode 100644 mu/test-mu-threads.c create mode 100644 mu4e/Makefile.am create mode 100644 mu4e/TODO create mode 100644 mu4e/fdl.texi create mode 100644 mu4e/mu4e-about.org create mode 100644 mu4e/mu4e-actions.el create mode 100644 mu4e/mu4e-compose.el create mode 100644 mu4e/mu4e-context.el create mode 100644 mu4e/mu4e-contrib.el create mode 100644 mu4e/mu4e-draft.el create mode 100644 mu4e/mu4e-headers.el create mode 100644 mu4e/mu4e-icalendar.el create mode 100644 mu4e/mu4e-lists.el create mode 100644 mu4e/mu4e-main.el create mode 100644 mu4e/mu4e-mark.el create mode 100644 mu4e/mu4e-message.el create mode 100644 mu4e/mu4e-meta.el.in create mode 100644 mu4e/mu4e-org.el create mode 100644 mu4e/mu4e-proc.el create mode 100644 mu4e/mu4e-speedbar.el create mode 100644 mu4e/mu4e-utils.el create mode 100644 mu4e/mu4e-vars.el create mode 100644 mu4e/mu4e-view.el create mode 100644 mu4e/mu4e.el create mode 100644 mu4e/mu4e.texi create mode 100644 mu4e/org-mu4e.el create mode 100644 toys/Makefile.am create mode 100644 toys/msg2pdf/Makefile.am create mode 100644 toys/msg2pdf/msg2pdf.c create mode 100644 toys/mug/Makefile.am create mode 100644 toys/mug/mu-msg-attach-view.c create mode 100644 toys/mug/mu-msg-attach-view.h create mode 100644 toys/mug/mu-msg-body-view.c create mode 100644 toys/mug/mu-msg-body-view.h create mode 100644 toys/mug/mu-msg-header-view.c create mode 100644 toys/mug/mu-msg-header-view.h create mode 100644 toys/mug/mu-msg-view.c create mode 100644 toys/mug/mu-msg-view.h create mode 100644 toys/mug/mu-widget-util.c create mode 100644 toys/mug/mu-widget-util.h create mode 100644 toys/mug/mug-msg-list-view.c create mode 100644 toys/mug/mug-msg-list-view.h create mode 100644 toys/mug/mug-msg-view.c create mode 100644 toys/mug/mug-msg-view.h create mode 100644 toys/mug/mug-query-bar.c create mode 100644 toys/mug/mug-query-bar.h create mode 100644 toys/mug/mug-shortcuts.c create mode 100644 toys/mug/mug-shortcuts.h create mode 100644 toys/mug/mug.c create mode 100644 toys/mug/mug.svg create mode 100644 www/cheatsheet.md create mode 100644 www/graph01.png create mode 100644 www/index.md create mode 100644 www/mu-guile.md create mode 100644 www/mu-guile.org create mode 100644 www/mu-small.png create mode 100644 www/mu.css create mode 100644 www/mu.jpg create mode 100644 www/mu.png create mode 100644 www/mu4e-1.png create mode 100644 www/mu4e-2.png create mode 100644 www/mu4e-3.png create mode 100644 www/mu4e-splitview-small.png create mode 100644 www/mu4e-splitview.png create mode 100644 www/mu4e.md create mode 100644 www/mu4egraph.png create mode 100644 www/mug-full.png create mode 100644 www/mug-thumb.png create mode 100644 www/mug.org create mode 100644 www/old-news.md diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000..3a491ef --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,2 @@ +((emacs-lisp-mode + (indent-tabs-mode . nil))) diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..d7b5d39 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,36 @@ +#-*-mode:conf-*- +# editorconfig file (see EditorConfig.org), with some +# lowest-denominator settings that should work for many editors. + +root = true # this is the top-level + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true + +# The "best" answer is "tabs-for-indentation; spaces for alignment", but in +# practice that's hard to accomplish in many editors. +# +# So we use spaces instead, at least that looks consistent for all + +[*.{cc,cpp,hh,hpp}] +indent_style = space +indent_size = 8 +max_line_length = 100 + +[*.{c,h}] +indent_style = space +indent_size = 8 +max_line_length = 80 + +[configure.ac] +indent_style = space +indent_size = 4 +max_line_length = 100 + +[Makefile.am] +indent_style = tab +indent_size = 8 +max_line_length = 100 diff --git a/.github/issue_template.md b/.github/issue_template.md new file mode 100644 index 0000000..4527979 --- /dev/null +++ b/.github/issue_template.md @@ -0,0 +1,20 @@ +## Expected or desired behavior + +Please describe the behavior you expected / want + +## Actual behavior + +Please describe the behavior you are actually seeing. + +For bug-reports, if applicable, include error messages, emacs stack +traces etc. Try to be as specific as possible - when do you see this +happening? Does it happen always? Sometimes? How often? + +## Steps to reproduce + +For bug-reports, please describe in as much details as possible how +one can reproduce the problem*. + +## Versions of mu, mu4e/emacs, operating system etc. + +## Any other detail diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62e23bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,123 @@ +www/mu +mug +/mu/mu +/mu/mu-help-strings.h +mug2 +.desktop +*html +.deps +.libs +autom4te* +Makefile +Makefile.in +INSTALL +aclocal.m4 +config.* +configure +install-sh +depcomp +libtool +ltmain.sh + +# Added automatically by `autoreconf` +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 + +missing +nohup.out +vgdump +stamp-h1 +GPATH +GRTAGS +GSYMS +GTAGS +*.lo +*.o +*.la +*.x +*.go +*.gz +*.bz2 +\#* +*.aux +*.cp +*.fn +*.info +*.ky +*.log +*.pg +*.toc +*.tp +*.vr +*.elc +*.gcda +*.gcno +*.trs +*.exe +*.lib +aminclude_static.am +elisp-comp +elc-stamp +dummy.cc +msg2pdf +gmime-test +test-mu-cmd +test-mu-cmd-cfind +test-mu-contacts +test-mu-container +test-mu-date +test-mu-flags +test-mu-maildir +test-mu-msg +test-mu-msg-fields +test-mu-query +test-mu-runtime +test-mu-store +test-mu-str +test-mu-threads +test-mu-util +test-parser +test-tokenizer +test-utils +tokenize +test-command-parser +test-mu-utils +test-sexp-parser +test-scanner +/guile/tests/test-mu-guile + +mu4e-meta.el +mu4e.pdf +texinfo.tex +texi.texi +*.tex +*.pdf +/www/auto/* +configure.lineno +/test.xml +/mu4e/mdate-sh +/mu4e/mu4e-about.el +/mu4e/stamp-vti +/mu4e/version.texi +/lib/doxyfile +/version.texi +/compile +build-aux/ +/TAGS +parse + +*_flymake.* +*_flymake_* +/perf.data +perf.data +perf.data.old +*vgdump +/lib/asan.log* +/man/mu-mfind.1 +/mu/mu-memcheck +mu-*-coverage +mu*tar.xz +compile_commands.json diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000..3a54641 --- /dev/null +++ b/.mailmap @@ -0,0 +1 @@ +Dirk-Jan C. Binnema diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..063324a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,35 @@ +language: c +sudo: required +compiler: + - gcc +env: + global: + - BUILD_PKGS="libtool autoconf autoconf-archive automake texinfo" + - BUILD_LIBS="libgmime-2.6-dev libxapian-dev guile-2.0-dev libwebkitgtk-dev" + - TEST_PKGS="pmccabe" + matrix: + - EVM_EMACS=emacs-24.1-bin + - EVM_EMACS=emacs-24.2-bin + - EVM_EMACS=emacs-24.3-bin + # - EVM_EMACS=emacs-24.5-travis + # - EVM_EMACS=emacs-25.1-travis +before_install: + - git submodule update --init --recursive + # The Ubuntu version on travis is way too old, need Autoconf 2.69 + - sudo add-apt-repository ppa:dns/gnu -y + - sudo apt-get -qq update + - sudo apt-get install -qq ${BUILD_PKGS} ${BUILD_LIBS} ${TEST_PKGS} +install: + - sudo mkdir /usr/local/evm + - sudo chown $(id -u):$(id -g) /usr/local/evm + - curl -fsSkL https://raw.github.com/rejeep/evm/master/go | bash + - export PATH="$HOME/.evm/bin:$PATH" + - evm install $EVM_EMACS --use +script: + # Need recent version of autoconf-archive + - curl http://nl.mirror.babylon.network/gnu/autoconf-archive/autoconf-archive-2016.09.16.tar.xz -o /tmp/aa.tar.xz && tar xf /tmp/aa.tar.xz + - cp autoconf-archive-2016.09.16/m4/*.m4 m4/ + - ./autogen.sh + - ./configure + - make + - make check diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..3a54641 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Dirk-Jan C. Binnema diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..eee38d2 --- /dev/null +++ b/ChangeLog @@ -0,0 +1 @@ +See NEWS.org diff --git a/HACKING b/HACKING new file mode 100644 index 0000000..4d8ce94 --- /dev/null +++ b/HACKING @@ -0,0 +1,144 @@ +* HACKING + + Here are some guidelines for hacking on the 'mu' source code. + + This is a fairly long list -- this is not meant to discourage anyone from + working on mu; I think most of the rules are common sense anyway, and some of + the more stylistic-aesthetic rules are clearly visible in current source code, + so as long as any new code 'fits in', it should go a long way in satisfying + them. + + I should add some notes for the Lisp/Scheme code as well... + +** Coding style + + For consistency and, more important, to keep things understandable, mu + attempts to follow the following rules: + + 1. Basic code layout is like in the Linux kernel coding style. Keep the '{' + on the same line as the statement, except for functions. Tabs for + indentation, space for alignment; use 8-char tabs. + + 2. Lines should not exceed 80 characters (C) or 100 characters (C++) + + 3. Functions should not exceed 35 lines (with few exceptions). You can easily + check if any functions violate this rule with 'make line35', which lists + all functions with more than 35 non-comment lines. + + 4. Source files should not exceed 1000 lines + + 5. A function's cyclomatic complexity should not exceed 10 (there could be + rare exceptions, see the toplevel ~Makefile.am~). You can test the + cyclomatic complexity with the ~pmccabe~ tool; if you installed that, you + can use 'make cc10' to list all functions that violate this rule; there + should be none. + + 6. Filenames have their components separated with dashes (e.g, ~mu-log.h~), and + start with ~mu-~ where appropriate. + + 7. Global functions have the prefix based on their module, e.g., ~mu-foo.h~ + declares a function of 'mu_foo_bar (int a);', mu-foo.c implements this. + + 8. Non-global functions *don't* have the module prefix, and are declared + static. + + 9. Functions have their return type on a separate line before the function + name, so: +#+BEGIN_EXAMPLE + int + foo (const char *bar) + { + .... + } +#+END_EXAMPLE + + There is no non-aesthetic reason for this. + + 10. In C code, variable-declarations are at the beginning of a block; in + principle, C++ follows that same guideline, unless for heavy yet + uncertain initializations following RAII. + + In C code, the declaration does *not* initialize the variable. This will + give the compiler a chance to warn us if the variable is not initialized + in a certain code path. + + 11. Returned strings of type char* must be freed by the caller; if they are + not to be freed, 'const char*' should be used instead + + 12. Functions calls have a space between function name and arguments, unless + there are none, so: + + ~foo (12, 3)~; + + and + + ~bar();~ + + after a comma, a space should follow. + + 13. Functions that do not take arguments are explicitly declared as + f(void) and not f(). Reason: f() means that the arguments are + /unspecified/ (in C) + + 14. C-code should not use ~//~ comments. + + +** Logging + + For logging, mu uses the GLib logging functions/macros as listed below, + except when logging may not have been initialized. + + The logging system redirects most logging to the log file (typically, + ~/.cache/mu/mu.log). g_warning, g_message and g_critical are shown to the user, + except when running with --quiet, in which case g_message is *not* shown. + + - ~g_message~ is for non-error messages the user will see (unless running with + ~--quiet~) + - ~g_warning~ is for problems the user may be able to do something about (and + they are written on ~stderr~) + - ~g_critical~ is for mu bugs, serious, internal problems (~g_return_if_fail~ and + friends use this). (and they are written on ~stderr~) + - don't use ~g_error~ + + If you just want to log something in the log file without writing to screen, + use ~MU_LOG_WRITE~, as defined in ~mu-util.h~. + +** Compiling from git + + For hacking, you're strongly advised to use the latest git version. + Compilation from git should be straightforward, if you have the right tools + installed. + +*** dependencies + + You need to install a few dependencies; e.g. on Debian/Ubuntu: +#+BEGIN_EXAMPLE + sudo apt-get install \ + automake \ + autoconf-archive \ + autotools-dev \ + libglib2.0-dev \ + libxapian-dev \ + libgmime-3.0-dev \ + m4 \ + make \ + libtool \ + pkg-config +#+END_EXAMPLE + + Then, to compile straight from ~git~: + +#+BEGIN_EXAMPLE + $ git clone https://github.com/djcb/mu + $ cd mu + $ ./autogen.sh + $ make +#+END_EXAMPLE + + You only need to run ~./autogen.sh~ the first time and after changes in the + build system; otherwise you can use ~./configure~. + +# Local Variables: +# mode: org; org-startup-folded: nofold +# fill-column: 80 +# End: diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..f62c2e7 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,61 @@ +## Copyright (C) 2008-2020 Dirk-Jan C. Binnema +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +if BUILD_GUILE +guile=guile +else +guile= +endif + +if BUILD_MU4E +mu4e=mu4e +else +mu4e= +endif + +SUBDIRS=m4 man lib $(guile) mu $(mu4e) contrib toys + +ACLOCAL_AMFLAGS=-I m4 + +# so we can say 'make test' +check: test cleanupnote + +cleanupnote: + @echo -e "\nNote: you can remove the mu-test- dir in your tempdir" + @echo "after 'make check' has finished." + +tags: + gtags + +EXTRA_DIST= \ + TODO \ + HACKING \ + README \ + gtest.mk \ + NEWS \ + NEWS.org \ + autogen.sh + +doc_DATA = \ + NEWS.org + +include $(top_srcdir)/aminclude_static.am + +CODE_COVERAGE_IGNORE_PATTERN= \ + '/usr/*' \ + '*test-*' diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..23e9add --- /dev/null +++ b/NEWS @@ -0,0 +1,2 @@ +See NEWS.org + diff --git a/NEWS.org b/NEWS.org new file mode 100644 index 0000000..28bb44f --- /dev/null +++ b/NEWS.org @@ -0,0 +1,868 @@ +#+STARTUP:showall +* NEWS (user visible changes) + +* 1.4 (released, as of April 18 2020) + +*** mu + + - mu now defaults to the [[https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html][XDG Base Directory Specification]] for the default + locations for various files. E.g. on Unix the mu database now lives under + ~~/.cache/mu/~ rather than ~~/.mu~. You can still use the old location by + passing ~--muhome=~/.mu~ to various ~mu~ commands, or setting ~(setq + mu4e-mu-home "~/.mu")~ for ~mu4e~. + + If your ~~/.cache~ is volatile (e.g., is cleared on reboot), you may want + use ~--muhome~. Some mailing-list dicussion suggest that's fairly rare + though. + + After upgrading, you may wish to delete the files in the old location to + recover some diskspace. + + - There's a new subcommand ~mu init~ to initialize the mu database, which + takes the ~--maildir~ and ~--my-address~ parameters that ~index~ used to take. + These parameters are persistent so ~index~ does not need (or accept) them + anymore. ~mu4e~ now depends on those parameters. + + ~init~ only needs to be run once or when changing these parameters. That + implies that you need to re-index after changing these parameters. The + ~.noupdate~ files are ignored when indexing the first time after ~mu init~ (or + in general, when the database is empty). + + - There is another new subcommand ~mu info~ to get information about the mu + database, the personal addresses etc. + + - The contacts cache (which is used by ~mu cfind~ and ~mu4e~'s + contact-completion) is now stored as part of the Xapian database rather + than as a separate file. + + - The ~--xbatchsize~ and ~--autoupgrade~ options for indexing are gone; both are + determined implicitly now. + +*** mu4e + + - ~mu4e~ no longer uses the ~mu4e-maildir~ and ~mu4e-user-mail-address-list~ + variables; instead it uses the information it gets from ~mu~ (see the ~mu~ + section above). If you have a non-default ~mu4e-mu-home~, make sure to set + it before ~mu4e~ starts. + + It is strongly recommended that you run ~mu init~ with the appropriate + parameters to (re)initialize the Xapian database, as mentioned in the + mu-section above. + + The main screen shows your address(es), and issues a warning if + ~user-email-address~ is not part of that (and refer you to ~mu init~). You can + avoid the addresses in the main screen and the warning by setting + ~mu4e-main-view-hide-addresses~ to non-nil. + + - In many cases, ~mu4e~ used to receive /all/ contacts after each indexing + operation; this was slow for some users, so we have updated this to /only/ + get the contacts that have changed since the last round. + + We also moved sorting the contacts to the mu-side, which speeds things up + further. However, as a side-effect of this, ~mu4e-contact-rewrite-function~ + and ~mu4e-compose-complete-ignore-address-regexp~ have been obsoleted; users + of those should migrate to ~mu4e-contact-process-function~; see its + docstring for details. + + - Christophe Troestler contributed support for Gnus' calender-invitation + handling in mu4e (i.e., you should be able to accept/reject invitations + etc.). It's very fresh code, and likely it'll be tweaked in the future. + But it's available now for testing. Note that this requires the gnus-based + viewer, as per ~(setq mu4e-view-use-gnus t)~ + + - In addition, he added support for custom headers, so the ones for for the + non-gnus-view should work just as well. + + - ~org-mode~ support is enabled by default now. ~speedbar~ support is disabled + by default. The support org functionality has been moved to ~mu4e-org.el~, + with ~org-mu4e.el~ remaining for older things. + + - ~mu4e~ now adds message-ids to messages when saving drafts, so we can find + them even with ~mu4e-headers-skip-duplicates~. + + - Bookmarks (as in ~mu4e-bookmarks~) are now simple plists (instead of cl + structs). ~make-mu4e-bookmark~ has been updated to produce such plists (for + backward compatibility). A bookmark now looks like a list of e.g. ~(:name + "My bookmark" :query "banana OR pear" :key ?f)~ this format is a bit easier + extensible. + + - ~mu4e~ recognizes an attribute ~:hide t~, which will hide the bookmark item + from the main-screen (and speedbar), but keep it available through the + completion UI. + + - ~mu4e-maildir-shortcuts~ have also become plists. The older format is still + recognized for backward compatibility, but you are encouraged to upgrade. + + - Replying to mailing-lists has been improved, allowing for choosing for + replying to all, sender, list-only. + + - A very visible change, ~mu4e~ now shows unread/all counts for bookmarks in + the main screen that are strings. This is on by default, but can be + disabled by setting ~:hide-unread~ in the bookmark ~plist~ to ~t~. For + speed-reasons, these counts do _not_ filter out duplicates nor messages that + have been removed from the filesystem. + + - ~mu4e-attachment-dir~ now also applies to composing messages; it determines + the default directory for inclusion. + + - The mu4e <-> mu interaction has been rewritten to communicate using + s-expressions, with a repl for testing. + +*** toys + + - Updated the ~mug~ toy UI to use Webkit2/GTK+. Note that this is just a toy + which is not meant for distribution. ~msg2pdf~ is disabled for now. + + +*** How to upgrade mu4e + + - upgrade ~mu~ to the latest stable version (1.4.x) + + - shut down emacs + + - Run ~mu init~ in a terminal + + - Make sure ~mu init~ points to the right Maildir folder and add your email + address(es) the following way: + + ~mu init --maildir=~/Maildir --my-address=jim@example.com --my-address=bob@example.com~ + + - once this is done, run ~mu index~ + + - Don't forget to delete your old mail cache location if necessary (see + release notes for more detail). + + +** 1.2 + + After a bit over a year since version 1.0, here is version 1.2. This is + mostly a bugfix release, but there are also a number of new features. + +*** mu + + - Substantial (algorithmic) speed-up of message-threading; this also (or + especially) affects mu4e, since threading is the default. See commit + eb9bfbb1ca3c for all the details, and thanks to Nicolas Avrutin. + + - The query-parser now generates better queries for wildcard searches, by + using the Xapian machinery for that (when available) rather than + transforming into regexp queries. + + - The perl backend is hardly used and will be removed; for now we just + disable it in the build. + + - Allow outputting messages in json format, closely following the sexp + output. This adds an (optional) dependency on the Json-Glib library. + +*** mu4e + + - Bump the minimal required emacs version to 24.4. This was already de-facto + true, now it is enforced. + + - In mu4e-bookmarks, allow the `:query` element to take a function (or + lambda) to dynamically generate the query string. + + - There is a new message-view for mu4e, based on the Gnus' article-view. + This bring a lot of (but not all) of the very rich Gnus article-mode + feature-set to mu4e, such as S/MIME-support, syntax-highlighting, + + For now this is experimental ("tech preview"), but might replace the + current message-view in a future release. Enable it with: + (setq mu4e-view-use-gnus t) + + Thanks to Christophe Troestler for his work on fixing various encoding + issues. + + - Many bug fixes + +*** guile + + - Now requires guile 2.2. + +*** Contributors for this release: + + Ævar Arnfjörð Bjarmason, Albert Krewinkel, Alberto Luaces, Alex Bennée, Alex + Branham, Alex Murray, Cheong Yiu Fung, Chris Nixon, Christian Egli, + Christophe Troestler, Dirk-Jan C. Binnema, Eric Danan, Evan Klitzke, Ian + Kelling, ibizaman, James P. Ascher, John Whitbeck, Junyeong Jeong, Kevin + Foley, Marcelo Henrique Cerri, Nicolas Avrutin, Oleh Krehel, Peter W. V. + Tran-Jørgensen, Piotr Oleskiewicz, Sebastian Miele, Ulrich Ölmann, + +** 1.0 + + After a decade of development, *mu 1.0*! + + Note: the new release requires a C++14 capable compiler. + +*** mu + + - New, custom query parser which replaces Xapian's 'QueryParser' + both in mu and mu4e. Existing queries should still work, but the new + engine handles non-alphanumeric queries much better. + - Support regular expressions in queries (with the new query engine), + e.g. "subject:/foo.*bar/". See the new `mu-query` and updated `mu-easy` + manpages for examples. + - cfind: ensure nicks are unique + - auxiliary programs invoked from mu/mu4e survive terminating the + shell / emacs + +*** mu4e + + - Allow for rewriting message bodies + - Toggle-menus for header settings + - electric-quote-(local-)mode work when composing emails + - Respect format=flowed and delsp=yes for viewing plain-text + messages + - Added new mu4e-split-view mode: single-window + - Add menu item for `untrash'. + - Unbreak abbrevs in mu4e-compose-mode + - Allow forwarding messages as attachments + (`mu4e-compose-forward-as-attachment') + - New defaults: default to 'skip duplicates' and 'include related' + in headers-view, which should be good defaults for most users. Can be + customized using `mu4e-headers-skip-duplicates' and + `mu4e-headers-include-related', respectively. + - Many bug fixed (see github for all the details). + - Updated documentation + +*** Contributors for this release: + + Ævar Arnfjörð Bjarmason, Alex Bennée, Arne Köhn, Christophe Troestler, + Damien Garaud, Dirk-Jan C. Binnema, galaunay, Hong Xu, Ian Kelling, John + Whitbeck, Josiah Schwab, Jun Hao, Krzysztof Jurewicz, maxime, Mekeor Melire, + Nathaniel Nicandro, Ronald Evers, Sean 'Shaleh' Perry, Sébastien Le + Callonnec, Stig Brautaset, Thierry Volpiatto, Titus von der Malsburg, + Vladimir Sedach, Wataru Ashihara, Yuri D'Elia. + + And all the people on the mailing-list and in github, with bug reports, + questions and suggestions. + + +** 0.9.18 + + New development series which will lead to 0.9.18. + +*** mu + + - Increase the default maximum size for messages to index to 500 + Mb; you can customize this using the --max-msg-size parameter to mu index. + - implement "lazy-checking", which makes mu not descend into + subdirectories when the directory-timestamp is up to date; greatly speeds + up indexing (see --lazy-check) + - prefer gpg2 for crypto + - fix a crash when running on OpenBSD + - fix --clear-links (broken filenames) + - You can now set the MU_HOME environment variable as an + alternative way of setting the mu homedir via the --muhome command-line + parameter. + +*** mu4e + +**** reading messages + + - Add `mu4e-action-view-with-xwidget`, and action for viewing + e-mails inside a Webkit-widget inside emacs (requires emacs 25.x with + xwidget/webkit/gtk3 support) + - Explicitly specify utf8 for external html viewing, so browsers + can handle it correctly. + - Make `shr' the default renderer for rich-text emails (when + available) + - Add a :user-agent field to the message-sexp (in mu4e-view), which + is either the User-Agent or X-Mailer field, when present. + +**** composing messages + + - Cleanly handle early exits from message composition as well as while + composing. + - Allow for resending existing messages, possibly editing them. M-x + mu4e-compose-resend, or use the menu; no shortcut. + - Better handle the closing of separate compose frames + - Improved font-locking for the compose buffers, and more extensive + checks for cited parts. + - automatically sign/encrypt replies to signed/encrypted messages + (subject to `mu4e-compose-crypto-reply-policy') + +**** searching & marking + + - Add a hook `mu4e-mark-execute-pre-hook`, which is run just before + executing marks. + - Just before executing any search, a hook-function + `mu4e-headers-search-hook` is invoked, which receives the search + expression as its parameter. + - In addition, there's a `mu4e-headers-search-bookmark-hook` which + gets called when searches get invoked as a bookmark (note that + `mu4e-headers-search-hook` will also be called just afterwards). This + hook also receives the search expression as its parameter. + - Remove the 'z' keybinding for leaving the headers + view. Keybindings are precious! + - Fix parentheses/precedence in narrowing search terms + +**** indexing + + - Allow for indexing in the background; see + `mu4e-index-update-in-background`. + - Better handle mbsync output in the update buffer + - Add variables mu4e-index-cleanup and mu4e-index-lazy to enable + lazy checking from mu4e; you can sit from mu4e using something like: + #+BEGIN_SRC elisp +(setq mu4e-index-cleanup nil ;; don't do a full cleanup check + mu4e-index-lazy-check t) ;; don't consider up-to-date dirs #+END_SRC + +**** misc + + - don't overwrite global-mode-string, append to it. + - Make org-links (and more general, all users of + mu4e-view-message-with-message-id) use a headers buffer, then view the + message. This way, those linked message are just like any other, and can + be deleted, moved etc. + - Support org-mode 9.x + - Improve file-name escaping, and make it support non-ascii filenames + - Attempt to jump to the same messages after a re-search update operation + - Add action for spam-filter options + - Let `mu4e~read-char-choice' become case-insensitive if there is + no exact match; small convenience that affects most the single-char + option-reading in mu4e. + +*** Perl + + - an experimental Perl binding ("mup") is available now. See + perl/README.md for details. + +** Contributors: + + Aaron LI, Abdo Roig-Maranges, Ævar Arnfjörð Bjarmason, Alex Bennée, Allen, + Anders Johansson, Antoine Levitt, Arthur Lee, attila, Charles-H. Schulz, + Christophe Troestler, Chunyang Xu, Dirk-Jan C. Binnema, Jakub Sitnicki, + Josiah Schwab, jsrjenkins, Jun Hao, Klaus Holst, Lukas Fürmetz, Magnus + Therning, Maximilian Matthe, Nicolas Richard, Piotr Trojanek, Prashant + Sachdeva, Remco van 't Veer, Stephen Eglen, Stig Brautaset, Thierry + Volpiatto, Thomas Moulia, Titus von der Malsburg, Yuri D'Elia, Vladimir + Sedach + +* Old news + :PROPERTIES: + :VISIBILITY: folded + :END: + +** 0.9.16 + +*** Release + + 2016-01-20: Release from the 0.9.15 series + +*** Contributors: + + Adam Sampson, Ævar Arnfjörð Bjarmason, Bar Shirtcliff, Charles-H. Schulz, + Clément Pit--Claudel, Damien Cassou, Declan Qian, Dima Kogan, Dirk-Jan C. + Binnema, Foivos S. Zakkak, Hinrik Örn Sigurðsson, Jeroen Tiebout, JJ Asghar, + Jonas Bernoulli, Jun Hao, Martin Yrjölä, Maximilian Matthé, Piotr Trojanek, + prsarv, Thierry Volpiatto, Titus von der Malsburg + + (and of course all people who reported issues, provided suggestions etc.) + +** 0.9.15 + + - bump version to 0.9.15. From now on, odd minor version numbers + are for development versions; thus, 0.9.16 is to be the next stable + release. + - special case text/calendar attachments to get .vcs + extensions. This makes it easier to process those with external tools. + - change the message file names to better conform to the maildir + spec; this was confusing some tools. + - fix navigation when not running in split-view mode + - add `mu4e-view-body-face', so the body-face for message in the + view can be customized; e.g. (set-face-attribute 'mu4e-view-body-face nil + :font "Liberation Serif-10") + - add `mu4e-action-show-thread`, an action for the headers and view + buffers to search for messages in the same thread as the current one. + - allow for transforming mailing-list names for display, using + `mu4e-mailing-list-patterns'. + - some optimizations in indexing (~30% faster in some cases) + - new variable mu4e-user-agent-string, to customize the User-Agent: + header. + - when removing the "In-reply-to" header from replies, mu4e will + also remove the (hidden) References header, effectively creating a new + message-thread. + - implement 'mu4e-context', for defining and switching between + various contexts, which are groups of settings. This can be used for + instance for switch between e-mail accounts. See the section in the manual + for details. + - correctly decode mailing-list headers + - allow for "fancy" mark-characters; and improve the default set + - by default, the maildirs are no longer cached; please see the + variable ~mu4e-cache-maildir-list~ if you have a lot of maildirs and it + gets slow. + - change the default value for + ~org-mu4e-link-query-in-headers-mode~ to ~nil~, ie. by default link to the + message, not the query, as this is usually more useful behavior. + - overwrite target message files that already exist, rather than + erroring out. + - set mu4e-view-html-plaintext-ratio-heuristic to 5, as 10 was too + high to detect some effectively html-only messages + - add mu4e-view-toggle-html (keybinding: 'h') to toggle between + text and html display. The existing 'mu4e-view-toggle-hide-cited' gets the + new binding '#'. + - add a customization variable `mu4e-view-auto-mark-as-read' + (defaults to t); if set to nil, mu4e won't mark messages as read when you + open them. This can be useful on read-only file-systems, since + marking-as-read implies a file-move operation. + - use smaller chunks for mu server on Cygwin, allowing for better + mu4e support there. + +** 0.9.13 + +*** contributors + + Attila, Daniele Pizzolli, Charles-H.Schulz, David C Sterrat, Dirk-Jan C. + Binnema, Eike Kettner, Florian Lindner, Foivos S. Zakkak, Gour, KOMURA + Takaaki, Pan Jie, Phil Hagelberg, thdox, Tiago Saboga, Titus von der + Malsburg + + (and of course all people who reported issues, provided suggestions etc.) + +*** mu/mu4e/guile + + - NEWS (this file) is now visible from within mu4e – "N" in the main-menu. + + - make `mu4e-headers-sort-field', `mu4e-headers-sort-direction' + public (that, is change the prefix from mu4e~ to mu4e-), so users can + manipulate them + + - make it possible the 'fancy' (unicode) characters separately for + headers and marks (see the variable `mu4e-use-fancy-chars'.) + + - allow for composing in a separate frame (see + `mu4e-compose-in-new-frame') + + - add the `:thread-subject' header field, for showing the subject + for a thread only once. So, instead of (from the manual): + + #+BEGIN_EXAMPLE +06:32 Nu To Edmund Dantès GstDev + Re: Gstreamer-V4L... 15:08 Nu Abbé Busoni +GstDev + Re: Gstreamer-V... 18:20 Nu Pierre Morrel GstDev \ Re: Gstreamer... +2013-03-18 S Jacopo EmacsUsr + emacs server on win... 2013-03-18 S Mercédès +EmacsUsr \ RE: emacs server ... 2013-03-18 S Beachamp EmacsUsr + Re: Copying a +whole... 22:07 Nu Albert de Moncerf EmacsUsr \ Re: Copying a who... 2013-03-18 S +Gaspard Caderousse GstDev | Issue with GESSimpl... 2013-03-18 Ss Baron Danglars +GuileUsr | Guile-SDL 0.4.2 ava... End of search results #+END_EXAMPLE + + the headers list would now look something like: + #+BEGIN_EXAMPLE +10:26 ⭑☐ Nicolas Goaziou Orgmode /bulk ◼ Re: [O] 2 issue with Include function +11:00 ⭑☐ Leonard Randall Orgmode /bulk ┗▶ 10:55 ⭑☐ Guillermo Rodrigu... GstDev +/bulk ◼ Re: stop pipeline into a callback function. 12:04 ⭑☐ Enrique Ocaña Gon... +GstDev /bulk ┗▶ 11:27 ⭑☐ Tim Müller GstDev /bulk ◼ 09:34 ⭑☐ Robert Klein Orgmode +/bulk ◼ Re: [O] Agenda Tag filtering - has the behaviour changed? #+END_EXAMPLE + + This is a feature known from e.g. `mutt' and `gnus` and many other + clients, and can be enabled by customizing `mu4e-headers-fields' + (replacing `:subject' with `:thread-subject') + + It's not the default yet, but may become so in the future. + + - add some spam-handling actions to mu4e-contrib.el + + - mu4e now targets org 8.x, which support for previous versions + relegated to `org-old-mu4e.el`. Some of the new org-features are improved + capture templates. + + - updates to the documentation, in particular about using BBDB. + + - improved URL-handling (use emacs built-in functionality) + + - many bug fixes, including some crash fixes on BSD + +*** guile + + – add --delete option to the find-dups scripts, to automatically delete + them. Use with care! + +** Release 0.9.12 + +*** mu + + - truncate /all/ terms the go beyond xapian's max term length + - lowercase the domain-part of email addresses in mu cfind (and mu4e), if + the domain is in ascii + - give messages without msgids fake-message-ids; this fixes the problem + where such messages were not found in --include-related queries + - cleanup of the query parser + - provide fake message-ids for messages without it; fixes #183 + - allow showing tags in 'mu find' output + - fix CSV quoting + +*** mu4e + + - update the emacs <-> backend protocol; documented in the mu-server man page + - show 'None' as date for messages without it (Headers View) + - add `mu4e-headers-found-hook', `mu4e-update-pre-hook'. + - split org support in org-old-mu4e.el (org <= 7.x) and org-mu4e.el + - org: improve template keywords + - rework URL handling + +** Release 0.9.5 + +*** mu + + - allow 'contact:' as a shortcut in queries for 'from:foo OR to:foo OR + cc:foo OR bcc:foo', and 'recip:' as a shortcut for 'to:foo OR cc:foo OR + bcc:foo' + - support getting related messages (--include-related), which includes + messages that may not match the query, but that are in the same threads as + messages that were + - support "list:"/"v:" for matching mailing list names, and the "v" + format-field to show them. E.g 'mu find list:emacs-orgmode.gnu.org' + +*** mu4e + + - scroll down in message view takes you to next message (but see + `mu4e-view-scroll-to-next') + - support 'human dates', that is, show the time for today's messages, and + the date for older messages in the headers view + - replace `mu4e-user-mail-address-regexp' and `mu4e-my-mail-addresses' with + `mu4e-user-mail-address-list' + - support tags (i.e.., X-Keywords and friends) in the headers-view, and the + message view. Thanks to Abdó Roig-Maranges. New field ":tags". + - automatically update the headers buffer when new messages are found during + indexing; set `mu4e-headers-auto-update' to nil to disable this. + - update mail/index with M-x mu4e-update-mail-and-index; which everywhere in + mu4e is available with key C-S-u. Use prefix argument to run in + background. + - add function `mu4e-update-index' to only update the index + - add 'friendly-names' for mailing lists, so they should up nicely in the + headers view + +*** guile + + - add 'mu script' command to run mu script, for example to do statistics on + your message corpus. See the mu-script man-page. + +*** mug + + - ported to gtk+ 3; remove gtk+ 2.x code + + + +** Release 0.9.9 <2012-10-14> + +*** mu4e + - view: address can be toggled long/short, compose message + - sanitize opening urls (mouse-1, and not too eager) + - tooltips for header labels, flags + - add sort buttons to header-labels + - support signing / decryption of messages + - improve address-autocompletion (e.g., ensure it's case-insensitive) + - much faster when there are many maildirs + - improved line wrapping + - better handle attached messages + - improved URL-matching + - improved messages to user (mu4e-(warn|error|message)) + - add refiling functionality + - support fancy non-ascii in the UI + - dynamic folders (i.e.., allow mu4e-(sent|draft|trash|refile)-folder) to + be a function + - dynamic attachment download folder (can be a function now) + - much improved manual + +*** mu + - remove --summary (use --summary-len instead) + - add --after for mu find, to limit to messages after T + - add new command `mu verify', to verify signatures + - fix iso-2022-jp decoding (and other 7-bit clean non-ascii) + - add support for X-keywords + - performance improvements for threaded display (~ 25% for 23K msgs) + - mu improved user-help (and the 'mu help' command) + - toys/mug2 replaces toys/mug + +*** mu-guile + - automated tests + - add mu:timestamp, mu:count + - handle db reopenings in the background + + +** Release 0.9.8.5 <2012-07-01> + +*** mu4e + + - auto-completion of e-mail addresses + - inline display of images (see `mu4e-view-show-images'), uses imagemagick + if available + - interactively change number of headers / columns for showing headers with + C-+ and C-- in headers, view mode + - support flagging message + - navigate to previous/next queries like a web browser (with , + ) + - narrow search results with '/' + - next/previous take a prefix arg now, to move to the nth previous/next message + - allow for writing rich-text messages with org-mode + - enable marking messages as Flagged + - custom marker functions (see manual) + - better "dwim" handling of buffer switching / killing + - deferred marking of message (i.e.., mark now, decide what to mark for + later) + - enable changing of sort order, display of threads + - clearer marks for marked messages + - fix sorting by subject (disregarding Re:, Fwd: etc.) + - much faster handling when there are many maildirs (speedbar) + - handle mailto: links + - improved, extended documentation + +*** mu + + - support .noupdate files (parallel to .noindex, dir is ignored unless we're + doing a --rebuild). + - append all inline text parts, when getting the text body + - respect custom maildir flags + - correctly handle the case where g_utf8_strdown (str) > len (str) + - make gtk, guile, webkit dependency optional, even if they are installed + + +** Release 0.9.8.4 <2012-05-08> + +*** mu4e + + - much faster header buffers + - split view mode (headers, view); see `mu4e-split-view'. + - add search history for queries + - ability to open attachments with arbitrary programs, pipe through shell + commands or open in the current emacs + - quote names in recipient addresses + - mu4e-get-maildirs works now for recursive maildirs as well + - define arbitrary operations for headers/messages/attachments using the + actions system -- see the chapter 'Actions' in the manual + - allow mu4e to be uses as the default emacs mailer (`mu4e-user-agent') + - mark headers based on a regexp, `mu4e-mark-matches', or '%' + - mark threads, sub-threads (mu4e-hdrs-mark-thread, + mu4e-hdrs-mark-subthread, or 'T', 't') + - add msg2pdf toy + - easy logging (using `mu4e-toggle-logging') + - improve mu4e-speedbar for use in headers/view + - use the message-mode FCC system for saving messages to the sent-messages + folder + - fix: off-by-one in number of matches shown + +*** general + + - fix for opening files with non-ascii names + - much improved support for searching non-Latin (Cyrillic etc.) languages + we can now match 'Тесла' or 'Аркона' without problems + - smarter escaping (fixes issues with finding message ids) + - fixes for queries with brackets + - allow --summary-len for the length of message summaries + - numerous other small fixes + + +** Release 0.9.8.3 <2012-04-06> + + *NOTE*: existing mu/mu4e are recommended to run `mu index --rebuild' after + installation. + +*** mu4e + + - allow for searching by editing bookmarks + (`mu4e-search-bookmark-edit-first') (keybinding 'B') + - make it configurable what to do with sent messages (see + `mu4e-sent-messages-behavior') + - speedbar support (initial patch by Antono V) + - better handling of drafts: + - don't save too early + - more descriptive buffer names (based on Subject, if any) + - don't put "--text-follows-this-line--" markers in files + - automatically include signatures, if set + - add user-settable variables mu4e-view-wrap-lines and mu4e-view-hide-cited, + which determine the initial way a message is displayed + - improved documentation + +*** general + + - much improved searching for GMail folders (i.e. maildir:/ matching); + this requires a 'mu index --rebuild' + - correctly handle utf-8 messages, even if they don't specify this explicitly + - fix compiler warnings for newer/older gcc and clang/clang++ + - fix unit tests (and some code) for Ubuntu 10.04 and FreeBSD9 + - fix warnings for compilation with GTK+ 3.2 and recent glib (g_set_error) + - fix mu_msg_move_to_maildir for top-level messages + - fix in maildir scanning + - plug some memleaks + +** Release 0.9.8.2 <2012-03-11> + +*** mu4e: + + - make mail updating non-blocking + - allow for automatic periodic update ('mu4e-update-interval') + - allow for external triggering of update + - make behavior when leaving the headers buffer customizable, ie. + ask/apply/ignore ('mu4e-headers-leave-behaviour') + +*** general + + - fix output for some non-UTF8 locales + - open ('play') file names with spaces + - don't show unnecessary errors for --format=links + - make build warning-free for clang/clang++ + - allow for slightly older autotools + - fix unit tests for some hidden assumptions (locale, dir structure etc.) + - some documentation updates / clarifications + +** Release 0.9.8.1 <2012-02-18 Sat> + +*** mu + - show only leaf/rfc822 MIME-parts + +*** mu4e + + - allow for shell commands with arguments in `mu4e-get-mail-command'. + - support marking messages as 'read' and 'unread' + - show the current query in the the mode-line (`global-mode-string'). + - don't repeat 'Re:' / 'Fwd:' + - colorize cited message parts + - better handling of text-based, embedded message attachments + - for text-bodies, concatenate all text/plain parts + - make filladapt dep optional + - documentation improvements + +** Release 0.9.8 <2012-01-31> + + - '--descending' has been renamed into '--reverse' + - search for attachment MIME-type using 'mime:' or 'y:' + - search for text in text-attachments using 'embed:' or 'e:' + - searching for attachment file names now uses 'file:' (was: 'attach:') + - experimental emacs-based mail client -- "mu4e" + - added more unit tests + - improved guile binding - no special binary is needed anymore, it's + installable are works with the normal guile system; code has been + substantially improved. still 'experimental' + +** Release 0.9.7 <2011-09-03 Sat> + + - don't enforce UTF-8 output, use locale (fixes issue #11) + - add mail threading to mu-find (using -t/--threads) (sorta fixes issue #13) + - add header line to --format=mutt-ab (mu cfind), (fixes issue #42) + - terminate mu view results with a form-feed marker (use --terminate) (fixes + issue #41) + - search X-Label: tags (fixes issue #40) + - added toys/muile, the mu guile shells, which allows for message stats etc. + - fix date handling (timezones) + +** Release 0.9.6 <2011-05-28 Sat> + + - FreeBSD build fix + - fix matching for mu cfind to be as expected + - fix mu-contacts for broken names/emails + - clear the contacts-cache too when doing a --rebuild + - wildcard searches ('*') for fields (except for path/maildir) + - search for attachment file names (with 'a:'/'attach:') -- also works with + wildcards + - remove --xquery completely; use --output=xquery instead + - fix progress info in 'mu index' + - display the references for a message using the 'r' character (xmu find) + - remove --summary-len/-k, instead use --summary for mu view and mu find, and + - support colorized output for some sub-commands (view, cfind and + extract). Disabled by default, use --color to enable, or set env MU_COLORS + to non-empty + - update documentation, added more examples + +** Release 0.9.5 <2011-04-25 Mon> + + - bug fix for infinite loop in Maildir detection + - minor fixes in tests, small optimizations + +** Release 0.9.4 <2011-04-12 Tue> + + - add the 'cfind' command, to search/export contact information + - add 'flag:unread' as a synonym for 'flag:new OR NOT flag:unseen' + - updated documentation + +** Release 0.9.3 <2011-02-13 Sun> + + - don't warn about missing files with --quiet + +** Release 0.9.2 <2011-02-02 Wed> + + - stricter checking of options; and options must now *follow* the sub-command + (if any); so, something like: 'mu index --maildir=/foo/bar' + - output searches as plain text (default), XML, JSON or s-expressions using + --format=plain|xml|json|sexp. For example: 'mu find foobar --output=json'. + These format options are experimental (except for 'plain') + - the --xquery option should now be used as --format=xquery, for output + symlinks, use --format=links. This is a change in the options. + - search output can include the message size using the 'z' shortcut + - match message size ranges (i.e.. size:500k..2M) + - fix: honor the --overwrite (or lack thereof) parameter + - support folder names with special characters (@, ' ', '.' and so on) + - better check for already-running mu index + - when --maildir= is not provided for mu index, default to the last one + - add --max-msg-size, to specify a new maximum message size + - move the 'mug' UI to toys/mug; no longer installable + - better support for Solaris builds, Gentoo. + +** Release 0.9.1 <2010-12-05 Sun> + + - Add missing icon for mug + - Fix unit tests (Issue #30) + - Fix Fedora 14 build (broken GTK+ 3) (Issue #31) + +** Release 0.9 <2010-12-04 Sat> + + - you can now search for the message priority ('prio:high', 'prio:low', + 'prio:normal') + - you can now search for message flags, e.g. 'flag:attach' for messages with + attachment, or 'flag:encrypted' for encrypted messages + - you can search for time-intervals, e.g. 'date:2010-11-26..2010-11-29' for + messages in that range. See the mu-find(1) and mu-easy(1) man-pages for + details and examples. + - you can store bookmarked queries in ~/.mu/bookmarks + - the 'flags' parameter has been renamed in 'flag' + - add a simple graphical UI for searching, called 'mug' + - fix --clearlinks for file systems without entry->d_type (fixes issue #28) + - make matching case-insensitive and accent-insensitive (accent-insensitive + for characters in Unicode Blocks 'Latin-1 Supplement' and 'Latin + Extended-A') + - more extensive pre-processing is done to make searching for email-addresses + and message-ids less likely to not work (issue #21) + - updated the man-pages + - experimental support for Fedora 14, which uses GMime 2.5.x (fixes issue #29) + +** Release 0.8 <2010-10-30 Sat> + + - There's now 'mu extract' for getting information about MIME-parts + (attachments) and extracting them + - Queries are now internally converted to lowercase; this solves some of the + false-negative issues + - All mu sub-commands now have their own man-page + - 'mu find' now takes a --summary-len= argument to print a summary of + up-to-n lines of the message + - Same for 'mu view'; the summary replaces the full body + - Setting the mu home dir now goes with -m, --muhome + - --log-stderr, --reindex, --rebuild, --autoupgrade, --nocleanup, --mode, + --linksdir, --clearlinks lost their single char version + +** Release 0.7 <2010-02-27 Sat> + + - Database format changed + - Automatic database scheme version check, notifies users when an upgrade + is needed + - 'mu view', to view mail message files + - Support for >10K matches + - Support for unattended upgrades - that is, the database can automatically + by upgraded (--autoupgrade). Also, the log file is automatically cleaned + when it gets too big (unless you use --nocleanup) + - Search for a certain Maildir using the maildir:,m: search prefixes. For + example, you can find all messages located in ~/Maildir/foo/bar/cur/msg + ~/Maildir/foo/bar/new/msg and with m:/foo/bar this replace the search for + path/p in 0.6 + - Fixes for reported issues () + - A test suite with a growing number of unit tests + + +** Release 0.6 <2010-01-23 Sat> + + - First new release of mu since 2008 + - No longer depends on sqlite + + +# Local Variables: +# mode: org; org-startup-folded: nil +# fill-column:80 +# End: diff --git a/README b/README new file mode 100644 index 0000000..921565b --- /dev/null +++ b/README @@ -0,0 +1,25 @@ +Welcome to mu & mu4e! + +Given the enormous amounts of e-mail many people gather and the importance of e-mail message in our +work-flows, it's essential to quickly deal with all that mail - in particular, to instantly find +that one important e-mail you need right now, and quickly file away message for later use. + +`mu` is a tool for dealing with e-mail messages stored in the Maildir-format. `mu`'s purpose in life +is to help you to quickly find the messages you need; in addition, it allows you to view messages, +extract attachments, create new maildirs, and so on. See the [mu cheatsheet] for some examples. =mu= +is fully documented. + +After indexing your messages into a [Xapian](http://www.xapian.org)-database, you can search them +using a custom query language. You can use various message fields or words in the body text to find +the right messages. + +Built on top of `mu` are some extensions (included in this package): + + * mu4e: a full-featured e-mail client that runs inside emacs + + * mu-guile: bindings for the Guile/Scheme programming language (version 2.2 and later) + +`mu` is written in C and C++; `mu4e` is written in elisp, and `mu-guile` in a mix of C and Scheme. + +Note, `mu` is available in Linux distributions (e.g. Debian/Ubuntu and Fedora) under the name +`maildir-utils`; apparently because they don't like short names. diff --git a/TODO b/TODO new file mode 100644 index 0000000..f152855 --- /dev/null +++ b/TODO @@ -0,0 +1,159 @@ +#+STARTUP: showall + +* TODO (fixes, ideas, etc.) + +** Future stuff + +*** mu + + - put threading information in the database, and enable getting the complete + threads when searching + - refactor fill_database function in test cases + - don't show duplicate e-mails (i.e.. for Gmail); check the message-id + +*** mu-guile + + - move contact export to separate scm + - fix logging + +*** mu4e + + - special-case replying to messages sent by self + - identities (see Jacek's 'mu4e: From field in replies' mail) + ==> [ workaround available, using mu4e-pre-compose-hook, dynamic folders ] + - new-mail warning + ==> [ workaround available, using mu4e-index-updated-hook ] + - custom header fields in headers-view, message-view + - show maildirs as a tree, not a list in speed bar + - review emacs menus + - re-factor / separate window/buffer management + - enable keeping message view buffers around + - better naming for draft/view buffers + - header updating interferes with marks (when updating for 'mark as read', + when reading a marked message) + - set/unset flag editing command + - handling of database upgrades + - restore point after rerunning a search + - make the mu4e-bookmarks format similar to the other ones + - refresh current query after update? + - fix mu4e-mark-set to work from the view buffer as well + - open links to mails through headers-mode somehow (i.e.., + mu4e-view-message-with-msgid) + - improve mouse interaction (i.e., cursor vs point) + - show counts of messages in searches (in main view) + - show flush only if there's something to flush (and # of flushables) + - fix unsafe temp-file handling + - make copy paste name/address in mu4e-view possible + + +* Done (0.9.9.x) + + - mu4e: scroll down –> go to next message + - mu: add contact: as a shortcut for matching from/to/cc/bcc: + - guile integration + - statistics + - 'human' dates in the headers view + - :tags in headers, message view + +* Done + :PROPERTIES: + :VISIBILITY: folded + :END: + + +** Done (0.9.9) + + - make contacts in the view clickable (toggle long/short display, compose message) + - opening urls is too eager (now use M-RET for opening url at point, not just + RET, which conflicted with using RET for scrolling) + - document quoting of queries + - use mu-error + - tooltips in header labels + - tooltip for flags field + - remove --summary option (for mu find, mu view); use --summary-len instead + - add sort buttons to header labels (and do the sorting) + - cleanup mu-cmd-find + - implement --after for mu find, to only show message files changed after a + certain time (mtime) + - add mu:timestamp for guile (referring to the message file's mtime) + - guile automated tests + - add 'mu verify' + - automated tests + - handle verbose/quiet/normal output 'mu verify' + - check gmime 2.4 does not break + - hook up mu4e with 'mu verify' + - add 'help' command + - refactor mu-msg-part + - move widgets/ into toys/mug2, remove toys/mug/, rename toys/mug2 -> toys/mug + - add guile mu:count + - don't show GPG/PKCS7 sigs as attachments + - fix address completion (quote names) + - add support for X-Keywords (in addition to X-Label) + - guile: add stats test cases + - fixed iso-2022-jp (japanese) decoding + - make address completion case-insensitive + - recognize '*' in urls + - handle exception 'The revision being read has been discarded - you should + call Xapian::Database::reopen() and retry the operation' + - handle passwords from get-mail shell command + - support fancy (non-ascii) chars for header flags, thread prefix strings + - improve performance of getting the list of maildirs + - fix setting wrapped/hide state in viewer + - fix ' realpath() failed for...' stuff + - allow for fancy chars (> ascii), make it configurable (mu4e-use-fancy-chars) + - don't user `error' for user-errors + - better echo-area reporting + - improve help feedback for user (command line) + - handling of encrypted messages + - improved checked for gmime-2.6 crypto funcs + - handling of command line options / help + - fix / add support for :size + - mu4e~view-wrap-lines (use visual-line-mode? see Jacek's mu4e~view-wrap-lines + mail) + - better help + - threading optimizations + - actions for /all/ headers, actions for /all/ attachment + - handle attached messages with attachments + +** Done (0.8.9.5) + + - make next/prev header respect prefix argument (Jacek's patch) + - make search results a stack (well, multiple stacks) + - optionally keep cc with user's email + - enable setting/unsetting 'Flagged' on messages + - allow narrowing of search results + - interactive split-view control (Jacek) + - view images inline + - *FIX* slow maildirs when there are many + - *FIX* ignore unrecognized maildir flag letters + - *FIX*: reply-to does not make it to the frontend + - *FIX* wrong buffer deleted after sending (see '(non mu) buffer is killed') + - rich text composing (with org-mode) + - let message-mode deal with burying/killing compose buffers + - *FIX* add runtime check for imagemagick + - *FIX* no error note if target message already exists (when moving) + - sorting + show / hide threads + - *FIX* having multiple header views visible + - *FIX* fix for strings where len (g_utf8_strdown (str)) > len (str) + - make sure marks correspond to the *current* message in message view (see + https://github.com/djcb/mu/issues/26) + - *FIX* don't remove unknown message flags when moving + - make guile/gtk/webkit dependency optional + - improve fringe marks (see https://github.com/djcb/mu/issues/21) + - mark message, decide what to do with them later (i.e.. 'deferred marking') + - custom predicate functions for marking + - make mu4e buffer killing less aggressive (i.e.., DWIM) + - about mu4e + - hide some headers when composing + - fix sorting subjects with ':' (but not 'Re:' or 'Fwd:') + - strip signature from original when replying + - make refresh after changing sort, threads the default + - contact completion (see Jacek's 'mu4e: using' mail) + - *FIX* emacs23 mailto: handling + - *FIX* message interference + - *FIX* emacs23.2+ auto-completion + + +# Local Variables: +# mode: org +# End: diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..1155320 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +test -f mu/mu.cc || { + echo "*** Run this script from the top-level mu source directory" + exit 1 +} + +# opportunistically; usually not needed, but occasionally it'll +# avoid build errors that would otherwise confuse users. +test -f Makefile && { + echo "*** clear out old things" + make distclean 2> /dev/null +} + + +command -V autoreconf > /dev/null +if [ $? != 0 ]; then + echo "*** No autoreconf found, please install it ***" + exit 1 +fi + +rm -f config.cache +rm -rf autom4te.cache + +autoreconf --force --install --verbose || exit $? + +if test -z "$*"; then + echo "# Configuring without parameters" +else + echo "# Configure with parameters $*" +fi + +./configure --config-cache $@ diff --git a/build-aux/config.rpath b/build-aux/config.rpath new file mode 100644 index 0000000..e69de29 diff --git a/c.cfg b/c.cfg new file mode 100644 index 0000000..0a1d2d0 --- /dev/null +++ b/c.cfg @@ -0,0 +1,1578 @@ +# Uncrustify 0.60 + +# +# General options +# + +# The type of line endings +newlines = lf # auto/lf/crlf/cr + +# The original size of tabs in the input +input_tab_size = 8 # number + +# The size of tabs in the output (only used if align_with_tabs=true) +output_tab_size = 8 # number + +# The ASCII value of the string escape char, usually 92 (\) or 94 (^). (Pawn) +string_escape_char = 92 # number + +# Alternate string escape char for Pawn. Only works right before the quote char. +string_escape_char2 = 0 # number + +# Allow interpreting '>=' and '>>=' as part of a template in 'void f(list>=val);'. +# If true (default), 'assert(x<0 && y>=3)' will be broken. +# Improvements to template detection may make this option obsolete. +tok_split_gte = false # false/true + +# Control what to do with the UTF-8 BOM (recommend 'remove') +utf8_bom = ignore # ignore/add/remove/force + +# If the file contains bytes with values between 128 and 255, but is not UTF-8, then output as UTF-8 +utf8_byte = false # false/true + +# Force the output encoding to UTF-8 +utf8_force = false # false/true + +# +# Indenting +# + +# The number of columns to indent per level. +# Usually 2, 3, 4, or 8. +indent_columns = 8 # number + +# The continuation indent. If non-zero, this overrides the indent of '(' and '=' continuation indents. +# For FreeBSD, this is set to 4. Negative value is absolute and not increased for each ( level +indent_continue = 0 # number + +# How to use tabs when indenting code +# 0=spaces only +# 1=indent with tabs to brace level, align with spaces +# 2=indent and align with tabs, using spaces when not on a tabstop +indent_with_tabs = 1 # number + +# Comments that are not a brace level are indented with tabs on a tabstop. +# Requires indent_with_tabs=2. If false, will use spaces. +indent_cmt_with_tabs = false # false/true + +# Whether to indent strings broken by '\' so that they line up +indent_align_string = false # false/true + +# The number of spaces to indent multi-line XML strings. +# Requires indent_align_string=True +indent_xml_string = 0 # number + +# Spaces to indent '{' from level +indent_brace = 0 # number + +# Whether braces are indented to the body level +indent_braces = false # false/true + +# Disabled indenting function braces if indent_braces is true +indent_braces_no_func = false # false/true + +# Disabled indenting class braces if indent_braces is true +indent_braces_no_class = false # false/true + +# Disabled indenting struct braces if indent_braces is true +indent_braces_no_struct = false # false/true + +# Indent based on the size of the brace parent, i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc. +indent_brace_parent = false # false/true + +# Whether the 'namespace' body is indented +indent_namespace = false # false/true + +# The number of spaces to indent a namespace block +indent_namespace_level = 0 # number + +# If the body of the namespace is longer than this number, it won't be indented. +# Requires indent_namespace=true. Default=0 (no limit) +indent_namespace_limit = 0 # number + +# Whether the 'extern "C"' body is indented +indent_extern = false # false/true + +# Whether the 'class' body is indented +indent_class = false # false/true + +# Whether to indent the stuff after a leading class colon +indent_class_colon = false # false/true + +# Virtual indent from the ':' for member initializers. Default is 2 +indent_ctor_init_leading = 2 # number + +# Additional indenting for constructor initializer list +indent_ctor_init = 0 # number + +# False=treat 'else\nif' as 'else if' for indenting purposes +# True=indent the 'if' one level +indent_else_if = false # false/true + +# Amount to indent variable declarations after a open brace. neg=relative, pos=absolute +indent_var_def_blk = 0 # number + +# Indent continued variable declarations instead of aligning. +indent_var_def_cont = false # false/true + +# True: force indentation of function definition to start in column 1 +# False: use the default behavior +indent_func_def_force_col1 = false # false/true + +# True: indent continued function call parameters one indent level +# False: align parameters under the open paren +indent_func_call_param = false # false/true + +# Same as indent_func_call_param, but for function defs +indent_func_def_param = false # false/true + +# Same as indent_func_call_param, but for function protos +indent_func_proto_param = false # false/true + +# Same as indent_func_call_param, but for class declarations +indent_func_class_param = false # false/true + +# Same as indent_func_call_param, but for class variable constructors +indent_func_ctor_var_param = false # false/true + +# Same as indent_func_call_param, but for templates +indent_template_param = false # false/true + +# Double the indent for indent_func_xxx_param options +indent_func_param_double = false # false/true + +# Indentation column for standalone 'const' function decl/proto qualifier +indent_func_const = 0 # number + +# Indentation column for standalone 'throw' function decl/proto qualifier +indent_func_throw = 0 # number + +# The number of spaces to indent a continued '->' or '.' +# Usually set to 0, 1, or indent_columns. +indent_member = 0 # number + +# Spaces to indent single line ('//') comments on lines before code +indent_sing_line_comments = 0 # number + +# If set, will indent trailing single line ('//') comments relative +# to the code instead of trying to keep the same absolute column +indent_relative_single_line_comments = false # false/true + +# Spaces to indent 'case' from 'switch' +# Usually 0 or indent_columns. +indent_switch_case = 0 # number + +# Spaces to shift the 'case' line, without affecting any other lines +# Usually 0. +indent_case_shift = 0 # number + +# Spaces to indent '{' from 'case'. +# By default, the brace will appear under the 'c' in case. +# Usually set to 0 or indent_columns. +indent_case_brace = 0 # number + +# Whether to indent comments found in first column +indent_col1_comment = false # false/true + +# How to indent goto labels +# >0 : absolute column where 1 is the leftmost column +# <=0 : subtract from brace indent +indent_label = 1 # number + +# Same as indent_label, but for access specifiers that are followed by a colon +indent_access_spec = 1 # number + +# Indent the code after an access specifier by one level. +# If set, this option forces 'indent_access_spec=0' +indent_access_spec_body = false # false/true + +# If an open paren is followed by a newline, indent the next line so that it lines up after the open paren (not recommended) +indent_paren_nl = false # false/true + +# Controls the indent of a close paren after a newline. +# 0: Indent to body level +# 1: Align under the open paren +# 2: Indent to the brace level +indent_paren_close = 1 # number + +# Controls the indent of a comma when inside a paren.If TRUE, aligns under the open paren +indent_comma_paren = false # false/true + +# Controls the indent of a BOOL operator when inside a paren.If TRUE, aligns under the open paren +indent_bool_paren = false # false/true + +# If 'indent_bool_paren' is true, controls the indent of the first expression. If TRUE, aligns the first expression to the following ones +indent_first_bool_expr = true # false/true + +# If an open square is followed by a newline, indent the next line so that it lines up after the open square (not recommended) +indent_square_nl = false # false/true + +# Don't change the relative indent of ESQL/C 'EXEC SQL' bodies +indent_preserve_sql = false # false/true + +# Align continued statements at the '='. Default=True +# If FALSE or the '=' is followed by a newline, the next line is indent one tab. +indent_align_assign = true # false/true + +# Indent OC blocks at brace level instead of usual rules. +indent_oc_block = false # false/true + +# Indent OC blocks in a message relative to the parameter name. +# 0=use indent_oc_block rules, 1+=spaces to indent +indent_oc_block_msg = 0 # number + +# Minimum indent for subsequent parameters +indent_oc_msg_colon = 0 # number + +# +# Spacing options +# + +# Add or remove space around arithmetic operator '+', '-', '/', '*', etc +sp_arith = force # ignore/add/remove/force + +# Add or remove space around assignment operator '=', '+=', etc +sp_assign = force # ignore/add/remove/force + +# Add or remove space around '=' in C++11 lambda capture specifications. Overrides sp_assign +sp_cpp_lambda_assign = ignore # ignore/add/remove/force + +# Add or remove space after the capture specification in C++11 lambda. +sp_cpp_lambda_paren = ignore # ignore/add/remove/force + +# Add or remove space around assignment operator '=' in a prototype +sp_assign_default = ignore # ignore/add/remove/force + +# Add or remove space before assignment operator '=', '+=', etc. Overrides sp_assign. +sp_before_assign = ignore # ignore/add/remove/force + +# Add or remove space after assignment operator '=', '+=', etc. Overrides sp_assign. +sp_after_assign = ignore # ignore/add/remove/force + +# Add or remove space around assignment '=' in enum +sp_enum_assign = force # ignore/add/remove/force + +# Add or remove space before assignment '=' in enum. Overrides sp_enum_assign. +sp_enum_before_assign = ignore # ignore/add/remove/force + +# Add or remove space after assignment '=' in enum. Overrides sp_enum_assign. +sp_enum_after_assign = ignore # ignore/add/remove/force + +# Add or remove space around preprocessor '##' concatenation operator. Default=Add +sp_pp_concat = add # ignore/add/remove/force + +# Add or remove space after preprocessor '#' stringify operator. Also affects the '#@' charizing operator. +sp_pp_stringify = ignore # ignore/add/remove/force + +# Add or remove space before preprocessor '#' stringify operator as in '#define x(y) L#y'. +sp_before_pp_stringify = ignore # ignore/add/remove/force + +# Add or remove space around boolean operators '&&' and '||' +sp_bool = force # ignore/add/remove/force + +# Add or remove space around compare operator '<', '>', '==', etc +sp_compare = force # ignore/add/remove/force + +# Add or remove space inside '(' and ')' +sp_inside_paren = ignore # ignore/add/remove/force + +# Add or remove space between nested parens +sp_paren_paren = ignore # ignore/add/remove/force + +# Whether to balance spaces inside nested parens +sp_balance_nested_parens = false # false/true + +# Add or remove space between ')' and '{' +sp_paren_brace = force # ignore/add/remove/force + +# Add or remove space before pointer star '*' +sp_before_ptr_star = force # ignore/add/remove/force + +# Add or remove space before pointer star '*' that isn't followed by a variable name +# If set to 'ignore', sp_before_ptr_star is used instead. +sp_before_unnamed_ptr_star = remove # ignore/add/remove/force + +# Add or remove space between pointer stars '*' +sp_between_ptr_star = remove # ignore/add/remove/force + +# Add or remove space after pointer star '*', if followed by a word. +sp_after_ptr_star = remove # ignore/add/remove/force + +# Add or remove space after a pointer star '*', if followed by a func proto/def. +sp_after_ptr_star_func = ignore # ignore/add/remove/force + +# Add or remove space after a pointer star '*', if followed by an open paren (function types). +sp_ptr_star_paren = ignore # ignore/add/remove/force + +# Add or remove space before a pointer star '*', if followed by a func proto/def. +sp_before_ptr_star_func = ignore # ignore/add/remove/force + +# Add or remove space before a reference sign '&' +sp_before_byref = ignore # ignore/add/remove/force + +# Add or remove space before a reference sign '&' that isn't followed by a variable name +# If set to 'ignore', sp_before_byref is used instead. +sp_before_unnamed_byref = ignore # ignore/add/remove/force + +# Add or remove space after reference sign '&', if followed by a word. +sp_after_byref = ignore # ignore/add/remove/force + +# Add or remove space after a reference sign '&', if followed by a func proto/def. +sp_after_byref_func = ignore # ignore/add/remove/force + +# Add or remove space before a reference sign '&', if followed by a func proto/def. +sp_before_byref_func = ignore # ignore/add/remove/force + +# Add or remove space between type and word. Default=Force +sp_after_type = force # ignore/add/remove/force + +# Add or remove space before the paren in the D constructs 'template Foo(' and 'class Foo('. +sp_before_template_paren = ignore # ignore/add/remove/force + +# Add or remove space in 'template <' vs 'template<'. +# If set to ignore, sp_before_angle is used. +sp_template_angle = ignore # ignore/add/remove/force + +# Add or remove space before '<>' +sp_before_angle = ignore # ignore/add/remove/force + +# Add or remove space inside '<' and '>' +sp_inside_angle = ignore # ignore/add/remove/force + +# Add or remove space after '<>' +sp_after_angle = ignore # ignore/add/remove/force + +# Add or remove space between '<>' and '(' as found in 'new List();' +sp_angle_paren = ignore # ignore/add/remove/force + +# Add or remove space between '<>' and a word as in 'List m;' +sp_angle_word = ignore # ignore/add/remove/force + +# Add or remove space between '>' and '>' in '>>' (template stuff C++/C# only). Default=Add +sp_angle_shift = add # ignore/add/remove/force + +# Permit removal of the space between '>>' in 'foo >' (C++11 only). Default=False +# sp_angle_shift cannot remove the space without this option. +sp_permit_cpp11_shift = false # false/true + +# Add or remove space before '(' of 'if', 'for', 'switch', and 'while' +sp_before_sparen = force # ignore/add/remove/force + +# Add or remove space inside if-condition '(' and ')' +sp_inside_sparen = remove # ignore/add/remove/force + +# Add or remove space before if-condition ')'. Overrides sp_inside_sparen. +sp_inside_sparen_close = ignore # ignore/add/remove/force + +# Add or remove space before if-condition '('. Overrides sp_inside_sparen. +sp_inside_sparen_open = ignore # ignore/add/remove/force + +# Add or remove space after ')' of 'if', 'for', 'switch', and 'while' +sp_after_sparen = ignore # ignore/add/remove/force + +# Add or remove space between ')' and '{' of 'if', 'for', 'switch', and 'while' +sp_sparen_brace = force # ignore/add/remove/force + +# Add or remove space between 'invariant' and '(' in the D language. +sp_invariant_paren = ignore # ignore/add/remove/force + +# Add or remove space after the ')' in 'invariant (C) c' in the D language. +sp_after_invariant_paren = ignore # ignore/add/remove/force + +# Add or remove space before empty statement ';' on 'if', 'for' and 'while' +sp_special_semi = ignore # ignore/add/remove/force + +# Add or remove space before ';'. Default=Remove +sp_before_semi = remove # ignore/add/remove/force + +# Add or remove space before ';' in non-empty 'for' statements +sp_before_semi_for = remove # ignore/add/remove/force + +# Add or remove space before a semicolon of an empty part of a for statement. +sp_before_semi_for_empty = force # ignore/add/remove/force + +# Add or remove space after ';', except when followed by a comment. Default=Add +sp_after_semi = add # ignore/add/remove/force + +# Add or remove space after ';' in non-empty 'for' statements. Default=Force +sp_after_semi_for = force # ignore/add/remove/force + +# Add or remove space after the final semicolon of an empty part of a for statement: for ( ; ; ). +sp_after_semi_for_empty = force # ignore/add/remove/force + +# Add or remove space before '[' (except '[]') +sp_before_square = ignore # ignore/add/remove/force + +# Add or remove space before '[]' +sp_before_squares = ignore # ignore/add/remove/force + +# Add or remove space inside a non-empty '[' and ']' +sp_inside_square = ignore # ignore/add/remove/force + +# Add or remove space after ',' +sp_after_comma = force # ignore/add/remove/force + +# Add or remove space before ',' +sp_before_comma = remove # ignore/add/remove/force + +# Add or remove space between an open paren and comma: '(,' vs '( ,' +sp_paren_comma = force # ignore/add/remove/force + +# Add or remove space before the variadic '...' when preceded by a non-punctuator +sp_before_ellipsis = ignore # ignore/add/remove/force + +# Add or remove space after class ':' +sp_after_class_colon = ignore # ignore/add/remove/force + +# Add or remove space before class ':' +sp_before_class_colon = ignore # ignore/add/remove/force + +# Add or remove space before case ':'. Default=Remove +sp_before_case_colon = remove # ignore/add/remove/force + +# Add or remove space between 'operator' and operator sign +sp_after_operator = ignore # ignore/add/remove/force + +# Add or remove space between the operator symbol and the open paren, as in 'operator ++(' +sp_after_operator_sym = ignore # ignore/add/remove/force + +# Add or remove space after C/D cast, i.e. 'cast(int)a' vs 'cast(int) a' or '(int)a' vs '(int) a' +sp_after_cast = ignore # ignore/add/remove/force + +# Add or remove spaces inside cast parens +sp_inside_paren_cast = ignore # ignore/add/remove/force + +# Add or remove space between the type and open paren in a C++ cast, i.e. 'int(exp)' vs 'int (exp)' +sp_cpp_cast_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'sizeof' and '(' +sp_sizeof_paren = ignore # ignore/add/remove/force + +# Add or remove space after the tag keyword (Pawn) +sp_after_tag = ignore # ignore/add/remove/force + +# Add or remove space inside enum '{' and '}' +sp_inside_braces_enum = force # ignore/add/remove/force + +# Add or remove space inside struct/union '{' and '}' +sp_inside_braces_struct = ignore # ignore/add/remove/force + +# Add or remove space inside '{' and '}' +sp_inside_braces = force # ignore/add/remove/force + +# Add or remove space inside '{}' +sp_inside_braces_empty = remove # ignore/add/remove/force + +# Add or remove space between return type and function name +# A minimum of 1 is forced except for pointer return types. +sp_type_func = ignore # ignore/add/remove/force + +# Add or remove space between function name and '(' on function declaration +sp_func_proto_paren = force # ignore/add/remove/force + +# Add or remove space between function name and '(' on function definition +sp_func_def_paren = force # ignore/add/remove/force + +# Add or remove space inside empty function '()' +sp_inside_fparens = ignore # ignore/add/remove/force + +# Add or remove space inside function '(' and ')' +sp_inside_fparen = ignore # ignore/add/remove/force + +# Add or remove space inside the first parens in the function type: 'void (*x)(...)' +sp_inside_tparen = ignore # ignore/add/remove/force + +# Add or remove between the parens in the function type: 'void (*x)(...)' +sp_after_tparen_close = ignore # ignore/add/remove/force + +# Add or remove space between ']' and '(' when part of a function call. +sp_square_fparen = ignore # ignore/add/remove/force + +# Add or remove space between ')' and '{' of function +sp_fparen_brace = ignore # ignore/add/remove/force + +# Add or remove space between function name and '(' on function calls +sp_func_call_paren = force # ignore/add/remove/force + +# Add or remove space between function name and '()' on function calls without parameters. +# If set to 'ignore' (the default), sp_func_call_paren is used. +sp_func_call_paren_empty = force # ignore/add/remove/force + +# Add or remove space between the user function name and '(' on function calls +# You need to set a keyword to be a user function, like this: 'set func_call_user _' in the config file. +sp_func_call_user_paren = ignore # ignore/add/remove/force + +# Add or remove space between a constructor/destructor and the open paren +sp_func_class_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'return' and '(' +sp_return_paren = ignore # ignore/add/remove/force + +# Add or remove space between '__attribute__' and '(' +sp_attribute_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'defined' and '(' in '#if defined (FOO)' +sp_defined_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'throw' and '(' in 'throw (something)' +sp_throw_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'throw' and anything other than '(' as in '@throw [...];' +sp_after_throw = ignore # ignore/add/remove/force + +# Add or remove space between 'catch' and '(' in 'catch (something) { }' +# If set to ignore, sp_before_sparen is used. +sp_catch_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'version' and '(' in 'version (something) { }' (D language) +# If set to ignore, sp_before_sparen is used. +sp_version_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'scope' and '(' in 'scope (something) { }' (D language) +# If set to ignore, sp_before_sparen is used. +sp_scope_paren = ignore # ignore/add/remove/force + +# Add or remove space between macro and value +sp_macro = force # ignore/add/remove/force + +# Add or remove space between macro function ')' and value +sp_macro_func = force # ignore/add/remove/force + +# Add or remove space between 'else' and '{' if on the same line +sp_else_brace = force # ignore/add/remove/force + +# Add or remove space between '}' and 'else' if on the same line +sp_brace_else = force # ignore/add/remove/force + +# Add or remove space between '}' and the name of a typedef on the same line +sp_brace_typedef = ignore # ignore/add/remove/force + +# Add or remove space between 'catch' and '{' if on the same line +sp_catch_brace = ignore # ignore/add/remove/force + +# Add or remove space between '}' and 'catch' if on the same line +sp_brace_catch = ignore # ignore/add/remove/force + +# Add or remove space between 'finally' and '{' if on the same line +sp_finally_brace = ignore # ignore/add/remove/force + +# Add or remove space between '}' and 'finally' if on the same line +sp_brace_finally = ignore # ignore/add/remove/force + +# Add or remove space between 'try' and '{' if on the same line +sp_try_brace = ignore # ignore/add/remove/force + +# Add or remove space between get/set and '{' if on the same line +sp_getset_brace = ignore # ignore/add/remove/force + +# Add or remove space before the '::' operator +sp_before_dc = ignore # ignore/add/remove/force + +# Add or remove space after the '::' operator +sp_after_dc = ignore # ignore/add/remove/force + +# Add or remove around the D named array initializer ':' operator +sp_d_array_colon = ignore # ignore/add/remove/force + +# Add or remove space after the '!' (not) operator. Default=Remove +sp_not = remove # ignore/add/remove/force + +# Add or remove space after the '~' (invert) operator. Default=Remove +sp_inv = remove # ignore/add/remove/force + +# Add or remove space after the '&' (address-of) operator. Default=Remove +# This does not affect the spacing after a '&' that is part of a type. +sp_addr = remove # ignore/add/remove/force + +# Add or remove space around the '.' or '->' operators. Default=Remove +sp_member = remove # ignore/add/remove/force + +# Add or remove space after the '*' (dereference) operator. Default=Remove +# This does not affect the spacing after a '*' that is part of a type. +sp_deref = remove # ignore/add/remove/force + +# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. Default=Remove +sp_sign = remove # ignore/add/remove/force + +# Add or remove space before or after '++' and '--', as in '(--x)' or 'y++;'. Default=Remove +sp_incdec = remove # ignore/add/remove/force + +# Add or remove space before a backslash-newline at the end of a line. Default=Add +sp_before_nl_cont = force # ignore/add/remove/force + +# Add or remove space after the scope '+' or '-', as in '-(void) foo;' or '+(int) bar;' +sp_after_oc_scope = ignore # ignore/add/remove/force + +# Add or remove space after the colon in message specs +# '-(int) f:(int) x;' vs '-(int) f: (int) x;' +sp_after_oc_colon = ignore # ignore/add/remove/force + +# Add or remove space before the colon in message specs +# '-(int) f: (int) x;' vs '-(int) f : (int) x;' +sp_before_oc_colon = ignore # ignore/add/remove/force + +# Add or remove space after the colon in immutable dictionary expression +# 'NSDictionary *test = @{@"foo" :@"bar"};' +sp_after_oc_dict_colon = ignore # ignore/add/remove/force + +# Add or remove space before the colon in immutable dictionary expression +# 'NSDictionary *test = @{@"foo" :@"bar"};' +sp_before_oc_dict_colon = ignore # ignore/add/remove/force + +# Add or remove space after the colon in message specs +# '[object setValue:1];' vs '[object setValue: 1];' +sp_after_send_oc_colon = ignore # ignore/add/remove/force + +# Add or remove space before the colon in message specs +# '[object setValue:1];' vs '[object setValue :1];' +sp_before_send_oc_colon = ignore # ignore/add/remove/force + +# Add or remove space after the (type) in message specs +# '-(int)f: (int) x;' vs '-(int)f: (int)x;' +sp_after_oc_type = ignore # ignore/add/remove/force + +# Add or remove space after the first (type) in message specs +# '-(int) f:(int)x;' vs '-(int)f:(int)x;' +sp_after_oc_return_type = ignore # ignore/add/remove/force + +# Add or remove space between '@selector' and '(' +# '@selector(msgName)' vs '@selector (msgName)' +# Also applies to @protocol() constructs +sp_after_oc_at_sel = ignore # ignore/add/remove/force + +# Add or remove space between '@selector(x)' and the following word +# '@selector(foo) a:' vs '@selector(foo)a:' +sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force + +# Add or remove space inside '@selector' parens +# '@selector(foo)' vs '@selector( foo )' +# Also applies to @protocol() constructs +sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force + +# Add or remove space before a block pointer caret +# '^int (int arg){...}' vs. ' ^int (int arg){...}' +sp_before_oc_block_caret = ignore # ignore/add/remove/force + +# Add or remove space after a block pointer caret +# '^int (int arg){...}' vs. '^ int (int arg){...}' +sp_after_oc_block_caret = ignore # ignore/add/remove/force + +# Add or remove space between the receiver and selector in a message. +# '[receiver selector ...]' +sp_after_oc_msg_receiver = ignore # ignore/add/remove/force + +# Add or remove space after @property. +sp_after_oc_property = ignore # ignore/add/remove/force + +# Add or remove space around the ':' in 'b ? t : f' +sp_cond_colon = force # ignore/add/remove/force + +# Add or remove space around the '?' in 'b ? t : f' +sp_cond_question = force # ignore/add/remove/force + +# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make sense here. +sp_case_label = force # ignore/add/remove/force + +# Control the space around the D '..' operator. +sp_range = ignore # ignore/add/remove/force + +# Control the spacing after ':' in 'for (TYPE VAR : EXPR)' (Java) +sp_after_for_colon = ignore # ignore/add/remove/force + +# Control the spacing before ':' in 'for (TYPE VAR : EXPR)' (Java) +sp_before_for_colon = ignore # ignore/add/remove/force + +# Control the spacing in 'extern (C)' (D) +sp_extern_paren = ignore # ignore/add/remove/force + +# Control the space after the opening of a C++ comment '// A' vs '//A' +sp_cmt_cpp_start = force # ignore/add/remove/force + +# Controls the spaces between #else or #endif and a trailing comment +sp_endif_cmt = ignore # ignore/add/remove/force + +# Controls the spaces after 'new', 'delete', and 'delete[]' +sp_after_new = ignore # ignore/add/remove/force + +# Controls the spaces before a trailing or embedded comment +sp_before_tr_emb_cmt = ignore # ignore/add/remove/force + +# Number of spaces before a trailing or embedded comment +sp_num_before_tr_emb_cmt = 0 # number + +# Control space between a Java annotation and the open paren. +sp_annotation_paren = ignore # ignore/add/remove/force + +# +# Code alignment (not left column spaces/tabs) +# + +# Whether to keep non-indenting tabs +align_keep_tabs = false # false/true + +# Whether to use tabs for aligning +align_with_tabs = false # false/true + +# Whether to bump out to the next tab when aligning +align_on_tabstop = false # false/true + +# Whether to left-align numbers +align_number_left = false # false/true + +# Align variable definitions in prototypes and functions +align_func_params = true # false/true + +# Align parameters in single-line functions that have the same name. +# The function names must already be aligned with each other. +align_same_func_call_params = false # false/true + +# The span for aligning variable definitions (0=don't align) +align_var_def_span = 1 # number + +# How to align the star in variable definitions. +# 0=Part of the type 'void * foo;' +# 1=Part of the variable 'void *foo;' +# 2=Dangling 'void *foo;' +align_var_def_star_style = 1 # number + +# How to align the '&' in variable definitions. +# 0=Part of the type +# 1=Part of the variable +# 2=Dangling +align_var_def_amp_style = 0 # number + +# The threshold for aligning variable definitions (0=no limit) +align_var_def_thresh = 0 # number + +# The gap for aligning variable definitions +align_var_def_gap = 0 # number + +# Whether to align the colon in struct bit fields +align_var_def_colon = false # false/true + +# Whether to align any attribute after the variable name +align_var_def_attribute = false # false/true + +# Whether to align inline struct/enum/union variable definitions +align_var_def_inline = false # false/true + +# The span for aligning on '=' in assignments (0=don't align) +align_assign_span = 1 # number + +# The threshold for aligning on '=' in assignments (0=no limit) +align_assign_thresh = 0 # number + +# The span for aligning on '=' in enums (0=don't align) +align_enum_equ_span = 1 # number + +# The threshold for aligning on '=' in enums (0=no limit) +align_enum_equ_thresh = 0 # number + +# The span for aligning struct/union (0=don't align) +align_var_struct_span = 1 # number + +# The threshold for aligning struct/union member definitions (0=no limit) +align_var_struct_thresh = 0 # number + +# The gap for aligning struct/union member definitions +align_var_struct_gap = 0 # number + +# The span for aligning struct initializer values (0=don't align) +align_struct_init_span = 1 # number + +# The minimum space between the type and the synonym of a typedef +align_typedef_gap = 0 # number + +# The span for aligning single-line typedefs (0=don't align) +align_typedef_span = 1 # number + +# How to align typedef'd functions with other typedefs +# 0: Don't mix them at all +# 1: align the open paren with the types +# 2: align the function type name with the other type names +align_typedef_func = 0 # number + +# Controls the positioning of the '*' in typedefs. Just try it. +# 0: Align on typedef type, ignore '*' +# 1: The '*' is part of type name: typedef int *pint; +# 2: The '*' is part of the type, but dangling: typedef int *pint; +align_typedef_star_style = 0 # number + +# Controls the positioning of the '&' in typedefs. Just try it. +# 0: Align on typedef type, ignore '&' +# 1: The '&' is part of type name: typedef int &pint; +# 2: The '&' is part of the type, but dangling: typedef int &pint; +align_typedef_amp_style = 0 # number + +# The span for aligning comments that end lines (0=don't align) +align_right_cmt_span = 1 # number + +# If aligning comments, mix with comments after '}' and #endif with less than 3 spaces before the comment +align_right_cmt_mix = false # false/true + +# If a trailing comment is more than this number of columns away from the text it follows, +# it will qualify for being aligned. This has to be > 0 to do anything. +align_right_cmt_gap = 1 # number + +# Align trailing comment at or beyond column N; 'pulls in' comments as a bonus side effect (0=ignore) +align_right_cmt_at_col = 0 # number + +# The span for aligning function prototypes (0=don't align) +align_func_proto_span = 0 # number + +# Minimum gap between the return type and the function name. +align_func_proto_gap = 0 # number + +# Align function protos on the 'operator' keyword instead of what follows +align_on_operator = false # false/true + +# Whether to mix aligning prototype and variable declarations. +# If true, align_var_def_XXX options are used instead of align_func_proto_XXX options. +align_mix_var_proto = false # false/true + +# Align single-line functions with function prototypes, uses align_func_proto_span +align_single_line_func = false # false/true + +# Aligning the open brace of single-line functions. +# Requires align_single_line_func=true, uses align_func_proto_span +align_single_line_brace = false # false/true + +# Gap for align_single_line_brace. +align_single_line_brace_gap = 0 # number + +# The span for aligning ObjC msg spec (0=don't align) +align_oc_msg_spec_span = 0 # number + +# Whether to align macros wrapped with a backslash and a newline. +# This will not work right if the macro contains a multi-line comment. +align_nl_cont = true # false/true + +# # Align macro functions and variables together +align_pp_define_together = true # false/true + +# The minimum space between label and value of a preprocessor define +align_pp_define_gap = 0 # number + +# The span for aligning on '#define' bodies (0=don't align) +align_pp_define_span = 1 # number + +# Align lines that start with '<<' with previous '<<'. Default=true +align_left_shift = true # false/true + +# Span for aligning parameters in an Obj-C message call on the ':' (0=don't align) +align_oc_msg_colon_span = 0 # number + +# If true, always align with the first parameter, even if it is too short. +align_oc_msg_colon_first = false # false/true + +# Aligning parameters in an Obj-C '+' or '-' declaration on the ':' +align_oc_decl_colon = false # false/true + +# +# Newline adding and removing options +# + +# Whether to collapse empty blocks between '{' and '}' +nl_collapse_empty_body = false # false/true + +# Don't split one-line braced assignments - 'foo_t f = { 1, 2 };' +nl_assign_leave_one_liners = false # false/true + +# Don't split one-line braced statements inside a class xx { } body +nl_class_leave_one_liners = false # false/true + +# Don't split one-line enums: 'enum foo { BAR = 15 };' +nl_enum_leave_one_liners = false # false/true + +# Don't split one-line get or set functions +nl_getset_leave_one_liners = false # false/true + +# Don't split one-line function definitions - 'int foo() { return 0; }' +nl_func_leave_one_liners = false # false/true + +# Don't split one-line if/else statements - 'if(a) b++;' +nl_if_leave_one_liners = false # false/true + +# Don't split one-line OC messages +nl_oc_msg_leave_one_liner = false # false/true + +# Add or remove newlines at the start of the file +nl_start_of_file = ignore # ignore/add/remove/force + +# The number of newlines at the start of the file (only used if nl_start_of_file is 'add' or 'force' +nl_start_of_file_min = 0 # number + +# Add or remove newline at the end of the file +nl_end_of_file = force # ignore/add/remove/force + +# The number of newlines at the end of the file (only used if nl_end_of_file is 'add' or 'force') +nl_end_of_file_min = 1 # number + +# Add or remove newline between '=' and '{' +nl_assign_brace = force # ignore/add/remove/force + +# Add or remove newline between '=' and '[' (D only) +nl_assign_square = ignore # ignore/add/remove/force + +# Add or remove newline after '= [' (D only). Will also affect the newline before the ']' +nl_after_square_assign = ignore # ignore/add/remove/force + +# The number of blank lines after a block of variable definitions at the top of a function body +# 0 = No change (default) +nl_func_var_def_blk = 0 # number + +# The number of newlines before a block of typedefs +# 0 = No change (default) +nl_typedef_blk_start = 0 # number + +# The number of newlines after a block of typedefs +# 0 = No change (default) +nl_typedef_blk_end = 0 # number + +# The maximum consecutive newlines within a block of typedefs +# 0 = No change (default) +nl_typedef_blk_in = 0 # number + +# The number of newlines before a block of variable definitions not at the top of a function body +# 0 = No change (default) +nl_var_def_blk_start = 0 # number + +# The number of newlines after a block of variable definitions not at the top of a function body +# 0 = No change (default) +nl_var_def_blk_end = 0 # number + +# The maximum consecutive newlines within a block of variable definitions +# 0 = No change (default) +nl_var_def_blk_in = 0 # number + +# Add or remove newline between a function call's ')' and '{', as in: +# list_for_each(item, &list) { } +nl_fcall_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum' and '{' +nl_enum_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'struct and '{' +nl_struct_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'union' and '{' +nl_union_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'if' and '{' +nl_if_brace = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and 'else' +nl_brace_else = ignore # ignore/add/remove/force + +# Add or remove newline between 'else if' and '{' +# If set to ignore, nl_if_brace is used instead +nl_elseif_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'else' and '{' +nl_else_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'else' and 'if' +nl_else_if = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and 'finally' +nl_brace_finally = ignore # ignore/add/remove/force + +# Add or remove newline between 'finally' and '{' +nl_finally_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'try' and '{' +nl_try_brace = ignore # ignore/add/remove/force + +# Add or remove newline between get/set and '{' +nl_getset_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'for' and '{' +nl_for_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'catch' and '{' +nl_catch_brace = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and 'catch' +nl_brace_catch = ignore # ignore/add/remove/force + +# Add or remove newline between 'while' and '{' +nl_while_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'scope (x)' and '{' (D) +nl_scope_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'unittest' and '{' (D) +nl_unittest_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'version (x)' and '{' (D) +nl_version_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'using' and '{' +nl_using_brace = ignore # ignore/add/remove/force + +# Add or remove newline between two open or close braces. +# Due to general newline/brace handling, REMOVE may not work. +nl_brace_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'do' and '{' +nl_do_brace = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and 'while' of 'do' statement +nl_brace_while = ignore # ignore/add/remove/force + +# Add or remove newline between 'switch' and '{' +nl_switch_brace = ignore # ignore/add/remove/force + +# Add a newline between ')' and '{' if the ')' is on a different line than the if/for/etc. +# Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch, and nl_catch_brace. +nl_multi_line_cond = false # false/true + +# Force a newline in a define after the macro name for multi-line defines. +nl_multi_line_define = true # false/true + +# Whether to put a newline before 'case' statement +nl_before_case = false # false/true + +# Add or remove newline between ')' and 'throw' +nl_before_throw = ignore # ignore/add/remove/force + +# Whether to put a newline after 'case' statement +nl_after_case = false # false/true + +# Add or remove a newline between a case ':' and '{'. Overrides nl_after_case. +nl_case_colon_brace = ignore # ignore/add/remove/force + +# Newline between namespace and { +nl_namespace_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'template<>' and whatever follows. +nl_template_class = ignore # ignore/add/remove/force + +# Add or remove newline between 'class' and '{' +nl_class_brace = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in the constructor member initialization +nl_class_init_args = ignore # ignore/add/remove/force + +# Add or remove newline between return type and function name in a function definition +nl_func_type_name = force # ignore/add/remove/force + +# Add or remove newline between return type and function name inside a class {} +# Uses nl_func_type_name or nl_func_proto_type_name if set to ignore. +nl_func_type_name_class = ignore # ignore/add/remove/force + +# Add or remove newline between function scope and name in a definition +# Controls the newline after '::' in 'void A::f() { }' +nl_func_scope_name = ignore # ignore/add/remove/force + +# Add or remove newline between return type and function name in a prototype +nl_func_proto_type_name = ignore # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' +nl_func_paren = ignore # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' in the definition +nl_func_def_paren = ignore # ignore/add/remove/force + +# Add or remove newline after '(' in a function declaration +nl_func_decl_start = ignore # ignore/add/remove/force + +# Add or remove newline after '(' in a function definition +nl_func_def_start = ignore # ignore/add/remove/force + +# Overrides nl_func_decl_start when there is only one parameter. +nl_func_decl_start_single = ignore # ignore/add/remove/force + +# Overrides nl_func_def_start when there is only one parameter. +nl_func_def_start_single = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in a function declaration +nl_func_decl_args = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in a function definition +nl_func_def_args = ignore # ignore/add/remove/force + +# Add or remove newline before the ')' in a function declaration +nl_func_decl_end = ignore # ignore/add/remove/force + +# Add or remove newline before the ')' in a function definition +nl_func_def_end = ignore # ignore/add/remove/force + +# Overrides nl_func_decl_end when there is only one parameter. +nl_func_decl_end_single = ignore # ignore/add/remove/force + +# Overrides nl_func_def_end when there is only one parameter. +nl_func_def_end_single = ignore # ignore/add/remove/force + +# Add or remove newline between '()' in a function declaration. +nl_func_decl_empty = ignore # ignore/add/remove/force + +# Add or remove newline between '()' in a function definition. +nl_func_def_empty = ignore # ignore/add/remove/force + +# Whether to put each OC message parameter on a separate line +# See nl_oc_msg_leave_one_liner +nl_oc_msg_args = false # false/true + +# Add or remove newline between function signature and '{' +nl_fdef_brace = force # ignore/add/remove/force + +# Add or remove a newline between the return keyword and return expression. +nl_return_expr = ignore # ignore/add/remove/force + +# Whether to put a newline after semicolons, except in 'for' statements +nl_after_semicolon = false # false/true + +# Whether to put a newline after brace open. +# This also adds a newline before the matching brace close. +nl_after_brace_open = false # false/true + +# If nl_after_brace_open and nl_after_brace_open_cmt are true, a newline is +# placed between the open brace and a trailing single-line comment. +nl_after_brace_open_cmt = false # false/true + +# Whether to put a newline after a virtual brace open with a non-empty body. +# These occur in un-braced if/while/do/for statement bodies. +nl_after_vbrace_open = false # false/true + +# Whether to put a newline after a virtual brace open with an empty body. +# These occur in un-braced if/while/do/for statement bodies. +nl_after_vbrace_open_empty = false # false/true + +# Whether to put a newline after a brace close. +# Does not apply if followed by a necessary ';'. +nl_after_brace_close = false # false/true + +# Whether to put a newline after a virtual brace close. +# Would add a newline before return in: 'if (foo) a++; return;' +nl_after_vbrace_close = false # false/true + +# Control the newline between the close brace and 'b' in: 'struct { int a; } b;' +# Affects enums, unions, and structures. If set to ignore, uses nl_after_brace_close +nl_brace_struct_var = ignore # ignore/add/remove/force + +# Whether to alter newlines in '#define' macros +nl_define_macro = false # false/true + +# Whether to not put blanks after '#ifxx', '#elxx', or before '#endif' +nl_squeeze_ifdef = false # false/true + +# Add or remove blank line before 'if' +nl_before_if = ignore # ignore/add/remove/force + +# Add or remove blank line after 'if' statement +nl_after_if = ignore # ignore/add/remove/force + +# Add or remove blank line before 'for' +nl_before_for = ignore # ignore/add/remove/force + +# Add or remove blank line after 'for' statement +nl_after_for = ignore # ignore/add/remove/force + +# Add or remove blank line before 'while' +nl_before_while = ignore # ignore/add/remove/force + +# Add or remove blank line after 'while' statement +nl_after_while = ignore # ignore/add/remove/force + +# Add or remove blank line before 'switch' +nl_before_switch = force # ignore/add/remove/force + +# Add or remove blank line after 'switch' statement +nl_after_switch = force # ignore/add/remove/force + +# Add or remove blank line before 'do' +nl_before_do = ignore # ignore/add/remove/force + +# Add or remove blank line after 'do/while' statement +nl_after_do = ignore # ignore/add/remove/force + +# Whether to double-space commented-entries in struct/enum +nl_ds_struct_enum_cmt = false # false/true + +# Whether to double-space before the close brace of a struct/union/enum +# (lower priority than 'eat_blanks_before_close_brace)' +nl_ds_struct_enum_close_brace = false # false/true + +# Add or remove a newline around a class colon. +# Related to pos_class_colon, nl_class_init_args, and pos_comma. +nl_class_colon = ignore # ignore/add/remove/force + +# Change simple unbraced if statements into a one-liner +# 'if(b)\n i++;' => 'if(b) i++;' +nl_create_if_one_liner = false # false/true + +# Change simple unbraced for statements into a one-liner +# 'for (i=0;i<5;i++)\n foo(i);' => 'for (i=0;i<5;i++) foo(i);' +nl_create_for_one_liner = false # false/true + +# Change simple unbraced while statements into a one-liner +# 'while (i<5)\n foo(i++);' => 'while (i<5) foo(i++);' +nl_create_while_one_liner = false # false/true + +# +# Positioning options +# + +# The position of arithmetic operators in wrapped expressions +pos_arith = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of assignment in wrapped expressions. +# Do not affect '=' followed by '{' +pos_assign = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of boolean operators in wrapped expressions +pos_bool = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of comparison operators in wrapped expressions +pos_compare = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of conditional (b ? t : f) operators in wrapped expressions +pos_conditional = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of the comma in wrapped expressions +pos_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of the comma in the constructor initialization list +pos_class_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of colons between constructor and member initialization +pos_class_colon = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# +# Line Splitting options +# + +# Try to limit code width to N number of columns +code_width = 80 # number + +# Whether to fully split long 'for' statements at semi-colons +ls_for_split_full = false # false/true + +# Whether to fully split long function protos/calls at commas +ls_func_split_full = false # false/true + +# Whether to split lines as close to code_width as possible and ignore some groupings +ls_code_width = false # false/true + +# +# Blank line options +# + +# The maximum consecutive newlines +nl_max = 0 # number + +# The number of newlines after a function prototype, if followed by another function prototype +nl_after_func_proto = 0 # number + +# The number of newlines after a function prototype, if not followed by another function prototype +nl_after_func_proto_group = 0 # number + +# The number of newlines after '}' of a multi-line function body +nl_after_func_body = 0 # number + +# The number of newlines after '}' of a multi-line function body in a class declaration +nl_after_func_body_class = 0 # number + +# The number of newlines after '}' of a single line function body +nl_after_func_body_one_liner = 0 # number + +# The minimum number of newlines before a multi-line comment. +# Doesn't apply if after a brace open or another multi-line comment. +nl_before_block_comment = 0 # number + +# The minimum number of newlines before a single-line C comment. +# Doesn't apply if after a brace open or other single-line C comments. +nl_before_c_comment = 0 # number + +# The minimum number of newlines before a CPP comment. +# Doesn't apply if after a brace open or other CPP comments. +nl_before_cpp_comment = 0 # number + +# Whether to force a newline after a multi-line comment. +nl_after_multiline_comment = false # false/true + +# The number of newlines after '}' or ';' of a struct/enum/union definition +nl_after_struct = 0 # number + +# The number of newlines after '}' or ';' of a class definition +nl_after_class = 0 # number + +# The number of newlines before a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label. +# Will not change the newline count if after a brace open. +# 0 = No change. +nl_before_access_spec = 0 # number + +# The number of newlines after a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label. +# 0 = No change. +nl_after_access_spec = 0 # number + +# The number of newlines between a function def and the function comment. +# 0 = No change. +nl_comment_func_def = 0 # number + +# The number of newlines after a try-catch-finally block that isn't followed by a brace close. +# 0 = No change. +nl_after_try_catch_finally = 0 # number + +# The number of newlines before and after a property, indexer or event decl. +# 0 = No change. +nl_around_cs_property = 0 # number + +# The number of newlines between the get/set/add/remove handlers in C#. +# 0 = No change. +nl_between_get_set = 0 # number + +# Add or remove newline between C# property and the '{' +nl_property_brace = ignore # ignore/add/remove/force + +# Whether to remove blank lines after '{' +eat_blanks_after_open_brace = false # false/true + +# Whether to remove blank lines before '}' +eat_blanks_before_close_brace = false # false/true + +# How aggressively to remove extra newlines not in preproc. +# 0: No change +# 1: Remove most newlines not handled by other config +# 2: Remove all newlines and reformat completely by config +nl_remove_extra_newlines = 0 # number + +# Whether to put a blank line before 'return' statements, unless after an open brace. +nl_before_return = true # false/true + +# Whether to put a blank line after 'return' statements, unless followed by a close brace. +nl_after_return = false # false/true + +# Whether to put a newline after a Java annotation statement. +# Only affects annotations that are after a newline. +nl_after_annotation = ignore # ignore/add/remove/force + +# Controls the newline between two annotations. +nl_between_annotation = ignore # ignore/add/remove/force + +# +# Code modifying options (non-whitespace) +# + +# Add or remove braces on single-line 'do' statement +mod_full_brace_do = ignore # ignore/add/remove/force + +# Add or remove braces on single-line 'for' statement +mod_full_brace_for = ignore # ignore/add/remove/force + +# Add or remove braces on single-line function definitions. (Pawn) +mod_full_brace_function = ignore # ignore/add/remove/force + +# Add or remove braces on single-line 'if' statement. Will not remove the braces if they contain an 'else'. +mod_full_brace_if = ignore # ignore/add/remove/force + +# Make all if/elseif/else statements in a chain be braced or not. Overrides mod_full_brace_if. +# If any must be braced, they are all braced. If all can be unbraced, then the braces are removed. +mod_full_brace_if_chain = false # false/true + +# Don't remove braces around statements that span N newlines +mod_full_brace_nl = 0 # number + +# Add or remove braces on single-line 'while' statement +mod_full_brace_while = ignore # ignore/add/remove/force + +# Add or remove braces on single-line 'using ()' statement +mod_full_brace_using = ignore # ignore/add/remove/force + +# Add or remove unnecessary paren on 'return' statement +mod_paren_on_return = remove # ignore/add/remove/force + +# Whether to change optional semicolons to real semicolons +mod_pawn_semicolon = false # false/true + +# Add parens on 'while' and 'if' statement around bools +mod_full_paren_if_bool = false # false/true + +# Whether to remove superfluous semicolons +mod_remove_extra_semicolon = false # false/true + +# If a function body exceeds the specified number of newlines and doesn't have a comment after +# the close brace, a comment will be added. +mod_add_long_function_closebrace_comment = 0 # number + +# If a switch body exceeds the specified number of newlines and doesn't have a comment after +# the close brace, a comment will be added. +mod_add_long_switch_closebrace_comment = 0 # number + +# If an #ifdef body exceeds the specified number of newlines and doesn't have a comment after +# the #endif, a comment will be added. +mod_add_long_ifdef_endif_comment = 1 # number + +# If an #ifdef or #else body exceeds the specified number of newlines and doesn't have a comment after +# the #else, a comment will be added. +mod_add_long_ifdef_else_comment = 1 # number + +# If TRUE, will sort consecutive single-line 'import' statements [Java, D] +mod_sort_import = false # false/true + +# If TRUE, will sort consecutive single-line 'using' statements [C#] +mod_sort_using = false # false/true + +# If TRUE, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C] +# This is generally a bad idea, as it may break your code. +mod_sort_include = false # false/true + +# If TRUE, it will move a 'break' that appears after a fully braced 'case' before the close brace. +mod_move_case_break = true # false/true + +# Will add or remove the braces around a fully braced case statement. +# Will only remove the braces if there are no variable declarations in the block. +mod_case_brace = ignore # ignore/add/remove/force + +# If TRUE, it will remove a void 'return;' that appears as the last statement in a function. +mod_remove_empty_return = true # false/true + +# +# Comment modifications +# + +# Try to wrap comments at cmt_width columns +cmt_width = 80 # number + +# Set the comment reflow mode (default: 0) +# 0: no reflowing (apart from the line wrapping due to cmt_width) +# 1: no touching at all +# 2: full reflow +cmt_reflow_mode = 0 # number + +# If false, disable all multi-line comment changes, including cmt_width. keyword substitution, and leading chars. +# Default is true. +cmt_indent_multi = true # false/true + +# Whether to group c-comments that look like they are in a block +cmt_c_group = false # false/true + +# Whether to put an empty '/*' on the first line of the combined c-comment +cmt_c_nl_start = false # false/true + +# Whether to put a newline before the closing '*/' of the combined c-comment +cmt_c_nl_end = true # false/true + +# Whether to group cpp-comments that look like they are in a block +cmt_cpp_group = false # false/true + +# Whether to put an empty '/*' on the first line of the combined cpp-comment +cmt_cpp_nl_start = false # false/true + +# Whether to put a newline before the closing '*/' of the combined cpp-comment +cmt_cpp_nl_end = true # false/true + +# Whether to change cpp-comments into c-comments +cmt_cpp_to_c = true # false/true + +# Whether to put a star on subsequent comment lines +cmt_star_cont = true # false/true + +# The number of spaces to insert at the start of subsequent comment lines +cmt_sp_before_star_cont = 0 # number + +# The number of spaces to insert after the star on subsequent comment lines +cmt_sp_after_star_cont = 0 # number + +# For multi-line comments with a '*' lead, remove leading spaces if the first and last lines of +# the comment are the same length. Default=True +cmt_multi_check_last = true # false/true + +# The filename that contains text to insert at the head of a file if the file doesn't start with a C/C++ comment. +# Will substitute $(filename) with the current file's name. +cmt_insert_file_header = "" # string + +# The filename that contains text to insert at the end of a file if the file doesn't end with a C/C++ comment. +# Will substitute $(filename) with the current file's name. +cmt_insert_file_footer = "" # string + +# The filename that contains text to insert before a function implementation if the function isn't preceded with a C/C++ comment. +# Will substitute $(function) with the function name and $(javaparam) with the javadoc @param and @return stuff. +# Will also substitute $(fclass) with the class name: void CFoo::Bar() { ... } +cmt_insert_func_header = "" # string + +# The filename that contains text to insert before a class if the class isn't preceded with a C/C++ comment. +# Will substitute $(class) with the class name. +cmt_insert_class_header = "" # string + +# The filename that contains text to insert before a Obj-C message specification if the method isn't preceded with a C/C++ comment. +# Will substitute $(message) with the function name and $(javaparam) with the javadoc @param and @return stuff. +cmt_insert_oc_msg_header = "" # string + +# If a preprocessor is encountered when stepping backwards from a function name, then +# this option decides whether the comment should be inserted. +# Affects cmt_insert_oc_msg_header, cmt_insert_func_header and cmt_insert_class_header. +cmt_insert_before_preproc = false # false/true + +# +# Preprocessor options +# + +# Control indent of preprocessors inside #if blocks at brace level 0 +pp_indent = ignore # ignore/add/remove/force + +# Whether to indent #if/#else/#endif at the brace level (true) or from column 1 (false) +pp_indent_at_level = false # false/true + +# If pp_indent_at_level=false, specifies the number of columns to indent per level. Default=1. +pp_indent_count = 1 # number + +# Add or remove space after # based on pp_level of #if blocks +pp_space = ignore # ignore/add/remove/force + +# Sets the number of spaces added with pp_space +pp_space_count = 0 # number + +# The indent for #region and #endregion in C# and '#pragma region' in C/C++ +pp_indent_region = 0 # number + +# Whether to indent the code between #region and #endregion +pp_region_indent_code = false # false/true + +# If pp_indent_at_level=true, sets the indent for #if, #else, and #endif when not at file-level +pp_indent_if = 0 # number + +# Control whether to indent the code between #if, #else and #endif when not at file-level +pp_if_indent_code = false # false/true + +# Whether to indent '#define' at the brace level (true) or from column 1 (false) +pp_define_at_level = false # false/true + +# You can force a token to be a type with the 'type' option. +# Example: +# type myfoo1 myfoo2 +# +# You can create custom macro-based indentation using macro-open, +# macro-else and macro-close. +# Example: +# macro-open BEGIN_TEMPLATE_MESSAGE_MAP +# macro-open BEGIN_MESSAGE_MAP +# macro-close END_MESSAGE_MAP +# +# You can assign any keyword to any type with the set option. +# set func_call_user _ N_ +# +# The full syntax description of all custom definition config entries +# is shown below: +# +# define custom tokens as: +# - embed whitespace in token using '' escape character, or +# put token in quotes +# - these: ' " and ` are recognized as quote delimiters +# +# type token1 token2 token3 ... +# ^ optionally specify multiple tokens on a single line +# define def_token output_token +# ^ output_token is optional, then NULL is assumed +# macro-open token +# macro-close token +# macro-else token +# set id token1 token2 ... +# ^ optionally specify multiple tokens on a single line +# ^ id is one of the names in token_enum.h sans the CT_ prefix, +# e.g. PP_PRAGMA +# +# all tokens are separated by any mix of ',' commas, '=' equal signs +# and whitespace (space, tab) +# diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..9740eed --- /dev/null +++ b/configure.ac @@ -0,0 +1,360 @@ +## Copyright (C) 2008-2020 Dirk-Jan C. Binnema +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +AC_PREREQ([2.68]) +AC_INIT([mu],[1.4.15],[https://github.com/djcb/mu/issues],[mu]) +AC_COPYRIGHT([Copyright (C) 2008-2020 Dirk-Jan C. Binnema]) +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_SRCDIR([mu/mu.cc]) +# libtoolize wants to put some stuff in here; if you have an old +# autotools/libtool setup. you can try to comment this out +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_AUX_DIR([build-aux]) + +m4_ifdef([AX_IS_RELEASE],[AX_IS_RELEASE([git-directory])]) +m4_ifdef([AX_CHECK_ENABLE_DEBUG],[AX_CHECK_ENABLE_DEBUG([yes])]) + +AM_INIT_AUTOMAKE([1.14 foreign no-dist-gzip tar-ustar dist-xz]) + +# silent build if we have a new enough automake +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +AS_IF([test x$prefix = xNONE],[prefix=/usr/local]) +AC_SUBST(prefix) + +# AC_PROG_CXX *before* AC_PROG_CC, otherwise configure won't error out +# when a c++ compiler is not found. Weird, huh? +AC_PROG_CXX +AC_PROG_CC +AC_PROG_CC_STDC +AC_PROG_CC_C99 +AC_PROG_INSTALL +AC_HEADER_STDC + +extra_flags="-Wformat-security \ + -Wstack-protector \ + -Wstack-protector-all \ + -Wno-cast-function-type" + +AX_CXX_COMPILE_STDCXX_14 +m4_ifdef([AX_COMPILER_FLAGS],[AX_COMPILER_FLAGS(,,[yes],${extra_flags})]) +AX_VALGRIND_CHECK + +LT_INIT + +AX_CODE_COVERAGE + +AC_PROG_AWK +AC_CHECK_PROG(SORT,sort,sort) + +AC_CHECK_HEADERS([wordexp.h]) + +# use the 64-bit versions +AC_SYS_LARGEFILE + +# asan is somewhat similar to valgrind, but has low enough overhead so it +# can be used during normal operation. +AC_ARG_ENABLE([asan],[AS_HELP_STRING([--enable-asan], + [Enable Address Sanitizer])], [use_asan=$enableval], [use_asan=no]) +AS_IF([test "x$use_asan" = "xyes"],[ + AC_SUBST(ASAN_CFLAGS, "-fsanitize=address -static-libasan -fno-omit-frame-pointer") + AC_SUBST(ASAN_CXXFLAGS,"-fsanitize=address -static-libasan -fno-omit-frame-pointer") + AC_SUBST(ASAN_LDFLAGS, "-fsanitize=address -static-libasan -fno-omit-frame-pointer") +]) + +# check for makeinfo +AC_CHECK_PROG(have_makeinfo,makeinfo,yes,no) +AM_CONDITIONAL(HAVE_MAKEINFO,test "x$have_makeinfo" = "xyes") + +# we need emacs for byte-compiling mu4e + +build_mu4e=no +AC_ARG_ENABLE([mu4e], + AS_HELP_STRING([--disable-mu4e],[Disable building mu4e])) +AS_IF([test "x$enable_mu4e" != "xno"], [ + AM_PATH_LISPDIR + AS_IF([test "x$lispdir" != "xno"], [ + emacs_version="$($EMACS --version | head -1)" + lispdir="${lispdir}/mu4e/" + ]) + AS_CASE([$emacs_version], + [*24.4*|*24.5*],[build_mu4e=yes], + [*25*|*26*|*27*|*28*],[build_mu4e=yes], + [AC_WARN([emacs is too old to build mu4e (need emacs >= 24.4)])]) +]) +AM_CONDITIONAL(BUILD_MU4E, test "x$build_mu4e" = "xyes") + +# we need some special tricks for filesystems that don't have d_type; +# e.g. Solaris. See mu-maildir.c. Explicitly disabling it is for +# testing purposes only +AC_ARG_ENABLE([dirent-d-type], + AC_HELP_STRING([--disable-dirent-d-type], + [Don't use dirent->d_type, even if you have it]), + [], [AC_STRUCT_DIRENT_D_TYPE] +) +AS_IF([test "x$ac_cv_member_struct_dirent_d_type" != "xyes"], + [use_dirent_d_type="no"], [use_dirent_d_type="yes"]) + +# support for d_ino (inode) in struct dirent is optional; if it's +# available we can sort direntries by inode and access them in that +# order; this is much faster on some file systems (such as extfs3). +# Explicitly disabling it is for testing purposes only. +AC_ARG_ENABLE([dirent-d-ino], + AC_HELP_STRING([--disable-dirent-d-ino], + [Don't use dirent->d_ino, even if you have it]), + [], [AC_STRUCT_DIRENT_D_INO] +) +AS_IF([test "x$ac_cv_member_struct_dirent_d_ino" != "xyes"], + [use_dirent_d_ino="no"], [use_dirent_d_ino="yes"]) + +AC_CHECK_FUNCS([memset memcpy realpath setlocale strerror getpass setsid]) +AC_CHECK_FUNCS([vasprintf strptime]) +AC_CHECK_FUNC(timegm,[],AC_MSG_ERROR([missing required function timegm])) + +# require pkg-config >= 0.28 (release in 2013; should be old enough...) +# with that version, we don't need the AC_SUBST stuff after PKG_CHECK. +m4_ifndef([PKG_PROG_PKG_CONFIG], + [m4_fatal([please install pkg-config >= 0.28 before running autoconf/autogen])]) +PKG_PROG_PKG_CONFIG(0.28) # latest version in buildroot +AS_IF([test -z "$PKG_CONFIG"], + AC_MSG_ERROR([ + *** pkg-config with version >= 0.28 could not be found. + *** + *** Make sure it is in your path, or set the PKG_CONFIG environment variable + *** to the full path to pkg-config.]) +) + +# glib2? +PKG_CHECK_MODULES(GLIB,glib-2.0 >= 2.38 gobject-2.0 gio-2.0) +glib_version="$($PKG_CONFIG --modversion glib-2.0)" + +# gmime, version 3.0 or higher +PKG_CHECK_MODULES(GMIME,gmime-3.0) +gmime_version="$($PKG_CONFIG --modversion gmime-3.0)" + +# gmime, version 3.0 or higher +PKG_CHECK_MODULES(JSON_GLIB,json-glib-1.0 >= 1.4,[have_json_glib=yes],[have_json_glib=no]) +AS_IF([test "x$have_json_glib" = "xyes"],[ + json_glib_version="$($PKG_CONFIG --modversion json-glib-1.0)" + AC_DEFINE(HAVE_JSON_GLIB,[1], [Do we support json-glib?]) +]) +AM_CONDITIONAL(HAVE_JSON_GLIB,[test "x$have_json_glib" = "xyes"]) + +# xapian checking - we need 1.4 at least +PKG_CHECK_MODULES(XAPIAN,xapian-core >= 1.4,[ + have_xapian=yes + xapian_version=$($PKG_CONFIG xapian-core --modversion) + AC_SUBST(XAPIAN_CXXFLAGS,${XAPIAN_CFLAGS}) +],[ + # fall back to the xapian-config script. Not sure if there are cases where the + # pkgconfig does not work, but xapian-config does, so keep this for now. + AC_MSG_NOTICE([falling back to xapian-config]) + AC_CHECK_PROG(XAPIAN_CONFIG,xapian-config,xapian-config,no) + AS_IF([test "x$XAPIAN_CONFIG" = "xno"],[ + AC_MSG_ERROR([ + *** xapian could not be found; please install it + *** e.g., in debian/ubuntu the package would be 'libxapian-dev' + *** If you compiled it yourself, you should ensure that xapian-config + *** is in your PATH.])], + [xapian_version=$($XAPIAN_CONFIG --version | sed -e 's/.* //')]) + + AS_CASE([$xapian_version], + [1.[[4-9]].[[0-9]]*], + [AC_MSG_NOTICE([xapian $xapian_version found.])], + [AC_MSG_ERROR([*** xapian version >= 1.4 needed, but version $xapian_version found.])]) + + XAPIAN_CXXFLAGS="$($XAPIAN_CONFIG --cxxflags)" + XAPIAN_LIBS="$($XAPIAN_CONFIG --libs)" + have_xapian="yes" + + AC_SUBST(XAPIAN_CXXFLAGS) + AC_SUBST(XAPIAN_LIBS) +]) +############################################################################### +# we set the set the version of the MuStore (Xapian database) layout +# here; it will become part of the db name, so we can automatically +# recreate the database when we have incompatible changes. +# +# note that MU_STORE_SCHEMA_VERSION does not follow mu versioning, as we +# hopefully don't have updates for each version; also, this has nothing to do +# with Xapian's software version +AC_DEFINE(MU_STORE_SCHEMA_VERSION,["451"],['Schema' version of the database]) +############################################################################### + +############################################################################### +# we need GTK+3 for some of the graphical tools +# use --without-gtk to disable it +AC_ARG_ENABLE([gtk],AS_HELP_STRING([--disable-gtk],[Disable GTK+])) +AS_IF([test "x$enable_gtk" != "xno"],[ + PKG_CHECK_MODULES(GTK,gtk+-3.0,[have_gtk=yes],[have_gtk=no]) + gtk_version="$($PKG_CONFIG --modversion gtk+-3.0)" +]) +AM_CONDITIONAL(HAVE_GTK,[test "x$have_gtk" = "xyes"]) + +# webkit? needed for the fancy web widget +# use --disable-webkit to disable it, even if you have it +# +# and note this is just a toy, not for distribution. +AC_ARG_ENABLE([webkit],AS_HELP_STRING([--disable-webkit],[Disable webkit])) +AS_IF([test "x$enable_webkit" != "xno"],[ + PKG_CHECK_MODULES(WEBKIT,webkit2gtk-4.0 >= 2.0, [have_webkit=yes],[have_webkit=no]) + AS_IF([test "x$have_webkit" = "xyes"],[ + webkit_version="$($PKG_CONFIG --modversion webkit2gtk-4.0)"]) +]) +AM_CONDITIONAL(HAVE_WEBKIT, [test "x$have_webkit" = "xyes"]) +AM_CONDITIONAL(BUILD_GUI,[test "x$have_webkit" = "xyes" -a "x$have_gtk" = "xyes"]) +############################################################################### + +############################################################################### +# build with guile2.2 when available and not disabled. +AC_ARG_ENABLE([guile], AS_HELP_STRING([--disable-guile],[Disable guile])) +AS_IF([test "x$enable_guile" != "xno"],[ + PKG_CHECK_MODULES(GUILE22, guile-2.2, [have_guile22=yes],[have_guile22=no]) + # this is a bit hacky; GUILE_PKG + AS_IF([test "x$have_guile22" = "xyes"],[ + GUILE_PKG([2.2]) + GUILE_PROGS + GUILE_FLAGS + AC_DEFINE_UNQUOTED([GUILE_BINARY],"$GUILE",[guile binary]) + AC_DEFINE(BUILD_GUILE,[1], [Do we support Guile?]) + AC_SUBST(GUILE_SNARF, [guile-snarf]) + guile_version=$($PKG_CONFIG guile-2.2 --modversion) + ]) +]) +AM_CONDITIONAL(BUILD_GUILE,[test "x$have_guile22" = "xyes"]) +############################################################################### + +############################################################################### +# optional readline +saved_libs=$LIBS +AX_LIB_READLINE +AC_SUBST(READLINE_LIBS,${LIBS}) +LIBS=$saved_libs +############################################################################### + +############################################################################### +# check for makeinfo +AC_CHECK_PROG(have_makeinfo,makeinfo,yes,no) +AM_CONDITIONAL(HAVE_MAKEINFO, [test "x$have_makeinfo" = "xyes"]) +############################################################################### + +############################################################################### +# docdir, so we can use it in mu4e-meta.el.in +AC_SUBST(MU_DOC_DIR, "${prefix}/share/doc/mu") +############################################################################### + +AC_CONFIG_FILES([ +Makefile +mu/Makefile +mu/mu-memcheck +lib/Makefile +lib/doxyfile +lib/utils/Makefile +lib/query/Makefile +mu4e/Makefile +mu4e/mu4e-meta.el +guile/Makefile +guile/texi.texi +guile/mu/Makefile +guile/examples/Makefile +guile/tests/Makefile +guile/scripts/Makefile +toys/Makefile +toys/mug/Makefile +man/Makefile +m4/Makefile +contrib/Makefile +],[ + [chmod +x mu/mu-memcheck] +]) +AC_OUTPUT + +dnl toys/msg2pdf/Makefile + +echo +echo "mu configuration is complete." +echo "------------------------------------------------" + +echo "mu version : $VERSION" +echo +echo "Xapian version : $xapian_version" +echo "GLib version : $glib_version" +echo "GMime version : $gmime_version" + +AM_COND_IF([HAVE_JSON_GLIB],[ +echo "Json-Glib version : $json_glib_version" +]) + +AM_COND_IF([BUILD_GUI],[ +echo "GTK+ version : $gtk_version" +echo "Webkit2/GTK+ version : $webkit_version" +]) + +AM_COND_IF([BUILD_GUILE],[ +echo "Guile version : $guile_version" +]) + +if test "x$build_mu4e" = "xyes"; then +echo "Emacs version : $emacs_version" +fi + +echo +echo "Have wordexp : $ac_cv_header_wordexp_h" +echo "Build mu4e emacs frontend : $build_mu4e" + +AM_COND_IF([BUILD_GUI],[ +echo "Build 'mug' toy-ui (gtk+/webkit) : yes"],[ +echo "Build 'mug' toy-ui (gtk+/webkit) : no" +]) + +echo + +echo "Have direntry->d_ino : $use_dirent_d_ino" +echo "Have direntry->d_type : $use_dirent_d_type" +echo "------------------------------------------------" +echo + +# +# Warnings / notes +# + +# makeinfo +if test "x$have_makeinfo" != "xyes"; then + echo "* You do not seem to have the makeinfo program; if you are building from git" + echo " you need that to create documentation for guile and emacs. It is in the" + echo " texinfo package in debian/ubuntu/fedora/... " + echo +fi + +# gui +AS_IF([test "x$buildgui" = "xyes"],[ + echo "* The demo UI will be built in toys/mug" + echo +]) + +# wordexp +AS_IF([test "x$ac_cv_header_wordexp_h" != "xyes"],[ + echo "* Your system does not seem to have the 'wordexp' function." + echo " This means that you cannot use shell-like expansion in options and " + echo " some other places. So, for example, instead of" + echo " --maildir=~/Maildir" + echo " you should use the complete path, something like:" + echo " --maildir=/home/user/Maildir" +]) + +echo +echo "Now, type 'make' (or 'gmake') to build mu" +echo diff --git a/contrib/Makefile.am b/contrib/Makefile.am new file mode 100644 index 0000000..faaf7cc --- /dev/null +++ b/contrib/Makefile.am @@ -0,0 +1,31 @@ +## Copyright (C) 2008-2013 Dirk-Jan C. Binnema +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +AM_CPPFLAGS=$(GMIME_CFLAGS) $(GLIB_CFLAGS) -I${prefix}/include +AM_CFLAGS=-Wall -Wextra -Wno-unused-parameter -Wdeclaration-after-statement -pedantic + +noinst_PROGRAMS=gmime-test +gmime_test_SOURCES=gmime-test.c +gmime_test_LDADD=$(GMIME_LIBS) $(GLIB_LIBS) + + +EXTRA_DIST= \ + mu-completion.zsh \ + mu-sexp-convert \ + mu.spec + diff --git a/contrib/gmime-test.c b/contrib/gmime-test.c new file mode 100644 index 0000000..5c59ed2 --- /dev/null +++ b/contrib/gmime-test.c @@ -0,0 +1,275 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2011-2017 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +/* gmime-test; compile with: + gcc -o gmime-test gmime-test.c -Wall -O0 -ggdb \ + `pkg-config --cflags --libs gmime-2.6` + */ + +#include +#include +#include +#include +#include + +static gchar* +get_recip (GMimeMessage *msg, GMimeAddressType atype) +{ + char *recep; + InternetAddressList *receps; + + receps = g_mime_message_get_addresses (msg, atype); + recep = (char*)internet_address_list_to_string (receps, NULL, FALSE); + + if (!recep || !*recep) { + g_free (recep); + return NULL; + } + + return recep; +} + +static gchar* +get_refs_str (GMimeMessage *msg) +{ + const gchar *str; + GMimeReferences *mime_refs; + int i, refs_len; + gchar *rv; + + str = g_mime_object_get_header (GMIME_OBJECT(msg), "References"); + if (!str) + return NULL; + + mime_refs = g_mime_references_parse (NULL, str); + refs_len = g_mime_references_length (mime_refs); + for (rv = NULL, i = 0; i < refs_len; ++i) { + const char* msgid; + msgid = g_mime_references_get_message_id (mime_refs, i); + rv = g_strdup_printf ("%s%s%s", + rv ? rv : "", + rv ? "," : "", + msgid); + } + g_mime_references_free (mime_refs); + + return rv; +} + +static void +print_date (GMimeMessage *msg) +{ + GDateTime *dt; + gchar *buf; + + dt = g_mime_message_get_date (msg); + if (!dt) + return; + + dt = g_date_time_to_local (dt); + buf = g_date_time_format (dt, "%c"); + g_date_time_unref (dt); + + if (buf) { + g_print ("Date : %s\n", buf); + g_free (buf); + } +} + + +static void +print_body (GMimeMessage *msg) +{ + GMimeObject *body; + GMimeDataWrapper *wrapper; + GMimeStream *stream; + + body = g_mime_message_get_body (msg); + + if (GMIME_IS_MULTIPART(body)) + body = g_mime_multipart_get_part (GMIME_MULTIPART(body), 0); + + if (!GMIME_IS_PART(body)) + return; + + wrapper = g_mime_part_get_content (GMIME_PART(body)); + if (!GMIME_IS_DATA_WRAPPER(wrapper)) + return; + + stream = g_mime_data_wrapper_get_stream (wrapper); + if (!GMIME_IS_STREAM(stream)) + return; + + do { + char buf[512]; + ssize_t len; + + len = g_mime_stream_read (stream, buf, sizeof(buf)); + if (len == -1) + break; + + if (write (fileno(stdout), buf, len) == -1) + break; + + if (len < (int)sizeof(buf)) + break; + + } while (1); +} + +static gboolean +test_message (GMimeMessage *msg) +{ + gchar *val; + const gchar *str; + + val = get_recip (msg, GMIME_ADDRESS_TYPE_FROM); + g_print ("From : %s\n", val ? val : "" ); + g_free (val); + + val = get_recip (msg, GMIME_ADDRESS_TYPE_TO); + g_print ("To : %s\n", val ? val : "" ); + g_free (val); + + val = get_recip (msg, GMIME_ADDRESS_TYPE_CC); + g_print ("Cc : %s\n", val ? val : "" ); + g_free (val); + + val = get_recip (msg, GMIME_ADDRESS_TYPE_BCC); + g_print ("Bcc : %s\n", val ? val : "" ); + g_free (val); + + str = g_mime_message_get_subject (msg); + g_print ("Subject: %s\n", str ? str : ""); + + print_date (msg); + + str = g_mime_message_get_message_id (msg); + g_print ("Msg-id : %s\n", str ? str : ""); + + { + gchar *refsstr; + refsstr = get_refs_str (msg); + g_print ("Refs : %s\n", refsstr ? refsstr : ""); + g_free (refsstr); + } + + print_body (msg); + + return TRUE; +} + + + +static gboolean +test_stream (GMimeStream *stream) +{ + GMimeParser *parser; + GMimeMessage *msg; + gboolean rv; + + parser = NULL; + msg = NULL; + + parser = g_mime_parser_new_with_stream (stream); + if (!parser) { + g_warning ("failed to create parser"); + rv = FALSE; + goto leave; + } + + msg = g_mime_parser_construct_message (parser, NULL); + if (!msg) { + g_warning ("failed to construct message"); + rv = FALSE; + goto leave; + } + + rv = test_message (msg); + +leave: + if (parser) + g_object_unref (parser); + + if (msg) + g_object_unref (msg); + + return rv; +} + + +static gboolean +test_file (const char *path) +{ + FILE *file; + GMimeStream *stream; + gboolean rv; + + stream = NULL; + file = NULL; + + file = fopen (path, "r"); + if (!file) { + g_warning ("cannot open file '%s': %s", path, + strerror(errno)); + rv = FALSE; + goto leave; + } + + stream = g_mime_stream_file_new (file); + if (!stream) { + g_warning ("cannot open stream for '%s'", path); + rv = FALSE; + goto leave; + } + + rv = test_stream (stream); + g_object_unref (stream); + return rv; + +leave: + if (file) + fclose (file); + + return rv; +} + + +int +main (int argc, char *argv[]) +{ + gboolean rv; + + if (argc != 2) { + g_printerr ("usage: %s \n", argv[0]); + return 1; + } + + setlocale (LC_ALL, ""); + + g_mime_init(); + + rv = test_file (argv[1]); + + g_mime_shutdown (); + + return rv ? 0 : 1; +} diff --git a/contrib/mu-completion.zsh b/contrib/mu-completion.zsh new file mode 100644 index 0000000..ea2bdbd --- /dev/null +++ b/contrib/mu-completion.zsh @@ -0,0 +1,124 @@ +#compdef mu + +## Copyright (C) 2011-2012 Dirk-Jan C. Binnema +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# zsh completion for mu. Install this by copying/linking to this file somewhere in +# your $fpath; the link/copy must have a name starting with an underscore "_" + +# main dispatcher function +_mu() { + if (( CURRENT > 2 )) ; then + local cmd=${words[2]} + curcontext="${curcontext%:*:*}:mu-$cmd" + (( CURRENT-- )) + shift words + _call_function ret _mu_$cmd + return ret + else + _mu_commands + fi +} + + + +_mu_commands() { + local -a mu_commands + mu_commands=( + 'index:scan your maildirs and import their metadata in the database' + 'find:search for messages in the database' + 'view:display specific messages' + 'cfind:search for contacts (name + email) in the database' + 'extract:extract message-parts (attachments) and save or open them' + 'mkdir:create maildirs' +# below are not generally very useful, so let's not auto-complete them +# 'add: add a message to the database.' +# 'remove:remove a message from the database.' +# 'server:sart the mu server' +) + + _describe -t command 'command' mu_commands +} + +_mu_common_options=( + '--debug[output information useful for debugging mu]' + '--quiet[do not give any non-critical information]' + '--nocolor[do not use colors in some of the output]' + '--version[display mu version and copyright information]' + '--log-stderr[log to standard error]' +) + +_mu_db_options=( + '--muhome[use some non-default location for the mu database]:directory:_files' +) + +_mu_find_options=( + '--fields[fields to display in the output]' + '--sortfield[field to sort the output by]' + '--descending[sort in descending order]' + '--summary[include a summary of the message]' + '--summary-len[number of lines to use for the summary]' + '--bookmark[use a named bookmark]' + '--output[set the kind of output for the query]' +) + +_mu_view_options=( + '--summary[only show a summary of the message]' + '--summary-len[number of lines to use for the summary]' +) + + +_mu_view() { + _arguments -s : \ + $_mu_common_options \ + $_mu_view_options +} + +_mu_extract() { + _files +} + +_mu_find() { + _arguments -s : \ + $_mu_common_options \ + $_mu_db_options \ + $_mu_find_options +} + +_mu_index() { + _arguments -s : \ + $_mu_db_options \ + $_mu_common_options +}mu + +_mu_cleanup() { + _arguments -s : \ + $_mu_db_options \ + $_mu_common_options +} + + +_mu_mkdir() { + _arguments -s : \ + '--mode=[file mode for the new Maildir]:file mode: ' \ + $_mu_common_options +} + +_mu "$@" + +# Local variables: +# mode: sh +# End: diff --git a/contrib/mu-sexp-convert b/contrib/mu-sexp-convert new file mode 100755 index 0000000..b2835ac --- /dev/null +++ b/contrib/mu-sexp-convert @@ -0,0 +1,204 @@ +#!/bin/sh +exec guile -e main -s $0 $@ +!# + +;; Copyright (C) 2012 Dirk-Jan C. Binnema +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +;; +;; a little hack to convert the output of +;; mu find --format=sexp +;; and +;; mu view --format=sexp +;; into XML or JSON + +(use-modules (ice-9 getopt-long) (ice-9 format) (ice-9 regex)) +(use-modules (sxml simple)) + +(define (mapconcat func lst sepa) + "Apply FUNC to elements of LST, concat the result as strings +separated by SEPA." + (if (null? lst) + "" + (string-append + (func (car lst)) + (if (null? (cdr lst)) + "" + (string-append sepa (mapconcat func (cdr lst) sepa)))))) + +(define (property-list? obj) + "Is OBJ a elisp-style property list (ie. a list of the +form (:symbol1 something :symbol2 somethingelse), as in an elisp +proplilst." + (and (list? obj) + (not (null? obj)) + (symbol? (car obj)) + (string= ":" (substring (symbol->string (car obj)) 0 1)))) + +(define (plist->pairs plist) + "Convert an elisp-style property list; e.g: + (:prop1 foo :prop2: bar ...) +into a list of pairs + ((prop1 . foo) (prop2 . bar) ...)." + (if (null? plist) + '() + (cons + (cons + (substring (symbol->string (car plist)) 1) + (cadr plist)) + (plist->pairs (cddr plist))))) + +(define (string->xml str) + "XML-encode STR." + ;; sneakily re-using sxml->xml + (call-with-output-string (lambda (port) (sxml->xml str port)))) + +(define (string->json str) + "Convert string into a JSON-encoded string." + (letrec ((convert + (lambda (lst) + (if (null? lst) + "" + (string-append + (cond + ((equal? (car lst) #\") "\\\"") + ((equal? (car lst) #\\) "\\\\") + ((equal? (car lst) #\/) "\\/") + ((equal? (car lst) #\bs) "\\b") + ((equal? (car lst) #\ff) "\\f") + ((equal? (car lst) #\lf) "\\n") + ((equal? (car lst) #\cr) "\\r") + ((equal? (car lst) #\ht) "\\t") + (#t (string (car lst)))) + (convert (cdr lst))))))) + (convert (string->list str)))) + +(define (etime->time_t t) + "Convert elisp time object T into a time_t value." + (logior (ash (car t) 16) (car (cdr t)))) + +(define (sexp->xml) + "Convert string INPUT to XML, return the XML (string)." + (letrec ((convert-xml + (lambda* (expr #:optional parent) + (cond + ((property-list? expr) + (mapconcat + (lambda (pair) + (format #f "\t<~a>~a\n" + (car pair) (convert-xml (cdr pair) (car pair)) (car pair))) + (plist->pairs expr) " ")) + ((list? expr) + (cond + ((member parent '("from" "to" "cc" "bcc")) + (mapconcat (lambda (addr) + (format #f "
~a~a
" + (if (string? (car addr)) + (format #f "~a" + (string->xml (car addr))) "") + (if (string? (cdr addr)) + (format #f "~a" + (string->xml (cdr addr))) ""))) + expr " ")) + ((string= parent "parts") "") ;; for now, ignore + ;; convert the crazy emacs time thingy to time_t... + ((string= parent "date") (format #f "~a" (etime->time_t expr))) + (#t + (mapconcat + (lambda (elm) (format #f "~a" (convert-xml elm))) expr "")))) + ((string? expr) (string->xml expr)) + ((symbol? expr) (format #f "~a" expr)) + ((number? expr) (number->string expr)) + (#t ".")))) + (msg->xml + (lambda () + (let ((expr (read))) + (if (not (eof-object? expr)) + (string-append (format #f "\n~a\n" (convert-xml expr)) (msg->xml)) + ""))))) + (format #f "\n\n~a" (msg->xml)))) + + +(define (sexp->json) + "Convert string INPUT to JSON, return the JSON (string)." + (letrec ((convert-json + (lambda* (expr #:optional parent) + (cond + ((property-list? expr) + (mapconcat + (lambda (pair) + (format #f "\n\t\"~a\": ~a" + (car pair) (convert-json (cdr pair) (car pair)))) + (plist->pairs expr) ", ")) + ((list? expr) + (cond + ((member parent '("from" "to" "cc" "bcc")) + (string-append "[" + (mapconcat (lambda (addr) + (format #f "{~a~a}" + (if (string? (car addr)) + (format #f "\"name\": \"~a\"," + (string->json (car addr))) "") + (if (string? (cdr addr)) + (format #f "\"email\": \"~a\"" + (string->json (cdr addr))) ""))) + expr ", ") + "]")) + ((string= parent "parts") "[]") ;; todo + ;; convert the crazy emacs time thingy to time_t... + ((string= parent "date") + (format #f "~a" (format #f "~a" (etime->time_t expr)))) + (#t + (string-append "[" + (mapconcat (lambda (elm) (format #f "~a" (convert-json elm))) expr ",") "]")))) + ((string? expr) + (format #f "\"~a\"" (string->json expr))) + ((symbol? expr) + (format #f "\"~a\"" expr)) + ((number? expr) (number->string expr)) + (#t ".")))) + (msg->json + (lambda (first) + (let ((expr (read))) + (if (not (eof-object? expr)) + (string-append (format #f "~a{~a\n}" + (if first "" ",\n") + (convert-json expr)) (msg->json #f)) + ""))))) + (format #f "[\n~a\n]" (msg->json #t)))) + +(define (main args) + (let* ((optionspec '((format (value #t)))) + (options (getopt-long args optionspec)) + (msg (string-append + "usage: mu-sexp-convert " + "--format=\n" + "reads from standard-input and prints to standard output\n")) + (outformat (or (option-ref options 'format #f) + (begin (display msg) (exit 1))))) + (cond + ((string= outformat "xml") + (format #t "~a\n" (sexp->xml))) + ((string= outformat "json") + (format #t "~a\n" (sexp->json))) + (#t (begin + (display msg) + (exit 1)))))) + +;; Local Variables: +;; mode: scheme +;; End: diff --git a/contrib/mu.spec b/contrib/mu.spec new file mode 100644 index 0000000..1ed66d4 --- /dev/null +++ b/contrib/mu.spec @@ -0,0 +1,129 @@ + +# These refer to the release version +# When 0.9.9.6 gets out, remove the global pre line +%global pre pre2 +%global rel 1 + +Summary: A lightweight email search engine for Maildirs +Name: mu +Version: 0.9.9.6 +URL: https://github.com/djcb/mu +# From Packaging:NamingGuidelines for pre-relase versions: +# Release: 0.%{X}.%{alphatag} where %{X} is the release number +%if %{pre} +Release: 0.%{rel}.%{prerelease}%{?dist} +%else +Release: %{rel}%{?dist} +%endif + +License: GPLv3 +Group: Applications/Internet +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +# Source is at ssaavedra repo because djcb has not yet this version tag created +Source0: http://github.com/ssaavedra/%{name}/archive/v%{version}%{?pre}.tar.gz +BuildRequires: emacs-el +BuildRequires: emacs +BuildRequires: gmime-devel +BuildRequires: guile-devel +BuildRequires: xapian-core-devel +BuildRequires: libuuid-devel +BuildRequires: texinfo +Requires: gmime +Requires: guile +Requires: xapian-core-libs +Requires: emacs-filesystem >= %{_emacs_version} + + +%description +E-mail is the 'flow' in the work flow of many people. Consequently, one spends a lot of time searching for old e-mails, to dig up some important piece of information. With people having tens of thousands of e-mails (or more), this is becoming harder and harder. How to find that one e-mail in an ever-growing haystack? +Enter mu. +'mu' is a set of command-line tools for Linux/Unix that enable you to quickly find the e-mails you are looking for, assuming that you store your e-mails in Maildirs (if you don't know what 'Maildirs' are, you are probably not using them). + +%package gtk +Group: Applications/Internet +Summary: GUI for using mu (called mug) +BuildRequires: gtk3-devel +BuildRequires: webkitgtk3-devel +Requires: gtk3 +Requires: gmime +Requires: webkitgtk3 +Requires: mu = %{version}-%{release} + +%description gtk +Mug is a simple GUI for mu from version 0.9. + +%package guile +Group: Applications/Internet +Summary: Guile scripting capabilities for mu +Requires: guile +Requires: mu = %{version}-%{release} +Requires(post): info +Requires(preun): info + +%description guile +Bindings for Guile to interact with mu. + + +%prep +%setup -n %{name}-%{version}%{?pre} -q + +%build +autoreconf -i +%configure +make %{?_smp_mflags} + +%install +rm -rf %{buildroot} +make install DESTDIR=%{buildroot} +install -p -c -m 755 %{_builddir}/%{buildsubdir}/toys/mug/mug %{buildroot}%{_bindir}/mug +cp -p %{_builddir}/%{buildsubdir}/mu4e/*.el %{buildroot}%{_emacs_sitelispdir}/mu4e/ +rm -f %{buildroot}%{_infodir}/dir + +%clean +rm -rf %{buildroot} + +%post +/sbin/install-info \ + --info-dir=%{_infodir} %{_infodir}/mu4e.info.gz || : +%preun +if [ $1 = 0 -a -f %{_infodir}/mu4e.info.gz ]; then + /sbin/install-info --delete \ + --info-dir=%{_infodir} %{_infodir}/mu4e.info.gz || : +fi + +%post guile +/sbin/install-info \ + --info-dir=%{_infodir} %{_infodir}/mu-guile.info.gz || : + +%preun guile +if [ $1 = 0 -a -f %{_infodir}/mu-guile.info.gz ]; then + /sbin/install-info --delete \ + --info-dir=%{_infodir} %{_infodir}/mu-guile.info.gz || : +fi + + +%files +%defattr(-,root,root) +%{_bindir}/mu +%{_mandir}/man1/* +%{_mandir}/man5/* +%{_datadir}/mu/* + +%{_emacs_sitelispdir}/mu4e +%{_emacs_sitelispdir}/mu4e/*.elc +%{_emacs_sitelispdir}/mu4e/*.el +%{_infodir}/mu4e.info.gz + +%files gtk +%{_bindir}/mug + +%files guile +%{_libdir}/libguile-mu.* +%{_datadir}/guile/site/2.0/mu/* +%{_datadir}/guile/site/2.0/mu.scm +%{_infodir}/mu-guile.info.gz + +%changelog +* Wed Feb 12 2014 Santiago Saavedra - 0.9.9.5-1 +- Create first SPEC. diff --git a/gtest.mk b/gtest.mk new file mode 100644 index 0000000..159576e --- /dev/null +++ b/gtest.mk @@ -0,0 +1,34 @@ +## Copyright (C) 2011 Dirk-Jan C. Binnema +## +## 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 3, or (at your option) any +## later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +TEST_PROGS= + + +# NOTE: we set the locale/tz to some well-know values, so the tests +# (at least when running under 'make check') run in a predictable +# environment. There are specific tests different timezone, though. +# +test: all $(TEST_PROGS) + @export LC_ALL="en_US.utf8" + @export TZ="Europe/Helsinki" + @test -z "$(TEST_PROGS)" || gtester --verbose $(TEST_PROGS) || exit $$?; \ + test -z "$(SUBDIRS)" || \ + for subdir in $(SUBDIRS); do \ + test "$$subdir" = "." || \ + (cd ./$$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $$? ; \ + done + +.PHONY: test gprof diff --git a/guile/Makefile.am b/guile/Makefile.am new file mode 100644 index 0000000..319b079 --- /dev/null +++ b/guile/Makefile.am @@ -0,0 +1,79 @@ +## Copyright (C) 2011-2013 Dirk-Jan C. Binnema +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +# note, we need top_builddir for snarfing with 'make distcheck' (ie., +# with separate builddir) +SUBDIRS= . mu scripts examples tests + +AM_CPPFLAGS= \ + -I. -I${top_builddir} -I${top_srcdir}/lib \ + ${GUILE_CFLAGS} \ + ${GLIB_CFLAGS} + +# don't use -Werror, as it might break on other compilers +# use -Wno-unused-parameters, because some callbacks may not +# really need all the params they get +AM_CFLAGS=$(ASAN_CFLAGS) ${WARN_CFLAGS} +AM_CXXFLAGS=$(ASAN_CXXFLAGS) ${WARN_CXXFLAGS} + +lib_LTLIBRARIES= \ + libguile-mu.la + +libguile_mu_la_SOURCES= \ + mu-guile.c \ + mu-guile.h \ + mu-guile-message.c \ + mu-guile-message.h + +libguile_mu_la_LIBADD= \ + ${top_builddir}/lib/libmu.la \ + ${GUILE_LIBS} + +libguile_mu_la_LDFLAGS= \ + $(ASAN_LDFLAGS) \ + -shared \ + -export-dynamic \ + -Wl,-z,muldefs + +XFILES= \ + mu-guile.x \ + mu-guile-message.x + +info_TEXINFOS= \ + mu-guile.texi +mu_guile_TEXINFOS= \ + fdl.texi + +BUILT_SOURCES=$(XFILES) + +snarfcppopts= $(DEFS) $(AM_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) $(AM_CPPFLAGS) +SUFFIXES = .x .doc +.c.x: + $(GUILE_SNARF) -o $@ $< $(snarfcppopts) + +# FIXME: GUILE_SITEDIR would be better, but that +# breaks 'make distcheck' +scmdir=${prefix}/share/guile/site/2.2/ +scm_DATA=mu.scm + +EXTRA_DIST=$(scm_DATA) + +## Add -MG to make the .x magic work with auto-dep code. +MKDEP = $(CC) -M -MG $(snarfcppopts) + +CLEANFILES=$(XFILES) diff --git a/guile/examples/Makefile.am b/guile/examples/Makefile.am new file mode 100644 index 0000000..7e126c5 --- /dev/null +++ b/guile/examples/Makefile.am @@ -0,0 +1,23 @@ +## Copyright (C) 2012-2013 Dirk-Jan C. Binnema +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +EXTRA_DIST= \ + msg-graphs \ + contacts-export \ + org2mu4e \ + mu-biff diff --git a/guile/examples/contacts-export b/guile/examples/contacts-export new file mode 100755 index 0000000..7e33c54 --- /dev/null +++ b/guile/examples/contacts-export @@ -0,0 +1,85 @@ +#!/bin/sh +exec guile -e main -s $0 $@ +!# + +;; +;; Copyright (C) 2012 Dirk-Jan C. Binnema +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +(use-modules (ice-9 getopt-long) (ice-9 format)) +(use-modules (srfi srfi-1)) +(use-modules (mu)) + +(define (sort-by-freq c1 c2) + (< (mu:frequency c1) (mu:frequency c2))) + +(define (sort-by-newness c1 c2) + (< (mu:last-seen c1) (mu:last-seen c2))) + +(define (main args) + (let* ((optionspec '( (muhome (value #t)) + (sort-by (value #t)) + (revert (value #f)) + (format (value #t)) + (limit (value #t)) + (help (single-char #\h) (value #f)))) + (options (getopt-long args optionspec)) + (msg (string-append + "usage: contacts-export [--help] [--muhome=] " + "--format= " + "--sort-by= [--revert] [--limit=]\n")) + (help (option-ref options 'help #f)) + (muhome (option-ref options 'muhome #f)) + (sort-by (or (option-ref options 'sort-by #f) "frequency")) + (revert (option-ref options 'revert #f)) + (form (or (option-ref options 'format #f) "plain")) + (limit (string->number (option-ref options 'limit "1000000")))) + (if help + (begin + (display msg) + (exit 0)) + (begin + (setlocale LC_ALL "") + (mu:initialize muhome) + (let* ((sort-func + (cond + ((string= sort-by "frequency") sort-by-freq) + ((string= sort-by "newness") sort-by-newness) + (else (begin (display msg) (exit 1))))) + (contacts '())) + ;; make a list of all contacts + (mu:for-each-contact + (lambda (c) (set! contacts (cons c contacts)))) + + ;; should we sort it? + (if sort-by + (set! contacts (sort! contacts + (if revert (negate sort-func) sort-func)))) + + ;; should we limit the number? + (if (and limit (< limit (length contacts))) + (set! contacts (take! contacts limit))) + ;; export! + (for-each + (lambda (c) + (format #t "~a\n" (mu:contact->string c form))) + contacts)))))) + +;; Local Variables: +;; mode: scheme +;; End: diff --git a/guile/examples/msg-graphs b/guile/examples/msg-graphs new file mode 100755 index 0000000..654dd28 --- /dev/null +++ b/guile/examples/msg-graphs @@ -0,0 +1,133 @@ +#!/bin/sh +exec guile -e main -s $0 $@ +!# +;; +;; Copyright (C) 2011-2012 Dirk-Jan C. Binnema +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +(setlocale LC_ALL "") + +(use-modules (ice-9 getopt-long) (ice-9 optargs) (ice-9 popen) (ice-9 format)) +(use-modules (mu) (mu stats) (mu plot)) +;;(use-modules (mu) (mu message) (mu stats) (mu plot)) + +(define (per-hour expr output) + "Count the total number of messages for each weekday (0-6 for Sun..Sat) that +match EXPR. OUTPUT corresponds to the output format, as per gnuplot's 'set +terminal'." + (mu:plot + (sort + (mu:tabulate + (lambda (msg) + (tm:hour (localtime (mu:date msg)))) expr) + (lambda (x y) (< (car x) (car y)))) + (format #f "Messages per hour matching ~a" expr) "Hour" "Messages" output)) + +(define (per-day expr output) + "Count the total number of messages for each weekday (0-6 for Sun..Sat) that +match EXPR. OUTPUT corresponds to the output format, as per gnuplot's 'set +terminal'." + (mu:plot + (mu:weekday-numbers->names + (sort (mu:tabulate + (lambda (msg) + (tm:wday (localtime (mu:date msg)))) expr) + (lambda (x y) (< (car x) (car y))))) + (format #f "Messages per weekday matching ~a" expr) "Day" "Messages" output)) + +(define (per-month expr output) + "Count the total number of messages for each weekday (0-6 for Sun..Sat) that +match EXPR. OUTPUT corresponds to the output format, as per gnuplot's 'set +terminal'." + (mu:plot + (mu:month-numbers->names + (sort + (mu:tabulate + (lambda (msg) + (tm:mon (localtime (mu:date msg)))) expr) + (lambda (x y) (< (car x) (car y))))) + (format #f "Messages per month matching ~a" expr) "Month" "Messages" output)) + + +(define (per-year-month expr output) + "Count the total number of messages for each weekday (0-6 for Sun..Sat) that +match EXPR. OUTPUT corresponds to the output format, as per gnuplot's 'set +terminal'." + (mu:plot + (sort (mu:tabulate + (lambda (msg) + (string->number + (format #f "~d~2'0d" + (+ 1900 (tm:year (localtime (mu:date msg)))) + (tm:mon (localtime (mu:date msg)))))) + expr) + (lambda (x y) (< (car x) (car y)))) + (format #f "Messages per year/month matching ~a" expr) + "Year/Month" "Messages" output)) + + + +(define (per-year expr output) + "Count the total number of messages for each weekday (0-6 for Sun..Sat) that +match EXPR. OUTPUT corresponds to the output format, as per gnuplot's 'set +terminal'." + (mu:plot + (sort (mu:tabulate + (lambda (msg) + (+ 1900 (tm:year (localtime (mu:date msg))))) expr) + (lambda (x y) (< (car x) (car y)))) + (format #f "Messages per year matching ~a" expr) "Year" "Messages" output)) + + + +(define (main args) + (let* ((optionspec '( (muhome (value #t)) + (what (value #t)) + (text (value #f)) + (help (single-char #\h) (value #f)))) + (options (getopt-long args optionspec)) + (msg (string-append + "usage: mu-msg-stats [--help] [--text] " + "[--muhome=] " + "--what= [searchexpr]\n")) + (help (option-ref options 'help #f)) + (what (option-ref options 'what #f)) + (text (option-ref options 'text #f)) + ;; if `text' is `#f', use a graphical window by setting output to "wxt", + ;; else use text-mode plotting ("dumb") + (output (if text "dumb" "wxt")) + (muhome (option-ref options 'muhome #f)) + (restargs (option-ref options '() #f)) + (expr (if restargs (string-join restargs) ""))) + (if (or help (not what)) + (begin + (display msg) + (exit (if help 0 1)))) + (mu:initialize muhome) + (cond + ((string= what "per-hour") (per-hour expr output)) + ((string= what "per-day") (per-day expr output)) + ((string= what "per-month") (per-month expr output)) + ((string= what "per-year-month") (per-year-month expr output)) + ((string= what "per-year") (per-year expr output)) + (else (begin + (display msg) + (exit 1)))))) + +;; Local Variables: +;; mode: scheme +;; End: diff --git a/guile/examples/mu-biff b/guile/examples/mu-biff new file mode 100755 index 0000000..bc6d507 --- /dev/null +++ b/guile/examples/mu-biff @@ -0,0 +1,59 @@ +#!/bin/sh +exec guile -e main -s $0 $@ +!# + +;; +;; Copyright (C) 2012 Dirk-Jan C. Binnema +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +;; script to list the message matching which are newer than +;; minutes + +;; use it, eg. like: +;; $ mu-biff --newer-than=`date +%s --date='5 minutes ago'` "maildir:/inbox" + + +(use-modules (ice-9 getopt-long) (ice-9 format)) +(use-modules (mu)) + +(define (main args) + (let* ((optionspec '((muhome (value #t)) + (newer-than (value #t)) + (help (single-char #\h) (value #f)))) + (options (getopt-long args optionspec)) + (msg (string-append + "usage: mu-biff [--help] [--muhome=]" + " [--newer-than=] ")) + (help (option-ref options 'help #f)) + (newer-than (string->number (option-ref options 'newer-than "0"))) + (muhome (option-ref options 'muhome #f)) + (query (string-concatenate (option-ref options '() '())))) + (if help + (begin (display msg) (newline) (exit 0)) + (begin + (mu:initialize muhome) + (mu:for-each-message + (lambda (msg) + (if (> (mu:timestamp msg) newer-than) + (format #t "~a ~a\n" + (mu:from msg) + (mu:subject msg)))) + query))))) + +;; Local Variables: +;; mode: scheme +;; End: diff --git a/guile/examples/org2mu4e b/guile/examples/org2mu4e new file mode 100755 index 0000000..3556b9a --- /dev/null +++ b/guile/examples/org2mu4e @@ -0,0 +1,78 @@ +#!/bin/sh +exec guile -e main -s $0 $@ +!# + +;; +;; Copyright (C) 2011-2012 Dirk-Jan C. Binnema +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +(use-modules (ice-9 getopt-long) (ice-9 format)) +(use-modules (mu)) + +(define (display-org-header query) + "Print the header for the org-file for QUERY." + (format #t "* Messages matching '~a'\n\n" query)) + +(define (org-mu4e-link msg) + "Create a link for this message understandable by org-mu4e." + (let* ((subject ;; cleanup subject + (string-map + (lambda (kar) + (if (member kar '(#\] #\[)) #\space kar)) + (or (mu:subject msg) "No subject")))) + (format #f "[[mu4e:msgid:~a][~s]]" + (mu:message-id msg) subject))) + +(define (display-org-entry msg tag) + "Write an org entry for MSG." + (format #t "** ~a ~a\n\t~s\n\t~s\n" + (org-mu4e-link msg) + (if tag (string-concatenate `(":" ,tag "::")) "") + (or (mu:from msg) "?") + (let ((body (mu:body-txt msg))) + (if (not body) ;; get a 'summary' of the body text + "" + (string-map + (lambda (c) + (if (or (char=? c #\newline) (char=? c #\return)) + #\space + c)) + (substring body 0 (min (string-length body) 100))))))) + +(define (main args) + (let* ((optionspec '( (muhome (value #t)) + (tag (value #t)) + (help (single-char #\h) (value #f)))) + (options (getopt-long args optionspec)) + (msg (string-append + "usage: mu4e-org [--help] [--muhome=] [--tag=] ")) + (help (option-ref options 'help #f)) + (tag (option-ref options 'tag #f)) + (muhome (option-ref options 'muhome #f)) + (query (string-concatenate (option-ref options '() '())))) + (if help + (begin (display msg) (exit 0)) + (begin + (mu:initialize muhome) + (display-org-header query) + (mu:for-each-message + (lambda (msg) (display-org-entry msg tag)) + query))))) + +;; Local Variables: +;; mode: scheme +;; End: diff --git a/guile/fdl.texi b/guile/fdl.texi new file mode 100644 index 0000000..96ce74e --- /dev/null +++ b/guile/fdl.texi @@ -0,0 +1,451 @@ +@c The GNU Free Documentation License. +@center Version 1.2, November 2002 + +@c This file is intended to be included within another document, +@c hence no sectioning command or @node. + +@display +Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc. +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +@end display + +@enumerate 0 +@item +PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document @dfn{free} in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of ``copyleft'', which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + +@item +APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The ``Document'', below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as ``you''. You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A ``Modified Version'' of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A ``Secondary Section'' is a named appendix or a front-matter section +of the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall +subject (or to related matters) and contains nothing that could fall +directly within that overall subject. (Thus, if the Document is in +part a textbook of mathematics, a Secondary Section may not explain +any mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The ``Invariant Sections'' are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The ``Cover Texts'' are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A ``Transparent'' copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not ``Transparent'' is called ``Opaque''. + +Examples of suitable formats for Transparent copies include plain +@sc{ascii} without markup, Texinfo input format, La@TeX{} input +format, @acronym{SGML} or @acronym{XML} using a publicly available +@acronym{DTD}, and standard-conforming simple @acronym{HTML}, +PostScript or @acronym{PDF} designed for human modification. Examples +of transparent image formats include @acronym{PNG}, @acronym{XCF} and +@acronym{JPG}. Opaque formats include proprietary formats that can be +read and edited only by proprietary word processors, @acronym{SGML} or +@acronym{XML} for which the @acronym{DTD} and/or processing tools are +not generally available, and the machine-generated @acronym{HTML}, +PostScript or @acronym{PDF} produced by some word processors for +output purposes only. + +The ``Title Page'' means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, ``Title Page'' means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +A section ``Entitled XYZ'' means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as ``Acknowledgements'', +``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' +of such a section when you modify the Document means that it remains a +section ``Entitled XYZ'' according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +@item +VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + +@item +COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + +@item +MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +@enumerate A +@item +Use in the Title Page (and on the covers, if any) a title distinct +from that of the Document, and from those of previous versions +(which should, if there were any, be listed in the History section +of the Document). You may use the same title as a previous version +if the original publisher of that version gives permission. + +@item +List on the Title Page, as authors, one or more persons or entities +responsible for authorship of the modifications in the Modified +Version, together with at least five of the principal authors of the +Document (all of its principal authors, if it has fewer than five), +unless they release you from this requirement. + +@item +State on the Title page the name of the publisher of the +Modified Version, as the publisher. + +@item +Preserve all the copyright notices of the Document. + +@item +Add an appropriate copyright notice for your modifications +adjacent to the other copyright notices. + +@item +Include, immediately after the copyright notices, a license notice +giving the public permission to use the Modified Version under the +terms of this License, in the form shown in the Addendum below. + +@item +Preserve in that license notice the full lists of Invariant Sections +and required Cover Texts given in the Document's license notice. + +@item +Include an unaltered copy of this License. + +@item +Preserve the section Entitled ``History'', Preserve its Title, and add +to it an item stating at least the title, year, new authors, and +publisher of the Modified Version as given on the Title Page. If +there is no section Entitled ``History'' in the Document, create one +stating the title, year, authors, and publisher of the Document as +given on its Title Page, then add an item describing the Modified +Version as stated in the previous sentence. + +@item +Preserve the network location, if any, given in the Document for +public access to a Transparent copy of the Document, and likewise +the network locations given in the Document for previous versions +it was based on. These may be placed in the ``History'' section. +You may omit a network location for a work that was published at +least four years before the Document itself, or if the original +publisher of the version it refers to gives permission. + +@item +For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve +the Title of the section, and preserve in the section all the +substance and tone of each of the contributor acknowledgements and/or +dedications given therein. + +@item +Preserve all the Invariant Sections of the Document, +unaltered in their text and in their titles. Section numbers +or the equivalent are not considered part of the section titles. + +@item +Delete any section Entitled ``Endorsements''. Such a section +may not be included in the Modified Version. + +@item +Do not retitle any existing section to be Entitled ``Endorsements'' or +to conflict in title with any Invariant Section. + +@item +Preserve any Warranty Disclaimers. +@end enumerate + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled ``Endorsements'', provided it contains +nothing but endorsements of your Modified Version by various +parties---for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + +@item +COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled ``History'' +in the various original documents, forming one section Entitled +``History''; likewise combine any sections Entitled ``Acknowledgements'', +and any sections Entitled ``Dedications''. You must delete all +sections Entitled ``Endorsements.'' + +@item +COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + +@item +AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an ``aggregate'' if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + +@item +TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled ``Acknowledgements'', +``Dedications'', or ``History'', the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + +@item +TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + +@item +FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +@uref{http://www.gnu.org/copyleft/}. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License ``or any later version'' applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. +@end enumerate + +@page +@heading ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + +@smallexample +@group + Copyright (C) @var{year} @var{your name}. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. A copy of the license is included in the section entitled ``GNU + Free Documentation License''. +@end group +@end smallexample + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the ``with@dots{}Texts.'' line with this: + +@smallexample +@group + with the Invariant Sections being @var{list their titles}, with + the Front-Cover Texts being @var{list}, and with the Back-Cover Texts + being @var{list}. +@end group +@end smallexample + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. + +@c Local Variables: +@c ispell-local-pdict: "ispell-dict" +@c End: + diff --git a/guile/mu-guile-message.c b/guile/mu-guile-message.c new file mode 100644 index 0000000..04a1669 --- /dev/null +++ b/guile/mu-guile-message.c @@ -0,0 +1,627 @@ +/* +** Copyright (C) 2011-2013 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ + +#include +#include + +#include "mu-guile.h" + +#include +#include +#include +#include +#include + +/* pseudo field, not in Xapian */ +#define MU_GUILE_MSG_FIELD_ID_TIMESTAMP (MU_MSG_FIELD_ID_NUM + 1) + +/* some symbols */ +static SCM SYMB_PRIO_LOW, SYMB_PRIO_NORMAL, SYMB_PRIO_HIGH; +static SCM SYMB_FLAG_NEW, SYMB_FLAG_PASSED, SYMB_FLAG_REPLIED, + SYMB_FLAG_SEEN, SYMB_FLAG_TRASHED, SYMB_FLAG_DRAFT, + SYMB_FLAG_FLAGGED, SYMB_FLAG_SIGNED, SYMB_FLAG_ENCRYPTED, + SYMB_FLAG_HAS_ATTACH, SYMB_FLAG_UNREAD; +static SCM SYMB_CONTACT_TO, SYMB_CONTACT_CC, SYMB_CONTACT_BCC, + SYMB_CONTACT_FROM; + +struct _MuMsgWrapper { + MuMsg *_msg; + gboolean _unrefme; +}; +typedef struct _MuMsgWrapper MuMsgWrapper; +static long MSG_TAG; + +static gboolean +mu_guile_scm_is_msg (SCM scm) +{ + return SCM_NIMP(scm) && (long)SCM_CAR(scm) == MSG_TAG; +} + +SCM +mu_guile_msg_to_scm (MuMsg *msg) +{ + MuMsgWrapper *msgwrap; + + g_return_val_if_fail (msg, SCM_UNDEFINED); + + msgwrap = scm_gc_malloc (sizeof (MuMsgWrapper), "msg"); + msgwrap->_msg = msg; + msgwrap->_unrefme = FALSE; + + SCM_RETURN_NEWSMOB (MSG_TAG, msgwrap); +} + +struct _FlagData { + MuFlags flags; + SCM lst; +}; +typedef struct _FlagData FlagData; + + +#define MU_GUILE_INITIALIZED_OR_ERROR \ + do { if (!(mu_guile_initialized())) \ + return mu_guile_error (FUNC_NAME, 0, \ + "mu not initialized; call mu:initialize", \ + SCM_UNDEFINED); \ + } while (0) + + +static void +check_flag (MuFlags flag, FlagData *fdata) +{ + SCM flag_scm; + + if (!(fdata->flags & flag)) + return; + + switch (flag) { + case MU_FLAG_NEW: flag_scm = SYMB_FLAG_NEW; break; + case MU_FLAG_PASSED: flag_scm = SYMB_FLAG_PASSED; break; + case MU_FLAG_REPLIED: flag_scm = SYMB_FLAG_REPLIED; break; + case MU_FLAG_SEEN: flag_scm = SYMB_FLAG_SEEN; break; + case MU_FLAG_TRASHED: flag_scm = SYMB_FLAG_TRASHED; break; + case MU_FLAG_SIGNED: flag_scm = SYMB_FLAG_SIGNED; break; + case MU_FLAG_DRAFT: flag_scm = SYMB_FLAG_DRAFT; break; + case MU_FLAG_FLAGGED: flag_scm = SYMB_FLAG_FLAGGED; break; + case MU_FLAG_ENCRYPTED: flag_scm = SYMB_FLAG_ENCRYPTED; break; + case MU_FLAG_HAS_ATTACH: flag_scm = SYMB_FLAG_HAS_ATTACH; break; + case MU_FLAG_UNREAD: flag_scm = SYMB_FLAG_UNREAD; break; + default: flag_scm = SCM_UNDEFINED; + } + + fdata->lst = scm_append_x + (scm_list_2(fdata->lst, + scm_list_1 (flag_scm))); +} + +static SCM +get_flags_scm (MuMsg *msg) +{ + FlagData fdata; + + fdata.flags = mu_msg_get_flags (msg); + fdata.lst = SCM_EOL; + + mu_flags_foreach ((MuFlagsForeachFunc)check_flag, &fdata); + + return fdata.lst; +} + + +static SCM +get_prio_scm (MuMsg *msg) +{ + switch (mu_msg_get_prio (msg)) { + + case MU_MSG_PRIO_LOW: return SYMB_PRIO_LOW; + case MU_MSG_PRIO_NORMAL: return SYMB_PRIO_NORMAL; + case MU_MSG_PRIO_HIGH: return SYMB_PRIO_HIGH; + + default: + g_return_val_if_reached (SCM_UNDEFINED); + } +} + +static SCM +msg_string_list_field (MuMsg *msg, MuMsgFieldId mfid) +{ + SCM scmlst; + const GSList *lst; + + lst = mu_msg_get_field_string_list (msg, mfid); + + for (scmlst = SCM_EOL; lst; + lst = g_slist_next(lst)) { + SCM item; + item = scm_list_1 + (mu_guile_scm_from_str((const char*)lst->data)); + scmlst = scm_append_x (scm_list_2(scmlst, item)); + } + + return scmlst; +} + + +static SCM +get_body (MuMsg *msg, gboolean html) +{ + SCM data; + const char* body; + MuMsgOptions opts; + + opts = MU_MSG_OPTION_NONE; + + if (html) + body = mu_msg_get_body_html (msg, opts); + else + body = mu_msg_get_body_text (msg, opts); + + if (body) + data = mu_guile_scm_from_str (body); + else + data = SCM_BOOL_F; + + /* explicitly close the file backend, so we won't run of fds */ + mu_msg_unload_msg_file (msg); + + return data; +} + + +SCM_DEFINE (get_field, "mu:c:get-field", 2, 0, 0, + (SCM MSG, SCM FIELD), + "Get the field FIELD from message MSG.\n") +#define FUNC_NAME s_get_field +{ + MuMsgWrapper *msgwrap; + MuMsgFieldId mfid; + msgwrap = (MuMsgWrapper*) SCM_CDR(MSG); + + MU_GUILE_INITIALIZED_OR_ERROR; + + SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME); + SCM_ASSERT (scm_integer_p(FIELD), FIELD, SCM_ARG2, FUNC_NAME); + + mfid = scm_to_int (FIELD); + SCM_ASSERT (mfid < MU_MSG_FIELD_ID_NUM || + mfid == MU_GUILE_MSG_FIELD_ID_TIMESTAMP, + FIELD, SCM_ARG2, FUNC_NAME); + + switch (mfid) { + case MU_MSG_FIELD_ID_PRIO: return get_prio_scm (msgwrap->_msg); + case MU_MSG_FIELD_ID_FLAGS: return get_flags_scm (msgwrap->_msg); + + case MU_MSG_FIELD_ID_BODY_HTML: + return get_body (msgwrap->_msg, TRUE); + case MU_MSG_FIELD_ID_BODY_TEXT: + return get_body (msgwrap->_msg, FALSE); + + /* our pseudo-field; we get it from the message file */ + case MU_GUILE_MSG_FIELD_ID_TIMESTAMP: + return scm_from_uint ( + (unsigned)mu_msg_get_timestamp(msgwrap->_msg)); + default: break; + } + + switch (mu_msg_field_type (mfid)) { + case MU_MSG_FIELD_TYPE_STRING: + return mu_guile_scm_from_str + (mu_msg_get_field_string(msgwrap->_msg, mfid)); + case MU_MSG_FIELD_TYPE_BYTESIZE: + case MU_MSG_FIELD_TYPE_TIME_T: + return scm_from_uint ( + mu_msg_get_field_numeric (msgwrap->_msg, mfid)); + case MU_MSG_FIELD_TYPE_INT: + return scm_from_int ( + mu_msg_get_field_numeric (msgwrap->_msg, mfid)); + case MU_MSG_FIELD_TYPE_STRING_LIST: + return msg_string_list_field (msgwrap->_msg, mfid); + default: + SCM_ASSERT (0, FIELD, SCM_ARG2, FUNC_NAME); + } +} +#undef FUNC_NAME + + + +struct _EachContactData { + SCM lst; + MuMsgContactType ctype; +}; +typedef struct _EachContactData EachContactData; + +static void +contacts_to_list (MuMsgContact *contact, EachContactData *ecdata) +{ + SCM item; + + if (ecdata->ctype != MU_MSG_CONTACT_TYPE_ALL && + mu_msg_contact_type (contact) != ecdata->ctype) + return; + + item = scm_list_1 + (scm_cons + (mu_guile_scm_from_str(mu_msg_contact_name (contact)), + mu_guile_scm_from_str(mu_msg_contact_email (contact)))); + + ecdata->lst = scm_append_x (scm_list_2(ecdata->lst, item)); +} + + +SCM_DEFINE (get_contacts, "mu:c:get-contacts", 2, 0, 0, + (SCM MSG, SCM CONTACT_TYPE), + "Get a list of contact information pairs.\n") +#define FUNC_NAME s_get_contacts +{ + MuMsgWrapper *msgwrap; + EachContactData ecdata; + + MU_GUILE_INITIALIZED_OR_ERROR; + + SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME); + SCM_ASSERT (scm_symbol_p (CONTACT_TYPE) || scm_is_bool(CONTACT_TYPE), + CONTACT_TYPE, SCM_ARG2, FUNC_NAME); + + if (CONTACT_TYPE == SCM_BOOL_F) + return SCM_UNSPECIFIED; /* nothing to do */ + else if (CONTACT_TYPE == SCM_BOOL_T) + ecdata.ctype = MU_MSG_CONTACT_TYPE_ALL; + else { + if (scm_is_eq (CONTACT_TYPE, SYMB_CONTACT_TO)) + ecdata.ctype = MU_MSG_CONTACT_TYPE_TO; + else if (scm_is_eq (CONTACT_TYPE, SYMB_CONTACT_CC)) + ecdata.ctype = MU_MSG_CONTACT_TYPE_CC; + else if (scm_is_eq (CONTACT_TYPE, SYMB_CONTACT_BCC)) + ecdata.ctype = MU_MSG_CONTACT_TYPE_BCC; + else if (scm_is_eq (CONTACT_TYPE, SYMB_CONTACT_FROM)) + ecdata.ctype = MU_MSG_CONTACT_TYPE_FROM; + else + return mu_guile_error (FUNC_NAME, 0, + "invalid contact type", + SCM_UNDEFINED); + } + + ecdata.lst = SCM_EOL; + msgwrap = (MuMsgWrapper*) SCM_CDR(MSG); + mu_msg_contact_foreach (msgwrap->_msg, + (MuMsgContactForeachFunc)contacts_to_list, + &ecdata); + /* explicitly close the file backend, so we won't run out of fds */ + mu_msg_unload_msg_file (msgwrap->_msg); + + return ecdata.lst; +} +#undef FUNC_NAME + +struct _AttInfo { + SCM attlist; + gboolean attachments_only; +}; +typedef struct _AttInfo AttInfo; + +static void +each_part (MuMsg *msg, MuMsgPart *part, AttInfo *attinfo) +{ + char *mime_type, *filename; + SCM elm; + + if (!part->type) + return; + if (attinfo->attachments_only && + !mu_msg_part_maybe_attachment (part)) + return; + + mime_type = g_strdup_printf ("%s/%s", part->type, part->subtype); + filename = mu_msg_part_get_filename (part, FALSE); + + elm = scm_list_5 ( + /* msg */ + mu_guile_scm_from_str (mu_msg_get_path(msg)), + /* index */ + scm_from_uint(part->index), + /* filename or #f */ + filename ? mu_guile_scm_from_str (filename) : SCM_BOOL_F, + /* mime-type */ + mime_type ? mu_guile_scm_from_str (mime_type): SCM_BOOL_F, + /* size */ + part->size > 0 ? scm_from_uint (part->size) : SCM_BOOL_F); + + g_free (mime_type); + g_free (filename); + + attinfo->attlist = scm_cons (elm, attinfo->attlist); +} + + +SCM_DEFINE (get_parts, "mu:c:get-parts", 1, 1, 0, + (SCM MSG, SCM ATTS_ONLY), + "Get the list of mime-parts for MSG. If ATTS_ONLY is #t, only" + "get parts that are (look like) attachments. The resulting list has " + "elements which are list of the form (index name mime-type size).\n") +#define FUNC_NAME s_get_parts +{ + MuMsgWrapper *msgwrap; + AttInfo attinfo; + + MU_GUILE_INITIALIZED_OR_ERROR; + + SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME); + SCM_ASSERT (scm_is_bool(ATTS_ONLY), ATTS_ONLY, SCM_ARG2, FUNC_NAME); + + attinfo.attlist = SCM_EOL; /* empty list */ + attinfo.attachments_only = ATTS_ONLY == SCM_BOOL_T ? TRUE : FALSE; + + msgwrap = (MuMsgWrapper*) SCM_CDR(MSG); + mu_msg_part_foreach (msgwrap->_msg, MU_MSG_OPTION_NONE, + (MuMsgPartForeachFunc)each_part, + &attinfo); + + /* explicitly close the file backend, so we won't run of fds */ + mu_msg_unload_msg_file (msgwrap->_msg); + + return attinfo.attlist; +} +#undef FUNC_NAME + + +SCM_DEFINE (get_header, "mu:c:get-header", 2, 0, 0, + (SCM MSG, SCM HEADER), "Get an arbitrary HEADER from MSG.\n") +#define FUNC_NAME s_get_header +{ + MuMsgWrapper *msgwrap; + char *header; + SCM val; + + MU_GUILE_INITIALIZED_OR_ERROR; + + SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME); + SCM_ASSERT (scm_is_string (HEADER)||HEADER==SCM_UNDEFINED, + HEADER, SCM_ARG2, FUNC_NAME); + + msgwrap = (MuMsgWrapper*) SCM_CDR(MSG); + header = scm_to_utf8_string (HEADER); + val = mu_guile_scm_from_str + (mu_msg_get_header(msgwrap->_msg, header)); + free (header); + + /* explicitly close the file backend, so we won't run of fds */ + mu_msg_unload_msg_file (msgwrap->_msg); + + return val; +} +#undef FUNC_NAME + + +static void +call_func (SCM FUNC, MuMsgIter *iter, const char* func_name) +{ + SCM msgsmob; + MuMsg *msg; + + msg = mu_msg_iter_get_msg_floating (iter); /* don't unref */ + + msgsmob = mu_guile_msg_to_scm (mu_msg_ref(msg)); + scm_call_1 (FUNC, msgsmob); +} + + +static MuMsgIter* +get_query_iter (MuQuery *query, const char* expr, int maxnum) +{ + MuMsgIter *iter; + GError *err; + + err = NULL; + iter = mu_query_run (query, expr, MU_MSG_FIELD_ID_NONE, maxnum, + MU_QUERY_FLAG_NONE, &err); + if (!iter) { + mu_guile_g_error ("", err); + g_clear_error (&err); + } + + return iter; +} + + +SCM_DEFINE (for_each_message, "mu:c:for-each-message", 3, 0, 0, + (SCM FUNC, SCM EXPR, SCM MAXNUM), +"Call FUNC for each msg in the message store matching EXPR. EXPR is" +"either a string containing a mu search expression or a boolean; in the former " +"case, limit the messages to only those matching the expression, in the " +"latter case, match /all/ messages if the EXPR equals #t, and match " +"none if EXPR equals #f.") +#define FUNC_NAME s_for_each_message +{ + MuMsgIter *iter; + char* expr; + + MU_GUILE_INITIALIZED_OR_ERROR; + + SCM_ASSERT (scm_procedure_p (FUNC), FUNC, SCM_ARG1, FUNC_NAME); + SCM_ASSERT (scm_is_bool(EXPR) || scm_is_string (EXPR), + EXPR, SCM_ARG2, FUNC_NAME); + SCM_ASSERT (scm_is_integer (MAXNUM), MAXNUM, SCM_ARG3, FUNC_NAME); + + if (EXPR == SCM_BOOL_F) + return SCM_UNSPECIFIED; /* nothing to do */ + + if (EXPR == SCM_BOOL_T) + expr = strdup (""); /* note, "" matches *all* messages */ + else + expr = scm_to_utf8_string(EXPR); + + iter = get_query_iter (mu_guile_instance()->query, expr, + scm_to_int(MAXNUM)); + free (expr); + if (!iter) + return SCM_UNSPECIFIED; + + while (!mu_msg_iter_is_done(iter)) { + call_func (FUNC, iter, FUNC_NAME); + mu_msg_iter_next (iter); + } + + mu_msg_iter_destroy (iter); + + return SCM_UNSPECIFIED; +} +#undef FUNC_NAME + + +static SCM +register_symbol (const char *name) +{ + SCM scm; + + scm = scm_from_utf8_symbol (name); + scm_c_define (name, scm); + scm_c_export (name, NULL); + + return scm; +} + +static void +define_symbols (void) +{ + SYMB_CONTACT_TO = register_symbol ("mu:contact:to"); + SYMB_CONTACT_CC = register_symbol ("mu:contact:cc"); + SYMB_CONTACT_FROM = register_symbol ("mu:contact:from"); + SYMB_CONTACT_BCC = register_symbol ("mu:contact:bcc"); + + SYMB_PRIO_LOW = register_symbol ("mu:prio:low"); + SYMB_PRIO_NORMAL = register_symbol ("mu:prio:normal"); + SYMB_PRIO_HIGH = register_symbol ("mu:prio:high"); + + SYMB_FLAG_NEW = register_symbol ("mu:flag:new"); + SYMB_FLAG_PASSED = register_symbol ("mu:flag:passed"); + SYMB_FLAG_REPLIED = register_symbol ("mu:flag:replied"); + SYMB_FLAG_SEEN = register_symbol ("mu:flag:seen"); + SYMB_FLAG_TRASHED = register_symbol ("mu:flag:trashed"); + SYMB_FLAG_DRAFT = register_symbol ("mu:flag:draft"); + SYMB_FLAG_FLAGGED = register_symbol ("mu:flag:flagged"); + SYMB_FLAG_SIGNED = register_symbol ("mu:flag:signed"); + SYMB_FLAG_ENCRYPTED = register_symbol ("mu:flag:encrypted"); + SYMB_FLAG_HAS_ATTACH = register_symbol ("mu:flag:has-attach"); + SYMB_FLAG_UNREAD = register_symbol ("mu:flag:unread"); +} + + +static struct { + const char* name; + unsigned val; +} VAR_PAIRS[] = { + + { "mu:field:bcc", MU_MSG_FIELD_ID_BCC }, + { "mu:field:body-html", MU_MSG_FIELD_ID_BODY_HTML }, + { "mu:field:body-txt", MU_MSG_FIELD_ID_BODY_TEXT }, + { "mu:field:cc", MU_MSG_FIELD_ID_CC }, + { "mu:field:date", MU_MSG_FIELD_ID_DATE }, + { "mu:field:flags", MU_MSG_FIELD_ID_FLAGS }, + { "mu:field:from", MU_MSG_FIELD_ID_FROM }, + { "mu:field:maildir", MU_MSG_FIELD_ID_MAILDIR }, + { "mu:field:message-id",MU_MSG_FIELD_ID_MSGID }, + { "mu:field:path", MU_MSG_FIELD_ID_PATH }, + { "mu:field:prio", MU_MSG_FIELD_ID_PRIO }, + { "mu:field:refs", MU_MSG_FIELD_ID_REFS }, + { "mu:field:size", MU_MSG_FIELD_ID_SIZE }, + { "mu:field:subject", MU_MSG_FIELD_ID_SUBJECT }, + { "mu:field:tags", MU_MSG_FIELD_ID_TAGS }, + { "mu:field:to", MU_MSG_FIELD_ID_TO }, + + /* non-Xapian field: timestamp */ + { "mu:field:timestamp", MU_GUILE_MSG_FIELD_ID_TIMESTAMP } +}; + +static void +define_vars (void) +{ + unsigned u; + for (u = 0; u != G_N_ELEMENTS(VAR_PAIRS); ++u) { + scm_c_define (VAR_PAIRS[u].name, + scm_from_uint (VAR_PAIRS[u].val)); + scm_c_export (VAR_PAIRS[u].name, NULL); + } +} + + +static SCM +msg_mark (SCM msg_smob) +{ + MuMsgWrapper *msgwrap; + msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + + msgwrap->_unrefme = TRUE; + + return SCM_UNSPECIFIED; +} + +static size_t +msg_free (SCM msg_smob) +{ + MuMsgWrapper *msgwrap; + msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + + if (msgwrap->_unrefme) + mu_msg_unref (msgwrap->_msg); + + return sizeof (MuMsgWrapper); +} + +static int +msg_print (SCM msg_smob, SCM port, scm_print_state * pstate) +{ + MuMsgWrapper *msgwrap; + msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + + scm_puts ("#_msg), + port); + + scm_puts (">", port); + + return 1; +} + + +void* +mu_guile_message_init (void *data) +{ + MSG_TAG = scm_make_smob_type ("msg", sizeof(MuMsgWrapper)); + + scm_set_smob_mark (MSG_TAG, msg_mark); + scm_set_smob_free (MSG_TAG, msg_free); + scm_set_smob_print (MSG_TAG, msg_print); + + define_vars (); + define_symbols (); + +#ifndef SCM_MAGIC_SNARFER +#include "mu-guile-message.x" +#endif /*SCM_MAGIC_SNARFER*/ + + return NULL; +} diff --git a/guile/mu-guile-message.h b/guile/mu-guile-message.h new file mode 100644 index 0000000..411644e --- /dev/null +++ b/guile/mu-guile-message.h @@ -0,0 +1,39 @@ +/* +** Copyright (C) 2011-2013 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_GUILE_MESSAGE_H__ +#define __MU_GUILE_MESSAGE_H__ + +#include + +G_BEGIN_DECLS + +/** + * Initialize this mu guile module. + * + * @param data + * + * @return + */ +void* mu_guile_message_init (void *data); + + +G_END_DECLS + +#endif /*__MU_GUILE_MESSAGE_H__*/ diff --git a/guile/mu-guile.c b/guile/mu-guile.c new file mode 100644 index 0000000..dcd7beb --- /dev/null +++ b/guile/mu-guile.c @@ -0,0 +1,256 @@ +/* +** Copyright (C) 2011-2020 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include +#include + +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#include +#pragma GCC diagnostic pop + +#include +#include +#include +#include +#include +#include + +#include "mu-guile.h" + + +SCM +mu_guile_scm_from_str (const char *str) +{ + if (!str) + return SCM_BOOL_F; + else + return scm_from_stringn (str, strlen(str), "UTF-8", + SCM_FAILED_CONVERSION_QUESTION_MARK); +} + + +SCM +mu_guile_error (const char *func_name, int status, + const char *fmt, SCM args) +{ + scm_error_scm (scm_from_locale_symbol ("MuError"), + scm_from_utf8_string (func_name ? func_name : ""), + scm_from_utf8_string (fmt), args, + scm_list_1 (scm_from_int (status))); + + return SCM_UNSPECIFIED; +} + +SCM +mu_guile_g_error (const char *func_name, GError *err) +{ + scm_error_scm (scm_from_locale_symbol ("MuError"), + scm_from_utf8_string (func_name), + scm_from_utf8_string (err ? err->message : "error"), + SCM_UNDEFINED, SCM_UNDEFINED); + + return SCM_UNSPECIFIED; +} + + + +/* there can be only one */ + +static MuGuile *_singleton = NULL; + +static gboolean +mu_guile_init_instance (const char *muhome) +{ + MuStore *store; + MuQuery *query; + GError *err; + + setlocale (LC_ALL, ""); + + if (!mu_runtime_init (muhome, "guile")) + return FALSE; + + err = NULL; + store = mu_store_new_readable + (mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), + &err); + if (!store) + goto errexit; + + query = mu_query_new (store, &err); + mu_store_unref (store); + if (!query) + goto errexit; + + _singleton = g_new0 (MuGuile, 1); + _singleton->query = query; + + return TRUE; + +errexit: + mu_guile_g_error (__func__, err); + g_clear_error (&err); + return FALSE; +} + +static void +mu_guile_uninit_instance (void) +{ + g_return_if_fail (_singleton); + + mu_query_destroy (_singleton->query); + g_free (_singleton); + + _singleton = NULL; + + mu_runtime_uninit (); +} + + +MuGuile* +mu_guile_instance (void) +{ + g_return_val_if_fail (_singleton, NULL); + return _singleton; +} + +gboolean +mu_guile_initialized (void) +{ + return _singleton != NULL; +} + + +SCM_DEFINE_PUBLIC (mu_initialize, "mu:initialize", 0, 1, 0, + (SCM MUHOME), + "Initialize mu - needed before you call any of the other " + "functions. Optionally, you can provide MUHOME which should be an " + "absolute path to your mu home directory " + "-- typically, the default, ~/.cache/mu, should be just fine.") +#define FUNC_NAME s_mu_initialize +{ + char *muhome; + gboolean rv; + + SCM_ASSERT (scm_is_string (MUHOME) || MUHOME == SCM_BOOL_F || + SCM_UNBNDP(MUHOME), MUHOME, SCM_ARG1, FUNC_NAME); + + if (mu_guile_initialized()) + return mu_guile_error (FUNC_NAME, 0, "Already initialized", + SCM_UNSPECIFIED); + + if (SCM_UNBNDP(MUHOME) || MUHOME == SCM_BOOL_F) + muhome = NULL; + else + muhome = scm_to_utf8_string (MUHOME); + + rv = mu_guile_init_instance (muhome); + free (muhome); + + if (!rv) + return mu_guile_error (FUNC_NAME, 0, "Failed to initialize mu", + SCM_UNSPECIFIED); + + /* cleanup when we're exiting */ + atexit (mu_guile_uninit_instance); + + return SCM_UNSPECIFIED; +} +#undef FUNC_NAME + +SCM_DEFINE_PUBLIC (mu_initialized_p, "mu:initialized?", 0, 0, 0, + (void), "Whether mu is initialized or not.\n") +#define FUNC_NAME s_mu_initialized_p +{ + return mu_guile_initialized() ? SCM_BOOL_T : SCM_BOOL_F; +} +#undef FUNC_NAME + + +SCM_DEFINE (log_func, "mu:c:log", 1, 0, 1, (SCM LEVEL, SCM FRM, SCM ARGS), + "log some message at LEVEL using a list of ARGS applied to FRM" + "(in 'simple-format' notation).\n") +#define FUNC_NAME s_log_func +{ + gchar *output; + SCM str; + int level; + + SCM_ASSERT (scm_integer_p(LEVEL), LEVEL, SCM_ARG1, FUNC_NAME); + SCM_ASSERT (scm_is_string(FRM), FRM, SCM_ARG2, ""); + SCM_VALIDATE_REST_ARGUMENT(ARGS); + + level = scm_to_int (LEVEL); + if (level != G_LOG_LEVEL_MESSAGE && + level != G_LOG_LEVEL_WARNING && + level != G_LOG_LEVEL_CRITICAL) + return mu_guile_error (FUNC_NAME, 0, "invalid log level", + SCM_UNSPECIFIED); + + str = scm_simple_format (SCM_BOOL_F, FRM, ARGS); + + if (!scm_is_string (str)) + return SCM_UNSPECIFIED; + + output = scm_to_utf8_string (str); + g_log (G_LOG_DOMAIN, level, "%s", output); + free (output); + + return SCM_UNSPECIFIED; +} +#undef FUNC_NAME + + +static struct { + const char* name; + unsigned val; +} VAR_PAIRS[] = { + + { "mu:message", G_LOG_LEVEL_MESSAGE }, + { "mu:warning", G_LOG_LEVEL_WARNING }, + { "mu:critical", G_LOG_LEVEL_CRITICAL } +}; + +static void +define_vars (void) +{ + unsigned u; + for (u = 0; u != G_N_ELEMENTS(VAR_PAIRS); ++u) { + scm_c_define (VAR_PAIRS[u].name, + scm_from_uint (VAR_PAIRS[u].val)); + scm_c_export (VAR_PAIRS[u].name, NULL); + } +} + + +void* +mu_guile_init (void *data) +{ + define_vars (); + + +#ifndef SCM_MAGIC_SNARFER +#include "mu-guile.x" +#endif /*SCM_MAGIC_SNARFER*/ + + return NULL; +} diff --git a/guile/mu-guile.h b/guile/mu-guile.h new file mode 100644 index 0000000..fd230a5 --- /dev/null +++ b/guile/mu-guile.h @@ -0,0 +1,99 @@ +/* +** Copyright (C) 2011-2013 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_GUILE_H__ +#define __MU_GUILE_H__ + +#include +#include + +G_BEGIN_DECLS + + +struct _MuGuile { + MuQuery *query; +}; +typedef struct _MuGuile MuGuile; + +/** + * get the single MuGuile instance + * + * @return the instance or NULL in case of error + */ +MuGuile *mu_guile_instance (void); + + +/** + * whether mu-guile is initialized + * + * @return TRUE if MuGuile is Initialized, FALSE otherwise + */ +gboolean mu_guile_initialized (void); + + +/** + * raise a guile error (based on a GError) + * + * @param func_name function name + * @param err the error + * + * @return SCM_UNSPECIFIED + */ +SCM mu_guile_g_error (const char *func_name, GError *err); + + +/** + * raise a guile error + * + * @param func_name function + * @param status err code + * @param fmt format string for error msg + * @param args params for format string + * + * @return SCM_UNSPECIFIED + */ +SCM mu_guile_error (const char *func_name, int status, + const char *fmt, SCM args); + + +/** + * convert a const char* into an SCM -- either a string or, if str == + * NULL, #f. It assumes str is in UTF8 encoding, and replace + * characters with '?' if needed. + * + * @param str a string or NULL + * + * @return a guile string or #f + */ +SCM mu_guile_scm_from_str (const char *str); + + +/** + * Initialize this mu guile module. + * + * @param data + * + * @return + */ +void* mu_guile_init (void *data); + + +G_END_DECLS + +#endif /*__MU_GUILE_H__*/ diff --git a/guile/mu-guile.texi b/guile/mu-guile.texi new file mode 100644 index 0000000..c52213e --- /dev/null +++ b/guile/mu-guile.texi @@ -0,0 +1,995 @@ +\input texinfo.tex @c -*-texinfo-*- +@c %**start of header +@setfilename mu-guile.info +@settitle mu-guile user manual + +@c Use proper quote and backtick for code sections in PDF output +@c Cf. Texinfo manual 14.2 +@set txicodequoteundirected +@set txicodequotebacktick + +@documentencoding UTF-8 +@c %**end of header + +@include texi.texi + +@copying +Copyright @copyright{} 2012 Dirk-Jan C. Binnema + +@quotation +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 or +any later version published by the Free Software Foundation; with no +Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A +copy of the license is included in the section entitled ``GNU Free +Documentation License.'' +@end quotation +@end copying + +@titlepage +@title @t{mu-guile} - extending @t{mu} with Guile Scheme +@subtitle version @value{mu-version} +@author Dirk-Jan C. Binnema + +@c The following two commands start the copyright page. +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@dircategory The Algorithmic Language Scheme +@direntry +* Mu-guile: (mu-guile). Guile-bindings for the mu e-mail indexer/searcher +@end direntry + +@contents + +@ifnottex +@node Top +@top mu-guile manual +@end ifnottex + +@iftex +@node Welcome to mu-guile +@unnumbered Welcome to mu-guile +@end iftex + +Welcome to @t{mu-guile}! + +@t{mu} is a program for indexing and searching your e-mails. It can search +your messages in many different ways, but sometimes that may not be +enough. If you have very specific queries, or want do generate some +statistics, you need some more power. + +@t{mu-guile} is made for those cases. @t{mu-guile} exposes the internals of +@t{mu} and its database to the @t{guile} programming language. Guile is the +@emph{GNU Ubiquitous Intelligent Language for Extensions} - a version of the +@emph{Scheme} programming language and the official GNU extension language. + +Guile/Scheme is a member of the @emph{Lisp} family of programming languages -- +like emacs-lisp, @emph{Racket}, Common Lisp. If you're not familiar with +Scheme, @t{mu-guile} is an excellent opportunity to learn a bit about! + +Trust me, it's not very hard -- and it's @emph{fun}! + +@menu +* Getting started:: +* Initializing mu-guile:: +* Messages:: +* Contacts:: +* Attachments and other parts:: +* Statistics:: +* Plotting data:: +* Writing scripts:: + +Appendices + +* Recipes:: Snippets do specific things +* GNU Free Documentation License:: The license of this manual. +@end menu + +@node Getting started +@chapter Getting started + +@menu +* Installation:: +* Making sure it works:: +@end menu + +This chapter walks you through the installation and the basic setup. + +@node Installation +@section Installation + +@t{mu-guile} is part of @t{mu} - by installing the latter, the former is +necessarily installed as well. At the time of writing, there are no +distribution-provided packaged versions of @t{mu-guile}; so for now, you need +to follow the steps below. + +@subsection Guile 2.x + +@t{mu-guile} is built automatically when @t{mu} is built, if you have +@t{guile} version 2 or higher. (@t{mu} checks for this during +@t{configure}). Thus, the first step is to ensure you have @t{guile} +installed. + +On Debian/Ubuntu you can install @t{guile} 2.x using the @t{guile-2.0-dev} +package (and its dependencies): +@example +$ sudo apt-get install guile-2.0-dev +@end example + +At the time of writing, there are no official packages for +Fedora@footnote{@url{https://bugzilla.redhat.com/show_bug.cgi?id=678238}}. If +you are using Fedora or any other system that does not have packages, you need +to compile @t{guile} from +source@footnote{@url{http://www.gnu.org/software/guile/manual/html_node/Obtaining-and-Installing-Guile.html#Obtaining-and-Installing-Guile}}. + +@subsection gnuplot + +For creating graphs with @t{mu-guile}, you need the @t{gnuplot} program -- +most likely, there is a package available for your system; for example: + +@example +$ sudo apt-get install gnuplot +@end example + +and in Fedora: + +@example +$ sudo yum install gnuplot +@end example + +@subsection mu + +Assuming @t{guile} 2.x is installed correctly, @t{mu} finds it during its +@t{configure}-stage, and creates @t{mu-guile}. Building @t{mu} follows the +normal steps -- please see the @t{mu} documentation for the details. + +The output of @t{./configure} should end with a little text describing the +detected versions of various libraries @t{mu} depends on. In particular, it +should mention the @t{guile} version, e.g. + +@example +Guile version : 2.0.3.82-a2c66 +@end example + +If you don't see any line referring to @t{guile}, please install it, and run +@t{configure} again. After a successful @t{./configure}, we can make and +install the package: + +@example +$ make && sudo make install +@end example + +@subsection mu-guile + +After this, @t{mu} and @t{mu-guile} are installed -- usually somewhere under +@t{/usr/local}.You may need to update @t{guile}'s @code{%load-path} to find it +there. You can check the current @code{%load-path} with the following: + +@example +guile -c '(display %load-path)(newline)' +@end example + +If necessary, you can add the @t{%load-path} by adding to your +@file{~/.guile}: + +@lisp +(set! %load-path (cons "/usr/local/share/guile/site/2.0" %load-path)) +@end lisp + +Or, alternatively, you can set @t{GUILE_LOAD_PATH}: +@example +export GUILE_LOAD_PATH=/usr/local/share/guile/site/2.0 +@end example + +In both cases the directory should be the directory that contains the +installed @t{mu.scm}; if you installed @t{mu} under a different prefix, you +must change the @code{%load-path} accordingly. After this, you should be ready +to go! + +Furthermore, you need to ensure that @t{guile} can find the mu-guile +library; for this we can use @code{LTDL_LIBRARY_PATH}, e.g. +@example +export LTDL_LIBRARY_PATH=/usr/local/lib +@end example + +@node Making sure it works +@section Making sure it works + +Assuming @t{mu-guile} has been installed correctly (@ref{Installation}), and +also assuming that you have already indexed your e-mail messages (if +necessary, see the @t{mu-index} man-page), we are ready to start @t{mu-guile}; +a session may look something like this: + +@cartouche +@verbatim +GNU Guile 2.0.5.123-4bd53 +Copyright (C) 1995-2012 Free Software Foundation, Inc. + +Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. +This program is free software, and you are welcome to redistribute it +under certain conditions; type `,show c' for details. + +Enter `,help' for help. +scheme@(guile-user)> +@end verbatim +@end cartouche + +@noindent +Now, copy-paste the following after the prompt: + +@cartouche +@lisp +(use-modules (mu)) +(mu:initialize) +(for-each + (lambda(msg) + (format #t "Subject: ~a\n" (mu:subject msg))) + (mu:message-list "hello")) +@end lisp +@end cartouche + +@noindent +After pressing @key{Enter}, you should get a list of all subjects of messages +that match @t{hello}: + +@verbatim +... +Subject: RE: The Bird Serpent War Cataclysm +Subject: Hello! +Subject: Re: post-run tomorrow +Subject: When all is lost +... +@end verbatim + +@noindent +If all this works, congratulations! @t{mu-guile} is installed now, ready to +serve your every searching need! + +@node Initializing mu-guile +@chapter Initializing mu-guile + +We now have installed @t{mu-guile}, and in @ref{Making sure it works} +confirmed that things work by trying some simple script. In this and the +following chapters, we take a closer look at programming with @t{mu-guile}. + +It is possible to write separate programs with @t{mu-guile}, but for now we'll +do things @emph{interactively}, that is, from the Guile-prompt +(``@abbr{REPL}''). + +As we have seen, we start our @t{mu-guile} session by starting @t{guile}: + +@verbatim +$ guile +@end verbatim + +@cartouche +@verbatim +GNU Guile 2.0.5.123-4bd53 +Copyright (C) 1995-2012 Free Software Foundation, Inc. + +Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. +This program is free software, and you are welcome to redistribute it +under certain conditions; type `,show c' for details. + +Enter `,help' for help. +scheme@(guile-user)> +@end verbatim +@end cartouche + +The first thing we need to do is loading the modules. All the basics are in +the @t{(mu)} module, with some statistical extras in @t{(mu stats)}, and some +graph plotting functionality in @t{(mu plot)}@footnote{@code{(mu plot)} +requires the @t{gnuplot} program}. Let's load all of them: +@verbatim +scheme@(guile-user)> (use-modules (mu) (mu stats) (mu plot)) +@end verbatim + +The first time you do this, @t{guile} will probably respond by showing some +messages about compiling the modules, and then return to you with another +prompt. Before we can do anything with @t{mu guile}, we need to initialize the +system: + +@verbatim +scheme@(guile-user)> (mu:initialize) +@end verbatim + +This opens the database for reading, using the default location of +@file{~/.cache/mu}@footnote{If you keep your @t{mu} database in a non-standard +place, use @code{(mu:initialize "/path/to/my/mu/")}} + +Now, @t{mu-guile} is ready to go. In the next chapter, we go through the +modules and show what you can do with them. + +@node Messages +@chapter Messages + +In this chapter, we discuss searching messages and doing things with them. + +@menu +* Finding messages:: query for messages in the database +* Message methods:: what methods are available for messages? +* Example - the longest subject:: find the messages with the longest subject +@end menu + +@node Finding messages +@section Finding messages +Now we are ready to retrieve some messages from the system. There are two main +procedures to do this: + +@itemize +@item @code{(mu:message-list [])} +@item @code{(mu:for-each-message [])} +@end itemize + +@noindent +The first procedure, @code{mu:message-list} returns a list of all messages +matching @t{}; if you leave @t{} out, it +returns @emph{all} messages. For example, to get all messages with @t{coffee} +in the subject line: + +@verbatim +scheme@(guile-user)> (mu:message-list "subject:coffee") +$1 = (#< 9040640> #< 9040630> + #< 9040570>) +@end verbatim + +@noindent +Apparently, we have three messages matching @t{subject:coffee}, so we get a +list of three @code{} objects. Let's just use the +@code{mu:subject} procedure ('method') provided by @code{} objects +to retrieve the subject-field (more about methods in the next section). + +For your convenience, @t{guile} has saved the result of our last query in a +variable called @t{$1}, so to get the subject of the first message in the +list, we can do: + +@verbatim +scheme@(guile-user)> (mu:subject (car $1)) +$2 = "Re: best coffee ever!" +@end verbatim + +@noindent +The second procedure we mentioned, @code{mu:for-each-message}, executes some +procedure for each message matched by the search expression (or @emph{all} +messages if the search expression is omitted): + +@verbatim +scheme@(guile-user)> (mu:for-each-message + (lambda(msg) + (display (mu:subject msg)) + (newline)) + "subject:coffee") +Re: best coffee ever! +best coffee ever! +Coffee beans +scheme@(guile-user)> +@end verbatim + +@noindent +Using @code{mu:message-list} and/or +@code{mu:for-each-message}@footnote{Implementation node: +@code{mu:message-list} is implemented in terms of @code{mu:for-each-message}, +not the other way around. Due to the way @t{mu} works, +@code{mu:for-each-message} is rather more efficient than a combination of +@code{for-each} and @code{mu:message-list}} and a couple of @t{} +methods, together with what Guile/Scheme provides, should allow for many +interesting programs. + +@node Message methods +@section Message methods + +Now that we've seen how to retrieve lists of message objects +(@code{}), let's see what we can do with such an object. + +@code{} defines the following methods that all take a single +@code{} object as a parameter. We won't go into the exact meanings +for all of these procedures here - for the details about various flags / +properties, please refer to the @t{mu-find} man-page. + +@itemize +@item @code{(mu:bcc msg)}: the @t{Bcc} field of the message, or @t{#f} if there is none +@item @code{(mu:body-html msg)}: : the html body of the message, or @t{#f} if there is none +@item @code{(mu:body-txt msg)}: the plain-text body of the message, or @t{#f} if there is none +@item @code{(mu:cc msg)}: the @t{Bcc} field of the message, or @t{#f} if there is none +@item @code{(mu:date msg)}: the @t{Date} field of the message, or 0 if there is none +@item @code{(mu:flags msg)}: list of message-flags for this message +@item @code{(mu:from msg)}: the @t{From} field of the message, or @t{#f} if there is none +@item @code{(mu:maildir msg)}: the maildir this message lives in, or @t{#f} if there is none +@item @code{(mu:message-id msg)}: the @t{Message-Id} field of the message, or @t{#f} if there is none +@item @code{(mu:path msg)}: the file system path for this message +@item @code{(mu:priority msg)}: the priority of this message (either @t{mu:prio:low}, @t{mu:prio:normal} or @t{mu:prio:high} +@item @code{(mu:references msg)}: the list of messages (message-ids) this message +refers to in(mu: the @t{References:} header +@item @code{(mu:size msg)}: size of the message in bytes +@item @code{(mu:subject msg)}: the @t{Subject} field of the message, or @t{#f} if there is none. +@item @code{(mu:tags msg)}: list of tags for this message +@item @code{(mu:timestamp msg)}: the timestamp (mtime) of the message file, or +#f if there is none. +message file +@item @code{(mu:to msg)}: the sender of the message, or @t{#f} if there is none +@end itemize + +With these methods, we can query messages for their properties; for example: + +@verbatim +scheme@(guile-user)> (define msg (car (mu:message-list "snow"))) +scheme@(guile-user)> (mu:subject msg) +$1 = "Re: Running in the snow is beautiful" +scheme@(guile-user)> (mu:flags msg) +$2 = (mu:flag:replied mu:flag:seen) +scheme@(guile-user)> (strftime "%F" (localtime (mu:date msg))) +$3 = "2011-01-15" +@end verbatim + +There are a couple more methods: +@itemize +@item @code{(mu:header msg "")} returns an arbitrary message +header (or @t{#f} if not found) -- e.g. @code{(header msg "User-Agent")} +@item If you include the @t{mu contact} module, the @code{(mu:contacts +msg [contact-type])} method (to get a list of contacts) is +added. @xref{Contacts}. +@item If you include the @t{mu part} module, the @code{((mu:parts msg)} and +@code{(mu:attachments msg)} methods are added. @xref{Attachments and other parts}. +@end itemize + +@node Example - the longest subject +@section Example - the longest subject + +Now, let's write a little example -- let's find out what is the @emph{longest +subject} of any e-mail messages we received in the year 2011. You can try +this if you put the following in a separate file, make it executable, and run +it like any program. + +@lisp +#!/bin/sh +exec guile -s $0 $@ +!# + +(use-modules (mu)) +(use-modules (srfi srfi-1)) + +(mu:initialize) + +;; note: (subject msg) => #f if there is no subject +(define list-of-subjects + (map (lambda (msg) + (or (mu:subject msg) "")) (mu:message-list "date:2011..2011"))) +;; see the mu-find manpage for the date syntax + +(define longest-subject + (fold (lambda (subj1 subj2) + (if (> (string-length subj1) (string-length subj2)) + subj1 subj2)) + "" list-of-subjects)) + +(format #t "Longest subject: ~s\n" longest-subject) +@end lisp + +There are many other ways to solve the same problem, for example by using an +iterative approach with @code{mu:for-each-message}, but it should show how one +can easily write little programs to answer specific questions about your +e-mail corpus. + +@node Contacts +@chapter Contacts + +We can retrieve the sender and recipients of an e-mail message using methods +like @code{mu:from}, @code{mu:to} etc.; @xref{Message methods}. These +procedures return the list of recipients as a single string; however, often it +is more useful to deal with recipients as separate objects. + +@menu +* Contact procedures and objects:: +* All contacts:: +* Utility procedures:: +* Example - mutt export:: +@end menu + + +@node Contact procedures and objects +@section Contact procedures and objects + +Message objects (@pxref{Messages}) have a method @t{mu:contacts}: + + @code{(mu:contacts [])} + +The @t{} is a symbol, one of @code{mu:to}, @code{mu:from}, +@code{mu:cc} or @code{mu:bcc}. This will then get the contact objects for the +contacts of the corresponding type. If you leave out the contact-type (or +specify @t{#t} for it, you will get a list of @emph{all} contact objects for +the message. + +A contact object (@code{}) has two methods: +@itemize +@item @code{mu:name} returns the name of the contact, or #f if there is none +@item @code{mu:email} returns the e-mail address of the contact, or #f if there is none +@end itemize + +Let's get a list of all names and e-mail addresses in the 'To:' field, of +messages matching 'book': + +@lisp +(use-modules (mu)) +(mu:initialize) +(mu:for-each-message + (lambda (msg) + (for-each + (lambda (contact) + (format #t "~a => ~a\n" + (or (mu:email contact) "") (or (mu:name contact) "no-name"))) + (mu:contacts msg mu:contact:to))) + "book") +@end lisp + +This shows what the methods do, but for many uses, it would be more useful to +have each of the contacts only show up @emph{once} - for that, please refer to +@xref{All contacts}. + +@node All contacts +@section All contacts + +Sometimes you may want to inspect @emph{all} the different contacts in the +@t{mu} database. This is useful, for instance, when exporting contacts to some +external format that can then be important in an e-mail program. + +To enable this, there is the procedure @code{mu:for-each-contact}, defined as + + @code{(mu:for-each-contact procedure [search-expression])}. + +This will aggregate the unique contacts from @emph{all} messages matching +@t{} (when it is left empty, it will match all messages in +the database), and execute @t{procedure} for each of them. + +The @t{procedure} receives an object of the type @t{}, +which is a @emph{subclass} of the @t{} class discussed in +@xref{Contact procedures and objects}. @t{} objects +expose the following additional methods: + +@itemize +@item @code{(mu:frequency )}: returns the @emph{number of times} this contact occurred in +one of the address fields +@item @code{(mu:last-seen )}: returns the @emph{most recent time} the contact was +seen in one of the address fields, as a @t{time_t} value +@end itemize + +The method assumes an e-mail address is unique for a certain contact; if a +certain e-mail address occurs with different names, it uses the most recent +non-empty name. + +@node Utility procedures +@section Utility procedures + +To make dealing with contacts even easier, there are a number of utility +procedures that can save you a bit of typing. + +For converting contacts to some textual form, there is @code{(mu:contact->string + format)}, which takes a contact and returns a text string with +the given format. Currently supported formats are @t{"org-contact}, @t{"mutt-alias"}, +@t{"mutt-ab"}, @t{"wanderlust"} and @t{"plain"}. + + +@node Example - mutt export +@section Example - mutt export + +Let's see how we could export the addresses in the @t{mu} database to the +addressbook format of the venerable +@t{mutt}@footnote{@url{http://www.mutt.org/}} e-mail client. + +The addressbook format that @t{mutt} uses is a sequence of lines that look +something like: +@verbatim +alias [] "<" ">" +@end verbatim + +@t{mu guile} provides the procedure @code{(mu:contact->string +format)} that we can use to do the conversion. + +We may want to focus on people with whom we have frequent correspondence; so +we may want to limit ourselves to people we have seen at least 10 times in the +last year. + +It is a bit hard to @emph{guess} the nick name for e-mail contacts, but +@code{mu:contact->string} tries something based on the name. You can always +adjust them later by hand, obviously. + +@lisp +#!/bin/sh +exec guile -s $0 $@ +!# + +(use-modules (mu)) +(mu:initialize) + +;; Get a list of contacts that were seen at least 20 times since 2010 +(define (selected-contacts) + (let ((addrs '()) + (start (car (mktime (car (strptime "%F" "2010-01-01"))))) + (minfreq 20)) + (mu:for-each-contact + (lambda (contact) + (if (and (mu:email contact) + (>= (mu:frequency contact) minfreq) + (>= (mu:last-seen contact) start)) + (set! addrs (cons contact addrs))))) + addrs)) + +(for-each + (lambda (contact) + (format #t "~a\n" (mu:contact->string contact "mutt-alias"))) + (selected-contacts)) +@end lisp + +This simple program could be improved in many ways; this is left as an +exercise to the reader. + +@node Attachments and other parts +@chapter Attachments and other parts + +To deal with @emph{attachments}, or, more in general @emph{MIME-parts}, there +is the @t{mu part} module. + +@menu +* Parts and their methods:: +* Attachment example:: +@end menu + +@node Parts and their methods +@section Parts and their methods +The module defines the @code{} class, and adds two methods to +@code{} objects: +@itemize +@item @code{(mu:parts msg)} - returns a list @code{} objects, one for +each MIME-parts in the message. +@item @code{(mu:attachments msg)} - like @code{parts}, but only list those MIME-parts +that look like proper attachments. +@end itemize + +A @code{} object exposes a few methods to get information about the +part: +@itemize +@item @code{(mu:name )} - returns the file name of the mime-part, or @code{#f} if +there is none. +@item @code{(mu:mime-type )} - returns the mime-type of the mime-part, or @code{#f} +if there is none. +@item @code{(mu:size )} - returns the size in bytes of the mime-part +@end itemize + +@c Then, we may want to save the part to a file; this can be done using either: +@c @itemize +@c @item @code{(mu:save part )} - save a part to a temporary file, return the file +@c name@footnote{the temporary filename is a predictable procedure of (user-id, +@c msg-path, part-index)} +@c @item @code{(mu:save-as )} - save part to file at path +@c @end itemize + +@node Attachment example +@section Attachment example + +Let's look at some small example. Let's get a list of the biggest attachments +in messages about Luxemburg: + +@lisp +#!/bin/sh +exec guile -s $0 $@ +!# + +(use-modules (mu)) +(mu:initialize) + +(define (all-attachments expr) + "Return a list of (name . size) for all attachments in messages +matching EXPR." + (let ((pairs '())) + (mu:for-each-message + (lambda (msg) + (for-each + (lambda (att) ;; add (filename . size) to the list + (set! pairs (cons (cons (mu:name att) (or (mu:size att) 0)) pairs))) + (mu:attachments msg))) + expr) + pairs)) + +(for-each + (lambda (att) + (format #t "~a: ~,1fKb\n" + (car att) (exact->inexact (/ (cdr att) 1024)))) + (sort (all-attachments "Luxemburg") + (lambda (att1 att2) + (< (cdr att1) (cdr att2))))) +@end lisp + +As an exercise for the reader, you might want to re-rewrite the +@code{all-attachments} in terms of @code{mu:message-list}, which would +probably be a bit more elegant. + + +@node Statistics +@chapter Statistics + +@t{mu-guile} offers some convenience procedures to determine various statistics +about the messages in the database. + +@menu +* Basics:: @code{mu:count}, @code{mu:average}, ... +* Tabulating values:: @code{mu:tabulate} +* Most frequent values:: @code{mu:top-n-most-frequent} +@end menu + +@node Basics +@section Basics + +Let's look at some of the basic statistical operations available, in an +interactive session: +@example +GNU Guile 2.0.5.123-4bd53 +Copyright (C) 1995-2012 Free Software Foundation, Inc. + +Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. +This program is free software, and you are welcome to redistribute it +under certain conditions; type `,show c' for details. + +Enter `,help' for help. +scheme@@(guile-user)> ;; load modules, initialize mu +scheme@@(guile-user)> (use-modules (mu) (mu stats)) +scheme@@(guile-user)> (mu:initialize) +scheme@@(guile-user)> +scheme@@(guile-user)> ;; count the number of messages with 'hello' in their subject +scheme@@(guile-user)> (mu:count "subject:hello") +$1 = 162 +scheme@@(guile-user)> ;; average the size of messages with hello in their subject +scheme@@(guile-user)> (mu:average mu:size "subject:hello") +$2 = 34597733/81 +scheme@@(guile-user)> (exact->inexact $2) +$3 = 427132.506172839 +scheme@@(guile-user)> ;; calculate the correlation between message size and +scheme@@(guile-user)> ;; subject length +scheme@@(guile-user)> (mu:correl mu:size (lambda (msg) + (string-length (mu:subject msg))) "subject:hello") +$5 = -0.10804368622292 +scheme@@(guile-user)> +@end example + +@node Tabulating values +@section Tabulating values + +@code{(mu:tabulate [])} applies @t{} to each +message matching @t{} (leave empty to match @emph{all} messages), +and returns a associative list (a list of pairs) with each of the different +results of @t{} and their frequencies. For fields that contain lists +of values (such as address-fields), each of the values in the list is added +separately. + +@subsection Example: messages per weekday + +We demonstrate @code{mu:tabulate} with an example. Suppose we want to know how +many messages we receive per weekday: + +@lisp +#!/bin/sh +exec guile -s $0 $@ +!# + +(use-modules (mu) (mu stats) (mu plot)) +(mu:initialize) + +;; create a list like (("Sun" . 13) ("Mon" . 23) ...) +(define weekday-table + (mu:weekday-numbers->names + (sort + (mu:tabulate + (lambda (msg) + (tm:wday (localtime (mu:date msg))))) + (lambda (a b) (< (car a) (car b)))))) + +(for-each + (lambda (elm) + (format #t "~a: ~a\n" (car elm) (cdr elm))) + weekday-table) +@end lisp + + +The procedure @code{weekday-table} uses @code{mu:tabulate-message} to get the +frequencies per hour -- this returns a list of pairs: +@verbatim +((5 . 2339) (0 . 2278) (4 . 2800) (2 . 3184) (6 . 1856) (3 . 2833) (1 . 2993)) +@end verbatim + +We sort these pairs by the day number, and then apply +@code{mu:weekday-numbers->names}, which takes the list, and returns a list +where the day numbers are replace by there abbreviated name (in the current +locale). Note, there is also @code{mu:month-numbers->names}. + +The script then outputs these numbers in the following form: + +@verbatim +Sun: 2278 +Mon: 2993 +Tue: 3184 +Wed: 2833 +Thu: 2800 +Fri: 2339 +Sat: 1856 +@end verbatim + +Clearly, Saturday is a slow day for e-mail... + +@node Most frequent values +@section Most frequent values + +In the above example, the number of values is small (the seven weekdays); +however, in many cases there can be many different values (for example, all +different message subjects), many of which may not be very interesting -- all +we need to know is the top-10 of most frequently seen values. + +This is fairly easy to achieve using @code{mu:tabulate} -- to get the top-10 +subjects@footnote{this requires the @code{(srfi srfi-1)}-module}, we can use +something like this: +@lisp +(take + (sort + (mu:tabulate mu:subject) + (lambda (a b) (> (cdr a) (cdr b)))) + 10) +@end lisp + +If this is not short enough, @t{mu-guile} offers a convenience procedure to do +this: @code{mu:top-n-most-frequent}. For example, to get the top-10 people we +sent mail to most often: + +@lisp +(mu:top-n-most-frequent mu:to 10 "maildir:/sent") +@end lisp + +Can't make it much easier than that! + + +@node Plotting data +@chapter Plotting data + +You can plot the results in the format produced by @code{mu:tabulate} with the +@t{(mu plot)} module, an experimental module that requires the +@t{gnuplot}@footnote{@url{http://www.gnuplot.info/}} program to be installed +on your system. + +The @code{mu:plot-histogram} procedure takes the following arguments: + +@code{(mu:plot-histogram <x-label> <y-label> [<want-ascii>])} + +Here, @code{<data>} is a table of data in the format that @code{mu:tabulate} +produces. @code{<title>}, @code{<x-label>} and @code{<y-lablel>} are, +respectively, the title of the graph, and the labels for X- and +Y-axis. Finally, if you pass @t{#t} for the final @code{<want-ascii>} +parameter, a plain-text rendering of the graph will be produced; otherwise, a +graphical window will be shown. + +An example should clarify how this works in practice; let's plot the number of +message per hour: + +@lisp +#!/bin/sh +exec guile -s $0 $@ +!# + +(use-modules (mu) (mu stats) (mu plot)) +(mu:initialize) + +(define (mail-per-hour-table) + (sort + (mu:tabulate + (lambda (msg) + (tm:hour (localtime (mu:date msg))))) + (lambda (x y) (< (car x) (car y))))) + +(mu:plot-histogram (mail-per-hour-table) "Mail per hour" "Hour" "Frequency") +@end lisp + +@cartouche +@verbatim + Mail per hour +Frequency + 1200 ++--+--+--+--+-+--+--+--+--+-+--+--+--+-+--+--+--+--+-+--+--+--+--++ + |+ + + + + + + "/tmp/fileHz7D2u" using 2:xticlabels(1) ******** + 1100 ++ *** +* + **** * * * + 1000 *+ * **** * +* + * * ****** **** * ** * * + 900 *+ * * ** **** * **** ** * +* + * * * ** * * ********* * ** ** * * + 800 *+ * **** ** * * * * ** * * ** ** * +* + 700 *+ *** **** * ** * * * * ** **** * ** ** * +* + * * * **** * * ** * * * * ** * **** ** ** * * + 600 *+ * **** * * * * ** * * * * ** * * * ** ** * +* + * * ** * * * * * ** * * * * ** * * * ** ** * * + 500 *+ * ** * * * * * ** * * * * ** * * * ** ** * +* + * * ** **** *** * * * ** * * * * ** * * * ** ** * * + 400 *+ * ** ** **** * * * * * ** * * * * ** * * * ** ** * +* + *+ *+**+**+* +*******+* +* +*+ *+**+* +*+ *+ *+**+* +*+ *+**+**+* +* + 300 ******************************************************************** + 0 1 2 3 4 5 6 7 8 910 11 12 1314 15 16 17 1819 20 21 22 23 + Hour +@end verbatim +@end cartouche + +@node Writing scripts +@chapter Writing scripts + +The @t{mu} program has built-in support for running guile-scripts, and comes +with a number of examples. + +You can get a list of all scripts with the @t{mu script} command: +@verbatim +$ mu script +Available scripts (use --verbose for details): + * find-dups: find duplicate messages + * msgs-count: count the number of messages matching some query + * msgs-per-day: graph the number of messages per day + * msgs-per-hour: graph the number of messages per hour + * msgs-per-month: graph the number of messages per month + * msgs-per-year: graph the number of messages per year + * msgs-per-year-month: graph the number of messages per year-month +@end verbatim + +You can then execute such a script by its name: +@verbatim +$ mu msgs-per-month --textonly --query=hello + + + Messages per month matching hello + + 240 ++-+-----+----+-----+-----+-----+----+-----+-----+-----+----+-----+-++ + | + + + + "/tmp/filewi9H0N" using 2:xticlabels(1) ****** | + 220 ++ * * ****** + | * * * * + 200 ++ * * * +* + | * * * * + 180 ++ ****** * * * +* + | * * * * * * + 160 ****** * * * * * +* + * * * * * * * * + * ******* * * * * ****** * * + 140 *+ ** * * * * * * ******** +* + * ** ******* * * * * * ** ** * + 120 *+ ** ** ******* * * * * ** ** +* + * ** ** ** * * * ******* ** ** * + 100 *+ ** ** ** * * * * ** ** ** +* + * + ** + ** + ** + * + * + + * + * + ** + ** + ** + * + 80 ********************************************************************** + Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec + Month +@end verbatim + +Please refer to the @t{mu-script} man-page for some details on writing your +own scripts. + + +@node Recipes +@appendix Recipes + +@itemize +@item Calculating the average length of subject-lines +@lisp +;; the average length of all our +(let ((len 0) (n 0)) + (mu:for-each-message + (lambda (msg) + (set! len (+ len (string-length (or (mu:subject msg) "")))) + (set! n (+ n 1)))) + (if (= n 0) 0 (/ len n))) + ;; this gives a rational, exact result; + ;; use exact->inexact to get decimals + +;; we we can make this short with the mu:average (with (mu stats)) +(mu:average (lambda (msg) (string-length (or (mu:subject msg) "")))) + + +@end lisp +@end itemize + +@node GNU Free Documentation License +@appendix GNU Free Documentation License + +@include fdl.texi +@bye diff --git a/guile/mu.scm b/guile/mu.scm new file mode 100644 index 0000000..08eae1f --- /dev/null +++ b/guile/mu.scm @@ -0,0 +1,318 @@ +;; Copyright (C) 2011-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +(define-module (mu) + :use-module (oop goops) + :use-module (ice-9 optargs) + :use-module (texinfo string-utils) + :export + ( ;; classes + <mu:message> + <mu:contact> + <mu:part> + ;; general +;; mu:initialize + ;; mu:initialized? + mu:log-warning + mu:log-message + mu:log-critical + ;; search funcs + mu:for-each-message + mu:for-each-msg + mu:message-list + ;; message funcs + mu:header + ;; message accessors + mu:field:bcc + mu:field:body-html + mu:field:body-txt + mu:field:cc + mu:field:date + mu:field:flags + mu:field:from + mu:field:maildir + mu:field:message-id + mu:field:path + mu:field:prio + mu:field:refs + mu:field:size + mu:field:subject + mu:field:tags + mu:field:timestamp + mu:field:to + ;; contact funcs + mu:name + mu:email + mu:contact->string + ;; + mu:for-each-contact + ;; + mu:contacts + ;; + ;; <mu:contact-with-stats> + mu:frequency + mu:last-seen + ;; parts + + <mu:part> + ;; message function + mu:attachments + mu:parts + ;; <mu:part> methods + mu:name + mu:mime-type + ;; size + ;; mu:save + ;; mu:save-as + )) + +;; this is needed for guile < 2.0.4 +(setlocale LC_ALL "") + +;; load the binary +(load-extension "libguile-mu" "mu_guile_init") +(load-extension "libguile-mu" "mu_guile_message_init") + +;; define some dummies so we don't get errors during byte compilation +(eval-when (compile) + (define mu:c:get-field) + (define mu:c:get-contacts) + (define mu:c:for-each-message) + (define mu:c:get-header) + (define mu:critical) + (define mu:c:log) + (define mu:message) + (define mu:c:log) + (define mu:warning) + (define mu:c:log) + (define mu:c:get-parts)) + +(define (mu:log-warning frm . args) + "Log FRM with ARGS at warning." + (mu:c:log mu:warning frm args)) + +(define (mu:log-message frm . args) + "Log FRM with ARGS at warning." + (mu:c:log mu:message frm args)) + +(define (mu:log-critical frm . args) + "Log FRM with ARGS at warning." + (mu:c:log mu:critical frm args)) + +(define-class <mu:message> () + (msg #:init-keyword #:msg)) ;; the MuMsg-smob we're wrapping + +(define-syntax define-getter + (syntax-rules () + ((define-getter method-name field) + (begin + (define-method (method-name (msg <mu:message>)) + (mu:c:get-field (slot-ref msg 'msg) field)) + (export method-name))))) + +(define-getter mu:bcc mu:field:bcc) +(define-getter mu:body-html mu:field:body-html) +(define-getter mu:body-txt mu:field:body-txt) +(define-getter mu:cc mu:field:cc) +(define-getter mu:date mu:field:date) +(define-getter mu:flags mu:field:flags) +(define-getter mu:from mu:field:from) +(define-getter mu:maildir mu:field:maildir) +(define-getter mu:message-id mu:field:message-id) +(define-getter mu:path mu:field:path) +(define-getter mu:priority mu:field:prio) +(define-getter mu:references mu:field:refs) +(define-getter mu:size mu:field:size) +(define-getter mu:subject mu:field:subject) +(define-getter mu:tags mu:field:tags) +(define-getter mu:timestamp mu:field:timestamp) +(define-getter mu:to mu:field:to) + +(define-method (mu:header (msg <mu:message>) (hdr <string>)) + "Get an arbitrary header HDR from message MSG; return #f if it does +not exist." + (mu:c:get-header (slot-ref msg 'msg) hdr)) + +(define* (mu:for-each-message func #:optional (expr #t) (maxresults -1)) + "Execute function FUNC for each message that matches mu search expression EXPR. +If EXPR is not provided, match /all/ messages in the store. MAXRESULTS +specifies the maximum of messages to return, or -1 (the default) for +no limit." + (mu:c:for-each-message + (lambda (msg) + (func (make <mu:message> #:msg msg))) + expr + maxresults)) + +;; backward-compatibility alias +(define mu:for-each-msg mu:for-each-message) + +(define* (mu:message-list #:optional (expr #t) (maxresults -1)) + "Return a list of all messages matching mu search expression +EXPR. If EXPR is not provided, return a list of /all/ messages in the +store. MAXRESULTS specifies the maximum of messages to return, or +-1 (the default) for no limit." + (let ((lst '())) + (mu:for-each-message + (lambda (m) + (set! lst (append! lst (list m)))) expr maxresults) + lst)) + +;; contacts +(define-class <mu:contact> () + (name #:init-value #f #:accessor mu:name #:init-keyword #:name) + (email #:init-value #f #:accessor mu:email #:init-keyword #:email)) + +(define-method (mu:contacts (msg <mu:message>) contact-type) + "Get all contacts for MSG of the given CONTACT-TYPE. MSG is of type <mu-message>, +while contact type is either `mu:contact:to', `mu:contact:cc', +`mu:contact:from' or `mu:contact:bcc' to get the corresponding type of +contacts, or #t to get all. + +Returns a list of <mu-contact> objects." + (map (lambda (pair) ;; a pair (na . addr) + (make <mu:contact> #:name (car pair) #:email (cdr pair))) + (mu:c:get-contacts (slot-ref msg 'msg) contact-type))) + +(define-method (mu:contacts (msg <mu:message>)) + "Get contacts of all types for message MSG as a list of <mu-contact> +objects." + (mu:contacts msg #t)) + +(define-class <mu:contact-with-stats> (<mu:contact>) + (tstamp #:init-value 0 #:accessor mu:timestamp #:init-keyword #:timestamp) + (last-seen #:init-value 0 #:accessor mu:last-seen) + (freq #:init-value 1 #:accessor mu:frequency)) + +(define* (mu:for-each-contact proc #:optional (expr #t)) + "Execute PROC for each contact. PROC receives a <mu-contact> instance +as parameter. If EXPR is specified, only consider contacts in messages +matching EXPR." + (let ((c-hash (make-hash-table 4096))) + (mu:for-each-message + (lambda (msg) + (for-each + (lambda (ct) + (let ((ct-ws (make <mu:contact-with-stats> + #:name (mu:name ct) + #:email (mu:email ct) + #:timestamp (mu:date msg)))) + (update-contacts-hash c-hash ct-ws))) + (mu:contacts msg #t))) + expr) + (hash-for-each ;; c-hash now contains a map of email->contact + (lambda (email ct-ws) (proc ct-ws)) c-hash))) + +(define-method (update-contacts-hash c-hash (nc <mu:contact-with-stats>)) + "Update the contacts hash with a new and/or existing contact." + ;; xc: existing-contact, nc: new contact + (let ((xc (hash-ref c-hash (mu:email nc)))) + (if (not xc) ;; no existing contact with this email address? + (hash-set! c-hash (mu:email nc) nc) ;; store the new contact. + ;; otherwise: + (begin + ;; 1) update the frequency for the existing contact + (set! (mu:frequency xc) (1+ (mu:frequency xc))) + ;; 2) update the name if the new one is not empty and its timestamp is newer + ;; in that case, also update the timestamp + (if (and (mu:name nc) (> (string-length (mu:name nc))) + (> (mu:timestamp nc) (mu:timestamp xc))) + (set! (mu:name xc) (mu:name nc)) + (set! (mu:timestamp xc) (mu:timestamp nc))) + ;; 3) update last-seen with timestamp, if x's timestamp is newer + (if (> (mu:timestamp nc) (mu:last-seen xc)) + (set! (mu:last-seen xc) (mu:timestamp nc))) + ;; okay --> now xc has been updated; but it back in the hash + (hash-set! c-hash (mu:email xc) xc))))) + +(define-method (mu:contact->string (contact <mu:contact>) (form <string>)) + "Convert a contact to a string in format FORM, which is a string, +either \"org-contact\", \"mutt-alias\", \"mutt-ab\", +\"wanderlust\", \"quoted\" \"plain\"." + (let* ((name (mu:name contact)) (email (mu:email contact)) + (nick ;; simplistic nick guessing... + (string-map + (lambda(kar) + (if (char-alphabetic? kar) kar #\_)) + (string-downcase (or name email))))) + (cond + ((string= form "plain") + (format #f "~a~a~a" (or name "") (if name " " "") email)) + ((string= form "org-contact") + (format #f "* ~s\n:PROPERTIES:\n:EMAIL:~a\n:NICK:~a\n:END:" + (or name email) email nick)) + ((string= form "wanderlust") + (format #f "~a ~s ~s" + nick (or name email) email)) + ((string= form "mutt-alias") + (format #f "alias ~a ~a <~a>" + nick (or name email) email)) + ((string= form "mutt-ab") + (format #f "~a\t~a\t" + email (or name ""))) + ((string= form "quoted") + (string-append + "\"" + (escape-special-chars + (string-append + (if name + (format #f "\"~a\" " name) + "") + (format #f "<~a>" email)) + "\"" #\\) + "\"")) + (else (error "Unsupported format"))))) + +;; message parts + + +(define-class <mu:part> () + (msgpath #:init-value #f #:init-keyword #:msgpath) + (index #:init-value #f #:init-keyword #:index) + (name #:init-value #f #:getter mu:name #:init-keyword #:name) + (mime-type #:init-value #f #:getter mu:mime-type #:init-keyword #:mime-type) + (size #:init-value 0 #:getter mu:size #:init-keyword #:size)) + +(define-method (get-parts (msg <mu:message>) (files-only <boolean>)) + "Get the part for MSG as a list of <mu:part> objects; if FILES-ONLY is #t, +only get the part with file names." + (map (lambda (part) + (make <mu:part> + #:msgpath (list-ref part 0) + #:index (list-ref part 1) + #:name (list-ref part 2) + #:mime-type (list-ref part 3) + #:size (list-ref part 4))) + (mu:c:get-parts (slot-ref msg 'msg) files-only))) + +(define-method (mu:attachments (msg <mu:message>)) + "Get the attachments for MSG as a list of <mu:part> objects." + (get-parts msg #t)) + +(define-method (mu:parts (msg <mu:message>)) + "Get the MIME-parts for MSG as a list of <mu-part> objects." + (get-parts msg #f)) + +;; (define-method (mu:save (part <mu:part>)) +;; "Save PART to a temporary file, and return the file name. If the +;; part had a filename, the temporary file's file name will be just that; +;; otherwise a name is made up." +;; (mu:save-part (slot-ref part 'msgpath) (slot-ref part 'index))) + +;; (define-method (mu:save-as (part <mu:part>) (filepath <string>)) +;; "Save message-part PART to file system path PATH." +;; (copy-file (save part) filepath)) diff --git a/guile/mu/Makefile.am b/guile/mu/Makefile.am new file mode 100644 index 0000000..f531822 --- /dev/null +++ b/guile/mu/Makefile.am @@ -0,0 +1,28 @@ +## Copyright (C) 2008-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +# FIXME: GUILE_SITEDIR would be better, but that +# breaks 'make distcheck' +scmdir=${prefix}/share/guile/site/2.2/mu/ + +scm_DATA= \ + stats.scm \ + plot.scm \ + script.scm + +EXTRA_DIST=$(scm_DATA) diff --git a/guile/mu/README b/guile/mu/README new file mode 100644 index 0000000..634ad8b --- /dev/null +++ b/guile/mu/README @@ -0,0 +1,207 @@ +* OUTDATED * + +* README + +** What is muile? + + `muile' is a little experiment/toy using the equally experimental mu guile + bindings, to be found in libmuguile/ in the top-level source directory. + + `guile'[1] is an interpreter/library for the Scheme programming language[2], + specifically meant for extending other programs. It is, in fact, the + official GNU language for doing so. 'muile' requires guile 2.x to get the full + support. + + Older versions may not support e.g. the 'mu-stats.scm' things discussed below. + + The combination of mu + guile is called `muile', and allows you to write + little Scheme-programs to query the mu-database, or inspect individual + messages. It is still in an experimental stage, but useful already. + +** How do I get it? + + The git-version and the future 0.9.7 version of mu will automatically build + muile if you have guile. I've been using guile 2.x from git, but installing + the 'guile-1.8-dev' package (Ubuntu/Debian) should do the trick. (I only did + very minimal testing with guile 1.8 though). + + Then, configure mu. The configure output should tell you about whether guile + was found (and where). If it's found, build mu, and toys/muile should be + created, as well. + +** What can I do with it? + + Go to toys/muile and start muile. You'll end up with a guile-shell where you + can type scheme [1], it looks something like this (for guile 2.x): + + ,---- + | scheme@(guile-user)> + `---- + + Now, let's load a message (of course, replace with a message on your system): + + ,---- + | scheme@(guile-user)> (define msg (mu:msg:make-from-file "/home/djcb/Maildir/cur/12131e7b20a2:2,S")) + `---- + + This defines a variable 'msg', which holds some message on your file + system. It's now easy to inspect this message: + + ,---- + | scheme@(guile-user)> (define msg (mu:msg:make-from-file "/home/djcb/Maildir/cur/12131e7b20a2:2,S")) + `---- + + Now, we can inspect this message a bit: + ,---- + | scheme@(guile-user)> (mu:msg:subject msg) + | $1 = "See me in bikini :-)" + | scheme@(guile-user)> (mu:msg:flags msg) + | $2 = (mu:attach mu:unread) + `---- + + and so on. Note, it's probably easiest to explore the various mu: methods + using autocompletion; to enable that make sure you have + + + ,---- + | (use-modules (ice-9 readline)) + | (activate-readline) + `---- + + in your ~/.guile configuration. + +** does this tool have some parameters? + + Yes, there is --muhome to set a non-default place for the message database + (see the documentation on --muhome in the mu-find manpage). + + And there is --msg=<path> where you specify some particular message file; + it will be available as 'mu:current-msg' in the guile (muile) environment. For + example: + + ,---- + | ./muile --msg=~/Maildir/inbox/cur/1311310172_1234:2,S + | [...] + | scheme@(guile-user)> mu:current-msg + | $1 = #<msg /home/djcb/Maildir/inbox/cur/1311310172_1234:2,S> + | scheme@(guile-user)> (mu:msg:size mu:current-msg) + | $2 = 7206 + `---- + +** What about searching messages in the database? + + That's easy, too - it does require a little more scheme knowledge. For + searching messages there is the mu:store:for-each function, which takes two + arguments; the first argument is a function that will be called for each + message found. The optional second argument is the search expression (following + 'mu find' syntax); if don't provide the argument, all messages match. + + So how does this work in practice? Let's see I want to see the subject and + sender for messages about milk: + + ,---- + | (mu:store:for-each (lambda(msg) (format #t "~s ~s\n" (mu:msg:from msg) (mu:msg:subject msg))) "milk") + `---- + + or slightly more readable: + + ,---- + | (mu:store:for-each + | (lambda(msg) + | (format #t "~s ~s\n" (mu:msg:from msg) (mu:msg:subject msg))) + | "milk") + `---- + + As you can see, I provide an anonymous ('lambda') function which will be + called for each message matching 'milk'. Admittedly, this requires a bit of + Scheme-knowledge... but this time is good as any to learn this nice + language. + + +** Can I do some statistics on my messages? + + Yes you can. In fact, it's pretty easy. If you load (in the muile/ directory) + the file 'mu-stats.scm': + + ,---- + | (load "mu-stats.scm") + `---- + + you'll get a bunch of functions (with names starting with 'mu:stats') to make + this very easy. Let's see, suppose I want to see how many messages I get per + weekday: + + ,---- + | scheme@(guile-user)> (mu:stats:per-weekday) + | $1 = ((0 . 2255) (1 . 2788) (2 . 2868) (3 . 2599) (4 . 2629) (5 . 2287) (6 . 1851)) + `---- + + Note, Sunday=0, Monday=1 and so on. Apparently, I get/send most of e-mail on + Tuesdays, and least on Saturday. + + And note that mu:stats:per-weekdays takes an optional search expression + argument, to limit the results to messages matching that, e.g., to only + consider messages related to emacs during this year: + + ,---- + | scheme@(guile-user)> (mu:stats:per-weekday "emacs date:2011..now") + | $8 = ((0 . 54) (1 . 22) (2 . 46) (3 . 47) (4 . 39) (5 . 54) (6 . 50)) + `---- + + There's also 'mu:stats:per-month', 'mu:stats:per-year', 'mu:stats:per-hour'. + I learnt that during 3-4am I sent/receive only about a third of what I sent + during 11-12pm. + +** What about getting the top-10 people in the To:-field? + + Easy. + + ,---- + | scheme@(guile-user)> (mu:stats:top-n-to) + | $1 = ((("Abc" "myself@example.com") . 4465) (("Def" "somebodyelse@example.com") . 2114) + | (and so on) + `---- + + I've changed the names a bit to protect the innocent, but what the function + does is return a list of pairs of + + (<name> <email>) . <frequency> + + descending in order of frequency. Note, 'mu:stats:top-n-to' takes two + optional arguments - first the 'n' in top-n (default is 10), and seconds as + search expression to limit the messages considered. + + There are also the functions 'mu:stats:top-n-subject' and + 'mu:stats:top-n-from' which do the same, mutatis mutandis, and it's quite + easy to add your own (see the mu-stats.scm for examples) + +** What about showing the results in a table? + + Even easier. Try: + + ,---- + | (mu:stats:table (mu:stats:top-n-to)) + `---- + + or + + ,---- + | (mu:stats:table (mu:stats:per-weekday)) + `---- + + You can also export the table: + + ,---- + | (mu:stats:export (mu:stats:per-weekday)) + `---- + + which will create a temporary file with the results, for further processing + in e.g. 'R' or 'gnuplot'. + + +[1] http://www.gnu.org/s/guile/ +[2] http://en.wikipedia.org/wiki/Scheme_(programming_language) + +# Local Variables: +# mode: org; org-startup-folded: nil +# End: diff --git a/guile/mu/contact.scm b/guile/mu/contact.scm new file mode 100644 index 0000000..843d9c4 --- /dev/null +++ b/guile/mu/contact.scm @@ -0,0 +1,4 @@ +(define-module (mu contact) :use-module(mu)) +(display "(mu contact) is deprecated, please remove from (use-modules ...)") +(newline) + diff --git a/guile/mu/message.scm b/guile/mu/message.scm new file mode 100644 index 0000000..bc9b27a --- /dev/null +++ b/guile/mu/message.scm @@ -0,0 +1,4 @@ +(define-module (mu message) :use-module (mu)) +(display "(mu message) is deprecated, please remove from (use-modules ...)") +(newline) + diff --git a/guile/mu/part.scm b/guile/mu/part.scm new file mode 100644 index 0000000..f9b9cd3 --- /dev/null +++ b/guile/mu/part.scm @@ -0,0 +1,4 @@ +(define-module (mu part) :use-module (mu)) +(display "(mu part) is deprecated, please remove from (use-modules ...)") +(newline) + diff --git a/guile/mu/plot.scm b/guile/mu/plot.scm new file mode 100644 index 0000000..adeb80f --- /dev/null +++ b/guile/mu/plot.scm @@ -0,0 +1,80 @@ +;; +;; Copyright (C) 2011-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +(define-module (mu plot) + :use-module (mu) + :use-module (ice-9 popen) + :export ( mu:plot ;; alias for mu:plot-histogram + mu:plot-histogram + )) + +(define (export-pairs pairs) + "Write a temporary file with the list of PAIRS in table format, and +return the file name." + (let* ((datafile (tmpnam)) + (output (open datafile (logior O_CREAT O_WRONLY) #O0600))) + (for-each + (lambda(pair) + (display (format #f "~a ~a\n" (car pair) (cdr pair)) output)) + pairs) + (close output) + datafile)) + +(define (find-program-in-path prog) + "Find exutable program PROG in PATH; return the full path, or #f if +not found." + (let* ((path (parse-path (getenv "PATH"))) + (progpath (search-path path prog))) + (if (not progpath) + #f + (if (access? progpath X_OK) ;; is + progpath + #f)))) + +(define* (mu:plot-histogram data title x-label y-label + #:optional (output "dumb") (extra-gnuplot-opts '())) + "Plot DATA with TITLE, X-LABEL and X-LABEL using the gnuplot +program. DATA is a list of cons-pairs (X . Y). + + OUTPUT is a string +that determines the type of output that gnuplot produces, depending on +the system. Which options are available depends on the particulars for +the gnuplot installation, but typical examples would be \"dumb\" for +text-only display, \"wxterm\" to write to a graphical window, or +\"png\" to write a PNG-image to stdout. + +EXTRA-GNUPLOT-OPTS is a list +of any additional options for gnuplot." + (if (not (find-program-in-path "gnuplot")) + (error "cannot find 'gnuplot' in path")) + (let ((datafile (export-pairs data)) + (gnuplot (open-pipe "gnuplot -p" OPEN_WRITE))) + (display (string-append + "reset\n" + "set term " (or output "dumb") "\n" + "set title \"" title "\"\n" + "set xlabel \"" x-label "\"\n" + "set ylabel \"" y-label "\"\n" + "set boxwidth 0.9\n" + (string-join extra-gnuplot-opts "\n") + "plot \"" datafile "\" using 2:xticlabels(1) with boxes fs solid\n") + gnuplot) + (close-pipe gnuplot))) + +;; backward compatibility +(define mu:plot mu:plot-histogram) diff --git a/guile/mu/script.scm b/guile/mu/script.scm new file mode 100644 index 0000000..3a62948 --- /dev/null +++ b/guile/mu/script.scm @@ -0,0 +1,57 @@ +;; Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +(define-module (mu script) + :export (mu:run-stats)) + +(use-modules (ice-9 getopt-long) (ice-9 optargs) (ice-9 popen) (ice-9 format)) +(use-modules (mu) (mu stats) (mu plot)) + +(define (help-and-exit) + "Show some help." + (display + (string-append "usage: script [--help] [--textonly] " + "[--muhome=<muhome>] [--query=<query>") + (newline)) + (exit 0)) + +(define (mu:run-stats args func) + "Run some statistics function. +Interpret argument-list ARGS (like command-line +arguments). Possible arguments are: + --help (show some help and exit) + --muhome (path to alternative mu home directory) + --output (a string describing the output, e.g. \"dumb\", \"png\" \"wxt\") + searchexpr (a search query) +then call FUNC with args SEARCHEXPR and OUTPUT." + (setlocale LC_ALL "") + (let* ((optionspec '((muhome (value #t)) + (query (value #t)) + (output (value #f)) + (help (single-char #\h) (value #f)))) + (options (getopt-long args optionspec)) + (query (option-ref options 'query #f)) + (help (option-ref options 'help #f)) + (output (option-ref options 'output #f)) + (muhome (option-ref options 'muhome #f)) + (restargs (option-ref options '() #f))) + (if help (help-and-exit)) + (mu:initialize muhome) + (func (or query "") output))) + +;; Local Variables: +;; mode: scheme +;; End: diff --git a/guile/mu/stats.scm b/guile/mu/stats.scm new file mode 100644 index 0000000..90ab836 --- /dev/null +++ b/guile/mu/stats.scm @@ -0,0 +1,165 @@ +;; +;; Copyright (C) 2011-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +(define-module (mu stats) + :use-module (oop goops) + :use-module (mu) + :use-module (srfi srfi-1) + :use-module (ice-9 i18n) + :use-module (ice-9 r5rs) + :export ( mu:tabulate + mu:top-n-most-frequent + mu:count + mu:average + mu:stddev + mu:correl + mu:max + mu:min + mu:weekday-numbers->names + mu:month-numbers->names)) + + +(define* (mu:tabulate func #:optional (expr #t)) + "Execute FUNC for each message matching EXPR, and return an alist +with maps each result of FUNC to its frequency. If the result of FUNC +is a list, add each of its values separately. + FUNC is a function takes a <mu-message> instance as its argument. For +example, to tabulate messages by weekday, one could use: + (mu:tabulate (lambda(msg) (tm:wday (localtime (date msg))))), and +get back a list like + ((1 . 2) (2 . 5)(3 . 4)(4 . 4)(5 . 12)(6 . 7)(7. 2))." + (let* ((table '()) + ;; func to add a value to our table + (update-table + (lambda (val) + (let ((old-freq (or (assoc-ref table val) 0))) + (set! table (assoc-set! table val (1+ old-freq))))))) + (mu:for-each-message + (lambda(msg) + (let ((val (func msg))) + (if (list? val) + (for-each update-table val) + (update-table val)))) + expr) + table)) + +(define* (top-n func less n #:optional (expr #t)) + "Take the results of (mu:tabulate FUNC EXPR), sort using LESS (a +function taking two arguments A and B (cons cells, (VAL . FREQ)), and +returns #t if A < B, #f otherwise), and then take the first N." + (take (sort (mu:tabulate func expr) less) n)) + +(define* (mu:top-n-most-frequent func n #:optional (expr #t)) + "Take the results of (mu:tabulate FUNC EXPR), and return the N items with the highest frequency." + (top-n func (lambda (a b) (> (cdr a) (cdr b))) n expr)) + +(define* (mu:count #:optional (expr #t)) + "Count the number of messages matching EXPR. If EXPR is not +provided, match /all/ messages." + (let ((num 0)) + (mu:for-each-message + (lambda (msg) (set! num (1+ num))) + expr) + num)) + +(define (average lst) + "Calculate the average of a list LST of numbers, or #f if undefined." + (if (null? lst) + #f + (/ (apply + lst) (length lst)))) + +(define (stddev lst) + "Calculate the standard deviation of a list LST of numbers or #f if +undefined." + (let* ((avg (average lst)) + (sosq (if avg + (apply + (map (lambda (x)(* (- x avg) (- x avg))) lst))))) + (if sosq + (sqrt (/ sosq (length lst)))))) + + +(define* (mu:average func #:optional (expr #t)) + "Get the average value of FUNC applied to all messages matching +EXPR (or #t for all). Returns #f if undefined." + (average (map func (mu:message-list expr)))) + +(define* (mu:stddev func #:optional (expr #t)) + "Get the standard deviation the the values of FUNC applied to all +messages matching EXPR (or #t for all). This is the 'population' stddev, not the 'sample' stddev. Returns #f if undefined." + (stddev (map func (mu:message-list expr)))) + +(define* (mu:max func #:optional (expr #t)) + "Get the maximum value of FUNC applied to all messages matching +EXPR (or #t for all). Returns #f if undefined." + (apply max (map func (mu:message-list expr)))) + +(define* (mu:min func #:optional (expr #t)) + "Get the minimum value of FUNC applied to all messages matching +EXPR (or #t for all). Returns #f if undefined." + (apply min (map func (mu:message-list expr)))) + + +(define (correl lst) + "Calculate Pearson's correlation coefficient for a list LST of cons +pair, where the car and cdr of the pairs are values from data set 1 +and 2, respectively." + (let ((n (length lst)) + (sx (apply + (map car lst))) + (sy (apply + (map cdr lst))) + (sxy (apply + (map (lambda (cell) (* (car cell) (cdr cell))) lst))) + (sxx (apply + (map (lambda (cell) (* (car cell) (car cell))) lst))) + (syy (apply + (map (lambda (cell) (* (cdr cell) (cdr cell))) lst)))) + (/ (- (* n sxy) (* sx sy)) + (sqrt (* (- (* n sxx) (* sx sx)) (- (* n syy) (* sy sy))))))) + +(define* (mu:correl func1 func2 #:optional (expr #t)) + "Determine Pearson's correlation coefficient between the value for +functions FUNC1 and FUNC2 to all messages matching EXPR (or #t for +all). Returns #f if undefined." + (let ((data + (map (lambda (msg) + (cons (func1 msg) (func2 msg))) + (mu:message-list expr)))) + (if data (correl data) #f))) + + +;; a list of abbreviated, localized day names +(define day-names + (map locale-day-short (iota 7 1))) + +(define (mu:weekday-numbers->names table) + "Convert a list of pairs with the car denoting a day number (0-6) +into a list of pairs with the car replaced by the corresponding day +name (abbreviated) for the current locale." + (map + (lambda (pair) + (cons (list-ref day-names (car pair)) (cdr pair))) + table)) + +;; a list of abbreviated, localized month names +(define month-names + (map locale-month-short (iota 12 1))) + +(define (mu:month-numbers->names table) + "Convert a list of pairs with the car denoting a month number (0-11) +into a list of pairs with the car replaced by the corresponding day +name (abbreviated)." + (map + (lambda (pair) + (cons (list-ref month-names (car pair)) (cdr pair))) + table)) diff --git a/guile/scripts/Makefile.am b/guile/scripts/Makefile.am new file mode 100644 index 0000000..c846596 --- /dev/null +++ b/guile/scripts/Makefile.am @@ -0,0 +1,29 @@ +## Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +EXTRA_DIST= \ + msgs-count.scm \ + msgs-per-year.scm \ + msgs-per-hour.scm \ + msgs-per-month.scm \ + msgs-per-day.scm \ + msgs-per-year-month.scm \ + find-dups.scm + +muguiledistscriptdir = $(pkgdatadir)/scripts/ +muguiledistscript_SCRIPTS = $(EXTRA_DIST) diff --git a/guile/scripts/find-dups.scm b/guile/scripts/find-dups.scm new file mode 100755 index 0000000..778acfe --- /dev/null +++ b/guile/scripts/find-dups.scm @@ -0,0 +1,119 @@ +#!/bin/sh +exec guile -e main -s $0 $@ +!# +;; +;; Copyright (C) 2013-2015 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +;; INFO: find duplicate messages +;; INFO: options: +;; INFO: --muhome=<muhome>: path to mu home dir +;; INFO: --delete: delete all but the first one (experimental, be careful!) + +(use-modules (mu) (mu script) (mu stats)) +(use-modules (ice-9 getopt-long) (ice-9 optargs) + (ice-9 popen) (ice-9 format) (ice-9 rdelim)) + +(define (md5sum path) + (let* ((port (open-pipe* OPEN_READ "md5sum" path)) + (md5 (read-delimited " " port))) + (close-pipe port) + md5)) + +(define (find-dups delete expr) + (let ((id-table (make-hash-table 20000))) + ;; fill the hash with <msgid-size> => <list of paths> + (mu:for-each-message + (lambda (msg) + (let* ((id (format #f "~a-~d" (mu:message-id msg) + (mu:size msg))) + (lst (hash-ref id-table id))) + (if lst + (set! lst (cons (mu:path msg) lst)) + (set! lst (list (mu:path msg)))) + (hash-set! id-table id lst))) + expr) + ;; list all the paths with multiple elements; check the md5sum to + ;; make 100%-minus-ε sure they are really the same file. + (hash-for-each + (lambda (id paths) + (if (> (length paths) 1) + (let ((hash (make-hash-table 10))) + (for-each + (lambda (path) + (when (file-exists? path) + (let* ((md5 (md5sum path)) (lst (hash-ref hash md5))) + (if lst + (set! lst (cons path lst)) + (set! lst (list path))) + (hash-set! hash md5 lst)))) + paths) + ;; hash now maps the md5sum to the messages... + (hash-for-each + (lambda (md5 mpaths) + (if (> (length mpaths) 1) + (begin + ;;(format #t "md5sum: ~a:\n" md5) + (let ((num 1)) + (for-each + (lambda (path) + (if (equal? num 1) + (format #t "~a\n" path) + (begin + (format #t "~a: ~a\n" (if delete "deleting" "dup") path) + (if delete (delete-file path)))) + (set! num (+ 1 num))) + mpaths))))) + hash)))) + id-table))) + + + +(define (main args) + "Find duplicate messages and, potentially, delete the dups. + Be careful with that! +Interpret argument-list ARGS (like command-line +arguments). Possible arguments are: + --muhome (path to alternative mu home directory). + --delete (delete all but the first one). Run mu index afterwards. + --expr (expression to constrain search)." + (setlocale LC_ALL "") + (let* ((optionspec '( (muhome (value #t)) + (delete (value #f)) + (expr (value #t)) + (help (single-char #\h) (value #f)))) + (options (getopt-long args optionspec)) + (help (option-ref options 'help #f)) + (delete (option-ref options 'delete #f)) + (expr (option-ref options 'expr #t)) + (muhome (option-ref options 'muhome #f))) + (mu:initialize muhome) + (find-dups delete expr))) + + +;; Local Variables: +;; mode: scheme +;; End: + + + + + + + + + diff --git a/guile/scripts/msgs-count.scm b/guile/scripts/msgs-count.scm new file mode 100755 index 0000000..923e3a5 --- /dev/null +++ b/guile/scripts/msgs-count.scm @@ -0,0 +1,40 @@ +#!/bin/sh +exec guile -e main -s $0 $@ +!# +;; +;; Copyright (C) 2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +;; INFO: graph the number of messages per day (using gnuplot) +;; INFO: options: +;; INFO: --query=<query>: limit to messages matching query +;; INFO: --muhome=<muhome>: path to mu home dir + +(use-modules (mu) (mu script) (mu stats)) + +(define (count expr output) + "Print the total number of messages matching the query EXPR. +OUTPUT is ignored." + (display (mu:count expr)) + (newline)) + +(define (main args) + (mu:run-stats args count)) + +;; Local Variables: +;; mode: scheme +;; End: diff --git a/guile/scripts/msgs-per-day.scm b/guile/scripts/msgs-per-day.scm new file mode 100755 index 0000000..824f556 --- /dev/null +++ b/guile/scripts/msgs-per-day.scm @@ -0,0 +1,49 @@ +#!/bin/sh +exec guile -e main -s $0 $@ +!# +;; +;; Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +;; INFO: graph the number of messages per day (using gnuplot) +;; INFO: options: +;; INFO: --query=<query>: limit to messages matching query +;; INFO: --muhome=<muhome>: path to mu home dir +;; INFO: --output: the output format, such as "png", "wxt" +;; INFO: (depending on the environment) + +(use-modules (mu) (mu script) (mu stats) (mu plot)) + +(define (per-day expr output) + "Count the total number of messages for each weekday (0-6 for +Sun..Sat) that match EXPR. OUTPUT corresponds to the output format, as +per gnuplot's 'set terminal'." + (mu:plot-histogram + (mu:weekday-numbers->names + (sort (mu:tabulate + (lambda (msg) + (tm:wday (localtime (mu:date msg)))) expr) + (lambda (x y) (< (car x) (car y))))) + (format #f "Messages per weekday matching ~a" expr) + "Day" "Messages" output)) + +(define (main args) + (mu:run-stats args per-day)) + +;; Local Variables: +;; mode: scheme +;; End: diff --git a/guile/scripts/msgs-per-hour.scm b/guile/scripts/msgs-per-hour.scm new file mode 100755 index 0000000..d96f9b6 --- /dev/null +++ b/guile/scripts/msgs-per-hour.scm @@ -0,0 +1,49 @@ +#!/bin/sh +exec guile -e main -s $0 $@ +!# +;; +;; Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +;; INFO: graph the number of messages per day (using gnuplot) +;; INFO: options: +;; INFO: --query=<query>: limit to messages matching query +;; INFO: --muhome=<muhome>: path to mu home dir +;; INFO: --output: the output format, such as "png", "wxt" +;; INFO: (depending on the environment) + +(use-modules (mu) (mu script) (mu stats) (mu plot)) + +(define (per-hour expr output) + "Count the total number of messages for each weekday (0-6 for +Sun..Sat) that match EXPR. OUTPUT corresponds to the output format, as +per gnuplot's 'set terminal'." + (mu:plot-histogram + (sort + (mu:tabulate + (lambda (msg) + (tm:hour (localtime (mu:date msg)))) expr) + (lambda (x y) (< (car x) (car y)))) + (format #f "Messages per hour matching ~a" expr) + "Hour" "Messages" output)) + +(define (main args) + (mu:run-stats args per-hour)) + +;; Local Variables: +;; mode: scheme +;; End: diff --git a/guile/scripts/msgs-per-month.scm b/guile/scripts/msgs-per-month.scm new file mode 100755 index 0000000..50dbbed --- /dev/null +++ b/guile/scripts/msgs-per-month.scm @@ -0,0 +1,50 @@ +#!/bin/sh +exec guile -e main -s $0 $@ +!# +;; +;; Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +;; INFO: graph the number of messages per day (using gnuplot) +;; INFO: options: +;; INFO: --query=<query>: limit to messages matching query +;; INFO: --muhome=<muhome>: path to mu home dir +;; INFO: --output: the output format, such as "png", "wxt" +;; INFO: (depending on the environment) + +(use-modules (mu) (mu script) (mu stats) (mu plot)) + +(define (per-month expr output) + "Count the total number of messages for each weekday (0-6 for +Sun..Sat) that match EXPR. OUTPUT corresponds to the output format, as +per gnuplot's 'set terminal'." + (mu:plot-histogram + (mu:month-numbers->names + (sort + (mu:tabulate + (lambda (msg) + (tm:mon (localtime (mu:date msg)))) expr) + (lambda (x y) (< (car x) (car y))))) + (format #f "Messages per month matching ~a" expr) + "Month" "Messages" output)) + +(define (main args) + (mu:run-stats args per-month)) + +;; Local Variables: +;; mode: scheme +;; End: diff --git a/guile/scripts/msgs-per-year-month.scm b/guile/scripts/msgs-per-year-month.scm new file mode 100755 index 0000000..33b1447 --- /dev/null +++ b/guile/scripts/msgs-per-year-month.scm @@ -0,0 +1,52 @@ +#!/bin/sh +exec guile -e main -s $0 $@ +!# +;; +;; Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +;; INFO: graph the number of messages per day (using gnuplot) +;; INFO: options: +;; INFO: --query=<query>: limit to messages matching query +;; INFO: --muhome=<muhome>: path to mu home dir +;; INFO: --output: the output format, such as "png", "wxt" +;; INFO: (depending on the environment) + +(use-modules (mu) (mu script) (mu stats) (mu plot)) + +(define (per-year-month expr output) + "Count the total number of messages for each weekday (0-6 for +Sun..Sat) that match EXPR. OUTPUT corresponds to the output format, as +per gnuplot's 'set terminal'." + (mu:plot-histogram + (sort (mu:tabulate + (lambda (msg) + (string->number + (format #f "~d~2'0d" + (+ 1900 (tm:year (localtime (mu:date msg)))) + (tm:mon (localtime (mu:date msg)))))) + expr) + (lambda (x y) (< (car x) (car y)))) + (format #f "Messages per year/month matching ~a" expr) + "Year/Month" "Messages" output)) + +(define (main args) + (mu:run-stats args per-year-month)) + +;; Local Variables: +;; mode: scheme +;; End: diff --git a/guile/scripts/msgs-per-year.scm b/guile/scripts/msgs-per-year.scm new file mode 100755 index 0000000..242e299 --- /dev/null +++ b/guile/scripts/msgs-per-year.scm @@ -0,0 +1,48 @@ +#!/bin/sh +exec guile -e main -s $0 $@ +!# +;; +;; Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +;; INFO: graph the number of messages per day (using gnuplot) +;; INFO: options: +;; INFO: --query=<query>: limit to messages matching query +;; INFO: --muhome=<muhome>: path to mu home dir +;; INFO: --output: the output format, such as "png", "wxt" +;; INFO: (depending on the environment) + +(use-modules (mu) (mu script) (mu stats) (mu plot)) + +(define (per-year expr output) + "Count the total number of messages for each weekday (0-6 for +Sun..Sat) that match EXPR. OUTPUT corresponds to the output format, as +per gnuplot's 'set terminal'." + (mu:plot-histogram + (sort (mu:tabulate + (lambda (msg) + (+ 1900 (tm:year (localtime (mu:date msg))))) expr) + (lambda (x y) (< (car x) (car y)))) + (format #f "Messages per year matching ~a" expr) + "Year" "Messages" output)) + +(define (main args) + (mu:run-stats args per-year)) + +;; Local Variables: +;; mode: scheme +;; End: diff --git a/guile/tests/Makefile.am b/guile/tests/Makefile.am new file mode 100644 index 0000000..8df87fb --- /dev/null +++ b/guile/tests/Makefile.am @@ -0,0 +1,52 @@ +# Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +## +## 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 3, or (at your option) any +## later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +AM_CPPFLAGS=$(XAPIAN_CXXFLAGS) \ + $(GMIME_CFLAGS) \ + $(GLIB_CFLAGS) \ + -I${top_srcdir} \ + -I${top_srcdir}/lib \ + -DMU_TESTMAILDIR=\"${top_srcdir}/lib/testdir\" \ + -DMU_TESTMAILDIR2=\"${top_srcdir}/lib/testdir2\" \ + -DMU_TESTMAILDIR3=\"${top_srcdir}/lib/testdir3\" \ + -DMU_PROGRAM=\"${abs_top_builddir}/mu/mu\" \ + -DMU_GUILE_MODULE_PATH=\"${abs_top_srcdir}/guile/\" \ + -DMU_GUILE_LIBRARY_PATH=\"${abs_top_builddir}/guile/.libs\" \ + -DABS_CURDIR=\"${abs_builddir}\" \ + -DABS_SRCDIR=\"${abs_srcdir}\" + +# don't use -Werror, as it might break on other compilers +# use -Wno-unused-parameters, because some callbacks may not +# really need all the params they get +AM_CFLAGS=$(ASAN_CFLAGS) ${WARN_CFLAGS} +AM_CXXFLAGS=$(ASAN_CXXFLAGS) ${WARN_CXXFLAGS} +AM_LDFLAGS=$(ASAN_LDFLAGS) + +noinst_PROGRAMS= $(TEST_PROGS) + +TEST_PROGS += test-mu-guile +test_mu_guile_SOURCES= test-mu-guile.c dummy.cc +test_mu_guile_LDADD=${top_builddir}/lib/libtestmucommon.la + +# we need to use dummy.cc to enforce c++ linking... +BUILT_SOURCES= \ + dummy.cc +dummy.cc: + touch dummy.cc + +EXTRA_DIST=test-mu-guile.scm diff --git a/guile/tests/test-mu-guile.c b/guile/tests/test-mu-guile.c new file mode 100644 index 0000000..50199eb --- /dev/null +++ b/guile/tests/test-mu-guile.c @@ -0,0 +1,134 @@ +/* +** Copyright (C) 2012-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include <glib.h> +#include <glib/gstdio.h> + +#include <lib/mu-query.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include "test-mu-common.h" +#include <lib/mu-store.hh> + + +/* tests for the command line interface, uses testdir2 */ + +static gchar* +fill_database (void) +{ + gchar *cmdline, *tmpdir; + GError *err; + + tmpdir = test_mu_common_get_random_tmpdir(); + cmdline = g_strdup_printf ( + "/bin/sh -c '" + "%s init --muhome=%s --maildir=%s --quiet; " + "%s index --muhome=%s --quiet'", + MU_PROGRAM, tmpdir, MU_TESTMAILDIR2, + MU_PROGRAM, tmpdir); + + if (g_test_verbose()) + g_print ("%s\n", cmdline); + + err = NULL; + if (!g_spawn_command_line_sync (cmdline, NULL, NULL, + NULL, &err)) { + g_printerr ("Error: %s\n", err ? err->message : "?"); + g_assert (0); + } + + g_free (cmdline); + return tmpdir; +} + + +static void +test_something (const char *what) +{ + char *dir, *cmdline; + gint result; + + dir = fill_database (); + cmdline = g_strdup_printf ( + "LD_LIBRARY_PATH=%s %s -q -L %s -e main %s/test-mu-guile.scm " + "--muhome=%s --test=%s", + MU_GUILE_LIBRARY_PATH, + GUILE_BINARY, + MU_GUILE_MODULE_PATH, + ABS_SRCDIR, + dir, + what); + + if (g_test_verbose ()) + g_print ("cmdline: %s\n", cmdline); + + result = system (cmdline); + g_assert (result == 0); + + g_free (dir); + g_free (cmdline); +} + +static void +test_mu_guile_queries (void) +{ + test_something ("queries"); +} + +static void +test_mu_guile_messages (void) +{ + test_something ("message"); +} + +static void +test_mu_guile_stats (void) +{ + test_something ("stats"); +} + + +int +main (int argc, char *argv[]) +{ + int rv; + g_test_init (&argc, &argv, NULL); + + if (!set_en_us_utf8_locale()) + return 0; /* don't error out... */ + + g_test_add_func ("/guile/queries", test_mu_guile_queries); + g_test_add_func ("/guile/message", test_mu_guile_messages); + g_test_add_func ("/guile/stats", test_mu_guile_stats); + + g_log_set_handler (NULL, + G_LOG_LEVEL_MASK | G_LOG_LEVEL_WARNING| + G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION, + (GLogFunc)black_hole, NULL); + + rv = g_test_run (); + + return rv; +} diff --git a/guile/tests/test-mu-guile.scm b/guile/tests/test-mu-guile.scm new file mode 100755 index 0000000..8281518 --- /dev/null +++ b/guile/tests/test-mu-guile.scm @@ -0,0 +1,124 @@ +#!/bin/sh +exec guile -e main -s $0 $@ +!# + +;; Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +;; +;; 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 3, or (at your option) any +;; later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +(setlocale LC_ALL "") + +(use-modules (srfi srfi-1)) +(use-modules (ice-9 getopt-long) (ice-9 optargs) (ice-9 popen) (ice-9 format)) +(use-modules (mu) (mu stats)) + +(define (n-results-or-exit query n) + "Run QUERY, and exit 1 if the number of results != N." + (let ((lst (mu:message-list query))) + (if (not (= (length lst) n)) + (begin + (simple-format (current-error-port) "Query: \"~A\"; expected ~A, got ~A\n" + query n (length lst)) + (exit 1))))) + +(define (test-queries) + "Test a bunch of queries (or die trying)." + (n-results-or-exit "hello" 1) + (n-results-or-exit "f:john fruit" 1) + (n-results-or-exit "f:soc@example.com" 1) + (n-results-or-exit "t:alki@example.com" 1) + (n-results-or-exit "t:alcibiades" 1) + (n-results-or-exit "f:soc@example.com OR f:john" 2) + (n-results-or-exit "f:soc@example.com OR f:john OR t:edmond" 3) + (n-results-or-exit "t:julius" 1) + (n-results-or-exit "s:dude" 1) + (n-results-or-exit "t:dantès" 1) + (n-results-or-exit "file:sittingbull.jpg" 1) + (n-results-or-exit "file:custer.jpg" 1) + (n-results-or-exit "file:custer.*" 1) + (n-results-or-exit "j:sit*" 1) + (n-results-or-exit "mime:image/jpeg" 1) + (n-results-or-exit "mime:text/plain" 13) + (n-results-or-exit "y:text*" 13) + (n-results-or-exit "y:image*" 1) + (n-results-or-exit "mime:message/rfc822" 2)) + +(define (error-exit msg . args) + "Print error and exit." + (let ((msg (apply format #f msg args))) + (simple-format (current-error-port) "*ERROR*: ~A\n" msg) + (exit 1))) + +(define (str-equal-or-exit got exp) + "S1 == S2 or exit 1." + ;; (format #t "'~A' <=> '~A'\n" s1 s2) + (if (not (string= exp got)) + (error-exit "Expected \"~A\", got \"~A\"\n" exp got))) + +(define (test-message) + "Test functions for a particular message." + + (let ((msg (car (mu:message-list "hello")))) + (str-equal-or-exit (mu:subject msg) "Fwd: rfc822") + (str-equal-or-exit (mu:to msg) "martin") + (str-equal-or-exit (mu:from msg) "foobar <foo@example.com>") + (str-equal-or-exit (mu:header msg "X-Mailer") "Ximian Evolution 1.4.5") + + (if (not (equal? (mu:priority msg) mu:prio:normal)) + (error-exit "Expected ~A, got ~A" (mu:priority msg) mu:prio:normal))) + + (let ((msg (car (mu:message-list "atoms")))) + (str-equal-or-exit (mu:subject msg) "atoms") + (str-equal-or-exit (mu:to msg) "Democritus <demo@example.com>") + (str-equal-or-exit (mu:from msg) "\"Richard P. Feynman\" <rpf@example.com>") + ;;(str-equal-or-exit (mu:header msg "Content-transfer-encoding") "7BIT") + + (if (not (equal? (mu:priority msg) mu:prio:high)) + (error-exit "Expected ~a, got ~a" (mu:priority msg) mu:prio:high)))) + +(define (num-equal-or-exit got exp) + "S1 == S2 or exit 1." + ;; (format #t "'~A' <=> '~A'\n" s1 s2) + (if (not (= exp got)) + (error-exit "Expected \"~S\", got \"~S\"\n" exp got))) + +(define (test-stats) + "Test statistical functions." + ;; average + (num-equal-or-exit (mu:average mu:size) 82152/13) + (num-equal-or-exit (floor (mu:stddev mu:size)) 13020.0) + (num-equal-or-exit (mu:max mu:size) 46308) + (num-equal-or-exit (mu:min mu:size) 111)) + +(define (main args) + (let* ((optionspec '((muhome (value #t)) + (test (value #t)))) + (options (getopt-long args optionspec)) + (muhome (option-ref options 'muhome #f)) + (test (option-ref options 'test #f))) + + (mu:initialize muhome) + + (if test + (cond + ((string= test "queries") (test-queries)) + ((string= test "message") (test-message)) + ((string= test "stats") (test-stats)) + (#t (exit 1)))))) + + +;; Local Variables: +;; mode: scheme +;; End: diff --git a/guile/texi.texi.in b/guile/texi.texi.in new file mode 100644 index 0000000..716d9a9 --- /dev/null +++ b/guile/texi.texi.in @@ -0,0 +1,3 @@ +@c the version for mu for including in texinfo docs +@set mu-version @VERSION@ + diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 0000000..405506e --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,285 @@ +## Copyright (C) 2010-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# enforce compiling guile (optionally) first,then this dir first +# before descending into tests/ +include $(top_srcdir)/gtest.mk + +SUBDIRS= utils query + +if HAVE_JSON_GLIB +json_srcs= \ + mu-msg-json.c +json_flag="-DHAVE_JSON_GLIB" +endif + +AM_CFLAGS= \ + $(WARN_CFLAGS) \ + $(GMIME_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(GUILE_CFLAGS) \ + $(JSON_GLIB_CFLAGS) \ + $(ASAN_CFLAGS) \ + $(json_flag) \ + $(CODE_COVERAGE_CFLAGS) \ + -DMU_TESTMAILDIR=\"${abs_srcdir}/testdir\" \ + -DMU_TESTMAILDIR2=\"${abs_srcdir}/testdir2\" \ + -DMU_TESTMAILDIR3=\"${abs_srcdir}/testdir3\" \ + -DMU_TESTMAILDIR4=\"${abs_srcdir}/testdir4\" \ + -DABS_CURDIR=\"${abs_builddir}\" \ + -DABS_SRCDIR=\"${abs_srcdir}\" \ + -Wno-format-nonliteral \ + -Wno-switch-enum \ + -Wno-deprecated-declarations \ + -Wno-inline + +AM_CXXFLAGS= \ + $(GMIME_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(GUILE_CFLAGS) \ + $(JSON_GLIB_CFLAGS) \ + $(json_flag) \ + $(WARN_CXXFLAGS) \ + $(XAPIAN_CXXFLAGS) \ + $(ASAN_CXXFLAGS) \ + $(CODE_COVERAGE_CFLAGS) \ + -DMU_TESTMAILDIR=\"${abs_srcdir}/testdir\" + +AM_CPPFLAGS= \ + $(CODE_COVERAGE_CPPFLAGS) + +# don't use -Werror, as it might break on other compilers +# use -Wno-unused-parameters, because some callbacks may not +# really need all the params they get +# AM_CFLAGS=-Wall -Wextra -Wno-unused-parameter \ +# -Wdeclaration-after-statement -Wno-variadic-macros +# AM_CXXFLAGS=-Wall -Wextra -Wno-unused-parameter + +noinst_LTLIBRARIES= \ + libmu.la + +libmu_la_SOURCES= \ + mu-bookmarks.c \ + mu-bookmarks.h \ + mu-contacts.cc \ + mu-contacts.hh \ + mu-container.c \ + mu-container.h \ + mu-flags.h \ + mu-flags.c \ + mu-index.c \ + mu-index.h \ + mu-maildir.c \ + mu-maildir.h \ + mu-msg-crypto.c \ + mu-msg-doc.cc \ + mu-msg-doc.h \ + mu-msg-fields.c \ + mu-msg-fields.h \ + mu-msg-file.c \ + mu-msg-file.h \ + mu-msg-iter.cc \ + mu-msg-iter.h \ + $(json_srcs) \ + mu-msg-part.c \ + mu-msg-part.h \ + mu-msg-prio.c \ + mu-msg-prio.h \ + mu-msg-priv.h \ + mu-msg-sexp.c \ + mu-msg.c \ + mu-msg.h \ + mu-msg.h \ + mu-query.cc \ + mu-query.h \ + mu-runtime.cc \ + mu-runtime.h \ + mu-script.c \ + mu-script.h \ + mu-store.cc \ + mu-store.hh \ + mu-threader.c \ + mu-threader.h + +libmu_la_LIBADD= \ + $(XAPIAN_LIBS) \ + $(GMIME_LIBS) \ + $(GLIB_LIBS) \ + $(GUILE_LIBS) \ + $(JSON_GLIB_LIBS) \ + ${builddir}/utils/libmu-utils.la \ + ${builddir}/query/libmu-query.la \ + $(CODE_COVERAGE_LIBS) + +libmu_la_LDFLAGS= \ + $(ASAN_LDFLAGS) + +EXTRA_DIST= \ + mu-msg-crypto.c \ + doxyfile.in + +noinst_PROGRAMS= $(TEST_PROGS) + +noinst_LTLIBRARIES+= \ + libtestmucommon.la + +TEST_PROGS += test-mu-maildir +test_mu_maildir_SOURCES= test-mu-maildir.c dummy.cc +test_mu_maildir_LDADD= libtestmucommon.la + +TEST_PROGS += test-mu-msg-fields +test_mu_msg_fields_SOURCES= test-mu-msg-fields.c dummy.cc +test_mu_msg_fields_LDADD= libtestmucommon.la + +TEST_PROGS += test-mu-msg +test_mu_msg_SOURCES= test-mu-msg.c dummy.cc +test_mu_msg_LDADD= libtestmucommon.la + +TEST_PROGS += test-mu-store +test_mu_store_SOURCES= test-mu-store.c dummy.cc +test_mu_store_LDADD= libtestmucommon.la + +TEST_PROGS += test-mu-flags +test_mu_flags_SOURCES= test-mu-flags.c dummy.cc +test_mu_flags_LDADD= libtestmucommon.la + +TEST_PROGS += test-mu-container +test_mu_container_SOURCES= test-mu-container.c dummy.cc +test_mu_container_LDADD= libtestmucommon.la + +TEST_PROGS += test-mu-contacts +test_mu_contacts_SOURCES= test-mu-contacts.cc +test_mu_contacts_LDADD= libtestmucommon.la + +# we need to use dummy.cc to enforce c++ linking... +BUILT_SOURCES= \ + dummy.cc + +dummy.cc: + touch dummy.cc + +libtestmucommon_la_SOURCES= \ + test-mu-common.c \ + test-mu-common.h +libtestmucommon_la_LIBADD= \ + libmu.la + +# note the question marks; make does not like files with ':', so we +# use the (also supported) version with '!' instead. We could escape +# the : with \: but automake does not recognize that.... + +# test messages, the '.ignore' message should be ignored +# when indexing +EXTRA_DIST+= \ + testdir/tmp/1220863087.12663.ignore \ + testdir/new/1220863087.12663_9.mindcrime \ + testdir/new/1220863087.12663_25.mindcrime \ + testdir/new/1220863087.12663_21.mindcrime \ + testdir/new/1220863087.12663_23.mindcrime \ + testdir/cur/1220863087.12663_5.mindcrime!2,S \ + testdir/cur/1220863087.12663_7.mindcrime!2,RS \ + testdir/cur/1220863087.12663_15.mindcrime!2,PS \ + testdir/cur/1220863087.12663_19.mindcrime!2,S \ + testdir/cur/1220863042.12663_1.mindcrime!2,S \ + testdir/cur/1220863060.12663_3.mindcrime!2,S \ + testdir/cur/1283599333.1840_11.cthulhu!2, \ + testdir/cur/1305664394.2171_402.cthulhu!2, \ + testdir/cur/1252168370_3.14675.cthulhu!2,S \ + testdir/cur/encrypted!2,S \ + testdir/cur/multimime!2,FS \ + testdir/cur/signed!2,S \ + testdir/cur/signed-encrypted!2,S \ + testdir/cur/special!2,Sabc \ + testdir/cur/multirecip!2,S \ + testdir2/bar/cur/mail1 \ + testdir2/bar/cur/mail2 \ + testdir2/bar/cur/mail3 \ + testdir2/bar/cur/mail4 \ + testdir2/bar/cur/mail5 \ + testdir2/bar/cur/181736.eml \ + testdir2/bar/cur/mail6 \ + testdir2/bar/tmp/.noindex \ + testdir2/bar/new/.noindex \ + testdir2/Foo/cur/mail5 \ + testdir2/Foo/cur/arto.eml \ + testdir2/Foo/cur/fraiche.eml \ + testdir2/Foo/tmp/.noindex \ + testdir2/Foo/new/.noindex \ + testdir2/wom_bat/cur/atomic \ + testdir2/wom_bat/cur/rfc822.1 \ + testdir2/wom_bat/cur/rfc822.2 \ + testdir3/cycle \ + testdir3/cycle/new/.noindex \ + testdir3/cycle/cur/rogue0 \ + testdir3/cycle/cur/cycle0 \ + testdir3/cycle/cur/cycle0.0 \ + testdir3/cycle/cur/cycle0.0.0 \ + testdir3/cycle/tmp/.noindex \ + testdir3/tree/new/.noindex \ + testdir3/tree/cur/child0.0 \ + testdir3/tree/cur/child4.0 \ + testdir3/tree/cur/root2 \ + testdir3/tree/cur/root1 \ + testdir3/tree/cur/child3.0.0.0.0 \ + testdir3/tree/cur/root0 \ + testdir3/tree/cur/child2.0.0 \ + testdir3/tree/cur/child0.1 \ + testdir3/tree/cur/child0.1.0 \ + testdir3/tree/cur/child4.1 \ + testdir3/tree/tmp/.noindex \ + testdir3/sort/1st-child-promotes-thread/cur/A \ + testdir3/sort/1st-child-promotes-thread/cur/B \ + testdir3/sort/1st-child-promotes-thread/cur/C \ + testdir3/sort/1st-child-promotes-thread/cur/D \ + testdir3/sort/2nd-child-promotes-thread/cur/A \ + testdir3/sort/2nd-child-promotes-thread/cur/B \ + testdir3/sort/2nd-child-promotes-thread/cur/C \ + testdir3/sort/2nd-child-promotes-thread/cur/D \ + testdir3/sort/2nd-child-promotes-thread/cur/E \ + testdir3/sort/child-does-not-promote-thread/cur/A \ + testdir3/sort/child-does-not-promote-thread/cur/X \ + testdir3/sort/child-does-not-promote-thread/cur/Y \ + testdir3/sort/child-does-not-promote-thread/cur/Z \ + testdir3/sort/grandchild-promotes-only-subthread/cur/A \ + testdir3/sort/grandchild-promotes-only-subthread/cur/B \ + testdir3/sort/grandchild-promotes-only-subthread/cur/C \ + testdir3/sort/grandchild-promotes-only-subthread/cur/D \ + testdir3/sort/grandchild-promotes-only-subthread/cur/E \ + testdir3/sort/grandchild-promotes-only-subthread/cur/F \ + testdir3/sort/grandchild-promotes-only-subthread/cur/G \ + testdir3/sort/grandchild-promotes-thread/cur/A \ + testdir3/sort/grandchild-promotes-thread/cur/B \ + testdir3/sort/grandchild-promotes-thread/cur/C \ + testdir3/sort/grandchild-promotes-thread/cur/D \ + testdir3/sort/grandchild-promotes-thread/cur/E \ + testdir4/1220863087.12663_19.mindcrime!2,S \ + testdir4/1220863042.12663_1.mindcrime!2,S \ + testdir4/1283599333.1840_11.cthulhu!2, \ + testdir4/1305664394.2171_402.cthulhu!2, \ + testdir4/1252168370_3.14675.cthulhu!2,S \ + testdir4/mail1 \ + testdir4/mail5 \ + testdir4/181736.eml \ + testdir4/encrypted!2,S \ + testdir4/multimime!2,FS \ + testdir4/signed!2,S \ + testdir4/signed-bad!2,S \ + testdir4/signed-encrypted!2,S \ + testdir4/special!2,Sabc + +TESTS=$(TEST_PROGS) + +include $(top_srcdir)/aminclude_static.am diff --git a/lib/doxyfile.in b/lib/doxyfile.in new file mode 100644 index 0000000..6ad94ac --- /dev/null +++ b/lib/doxyfile.in @@ -0,0 +1,181 @@ +# Doxyfile 0.1 + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = mu +PROJECT_NUMBER = @VERSION@ +OUTPUT_DIRECTORY = apidocs +OUTPUT_LANGUAGE = English +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +INTERNAL_DOCS = NO +STRIP_CODE_COMMENTS = YES +CASE_SENSE_NAMES = YES +SHORT_NAMES = NO +HIDE_SCOPE_NAMES = NO +VERBATIM_HEADERS = YES +SHOW_INCLUDE_FILES = YES +JAVADOC_AUTOBRIEF = YES +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +ALIASES = +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +OPTIMIZE_OUTPUT_FOR_C = YES +SHOW_USED_FILES = YES +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_FORMAT = +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = @top_srcdir@/lib/ +FILE_PATTERNS = *.c *.h +RECURSIVE = YES +EXCLUDE = tests + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = Makefile.* ChangeLog CHANGES CHANGES.* README \ + README.* *.png AUTHORS DESIGN DESIGN.* *.desktop \ + DESKTOP* COMMENTS HOWTO magic NOTES TODO THANKS + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = YES +MAN_OUTPUT = man +MAN_EXTENSION = .3mu +MAN_LINKS = YES +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = YES +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = "G_BEGIN_DECLS=" \ + "G_END_DECLS=" +# "DOXYGEN_SHOULD_SKIP_THIS" \ +# "DBUS_GNUC_DEPRECATED=" \ +# "_DBUS_DEFINE_GLOBAL_LOCK(name)=" \ +# "_DBUS_GNUC_PRINTF(from,to)=" +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +PERL_PATH = +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +TEMPLATE_RELATIONS = YES +HIDE_UNDOC_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +GRAPHICAL_HIERARCHY = YES +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 640 +MAX_DOT_GRAPH_HEIGHT = 1024 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/lib/mu-bookmarks.c b/lib/mu-bookmarks.c new file mode 100644 index 0000000..2f1ebac --- /dev/null +++ b/lib/mu-bookmarks.c @@ -0,0 +1,146 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ +/* +** Copyright (C) 2010-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include <glib.h> +#include "mu-bookmarks.h" + +#define MU_BOOKMARK_GROUP "mu" + +struct _MuBookmarks { + char *_bmpath; + GHashTable *_hash; +}; + + +static void +fill_hash (GHashTable *hash, GKeyFile *kfile) +{ + gchar **keys, **cur; + + keys = g_key_file_get_keys (kfile, MU_BOOKMARK_GROUP, NULL, NULL); + if (!keys) + return; + + for (cur = keys; *cur; ++cur) { + gchar *val; + val = g_key_file_get_string (kfile, MU_BOOKMARK_GROUP, + *cur, NULL); + if (val) + g_hash_table_insert (hash, *cur, val); + } + + /* don't use g_strfreev, because we put them in the hash table; + * only free the gchar** itself */ + g_free (keys); +} + +static GHashTable* +create_hash_from_key_file (const gchar *bmpath) +{ + GKeyFile *kfile; + GHashTable *hash; + + kfile = g_key_file_new (); + + if (!g_key_file_load_from_file (kfile, bmpath, G_KEY_FILE_NONE, NULL)) { + g_key_file_free (kfile); + return NULL; + } + + hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + fill_hash (hash, kfile); + + g_key_file_free (kfile); + + return hash; +} + + + +MuBookmarks* +mu_bookmarks_new (const gchar *bmpath) +{ + MuBookmarks *bookmarks; + GHashTable *hash; + + g_return_val_if_fail (bmpath, NULL); + + hash = create_hash_from_key_file (bmpath); + if (!hash) + return NULL; + + bookmarks = g_new (MuBookmarks, 1); + + bookmarks->_bmpath = g_strdup (bmpath); + bookmarks->_hash = hash; + + return bookmarks; +} + + + +void +mu_bookmarks_destroy (MuBookmarks *bm) +{ + if (!bm) + return; + + g_free (bm->_bmpath); + g_hash_table_destroy (bm->_hash); + g_free (bm); +} + +const gchar* +mu_bookmarks_lookup (MuBookmarks *bm, const gchar *name) +{ + g_return_val_if_fail (bm, NULL); + g_return_val_if_fail (name, NULL); + + return g_hash_table_lookup (bm->_hash, name); +} + +struct _BMData { + MuBookmarksForeachFunc _func; + gpointer _user_data; +}; +typedef struct _BMData BMData; + + +static void +each_bookmark (const gchar* key, const gchar *val, BMData *bmdata) +{ + bmdata->_func (key, val, bmdata->_user_data); +} + + +void +mu_bookmarks_foreach (MuBookmarks *bm, MuBookmarksForeachFunc func, + gpointer user_data) +{ + BMData bmdata; + + g_return_if_fail (bm); + g_return_if_fail (func); + + bmdata._func = func; + bmdata._user_data = user_data; + + g_hash_table_foreach (bm->_hash, (GHFunc)each_bookmark, &bmdata); +} diff --git a/lib/mu-bookmarks.h b/lib/mu-bookmarks.h new file mode 100644 index 0000000..2f1d99f --- /dev/null +++ b/lib/mu-bookmarks.h @@ -0,0 +1,86 @@ +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_BOOKMARKS_H__ +#define __MU_BOOKMARKS_H__ + +#include <glib.h> + +G_BEGIN_DECLS +/** + * @addtogroup MuBookmarks + * Functions for dealing with bookmarks + * @{ + */ + +struct _MuBookmarks; +/*! \struct MuBookmarks + * \brief Opaque structure representing a sequence of bookmarks + */ +typedef struct _MuBookmarks MuBookmarks; + + +/** + * create a new bookmarks object. when it's no longer needed, use + * mu_bookmarks_destroy + * + * @param bmpath path to the bookmarks file + * + * @return a new BookMarks object, or NULL in case of error + */ +MuBookmarks *mu_bookmarks_new (const gchar *bmpath) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +/** + * destroy a bookmarks object + * + * @param bm a bookmarks object, or NULL + */ +void mu_bookmarks_destroy (MuBookmarks *bm); + + +/** + * get the value for some bookmark + * + * @param bm a valid bookmarks object + * @param name name of the bookmark to retrieve + * + * @return the value of the bookmark or NULL in case in error, e.g. if + * the bookmark was not found + */ +const gchar* mu_bookmarks_lookup (MuBookmarks *bm, const gchar *name); + +typedef void (*MuBookmarksForeachFunc) (const gchar *key, const gchar *val, + gpointer user_data); + +/** + * call a function for each bookmark + * + * @param bm a valid bookmarks object + * @param func a callback function to be called for each bookmarks + * @param user_data a user pointer passed to the callback + */ +void mu_bookmarks_foreach (MuBookmarks *bm, MuBookmarksForeachFunc func, + gpointer user_data); + +/** @} */ + +G_END_DECLS + +#endif /*__MU_BOOKMARKS_H__*/ diff --git a/lib/mu-contacts.cc b/lib/mu-contacts.cc new file mode 100644 index 0000000..e5bb21f --- /dev/null +++ b/lib/mu-contacts.cc @@ -0,0 +1,299 @@ +/* +** Copyright (C) 2019 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include "mu-contacts.hh" + +#include <mutex> +#include <unordered_map> +#include <set> +#include <sstream> +#include <functional> +#include <algorithm> + +#include <utils/mu-utils.hh> +#include <glib.h> + +using namespace Mu; + +ContactInfo::ContactInfo (const std::string& _full_address, + const std::string& _email, + const std::string& _name, + bool _personal, time_t _last_seen, size_t _freq): + full_address{_full_address}, + email{_email}, + name{_name}, + personal{_personal}, + last_seen{_last_seen}, + freq{_freq}, + tstamp{g_get_monotonic_time()} {} + + +struct EmailHash { + std::size_t operator()(const std::string& email) const { + std::size_t djb = 5381; // djb hash + for (const auto c : email) + djb = ((djb << 5) + djb) + g_ascii_tolower(c); + return djb; + } +}; + +struct EmailEqual { + bool operator()(const std::string& email1, const std::string& email2) const { + return g_ascii_strcasecmp(email1.c_str(), email2.c_str()) == 0; + } +}; + +struct ContactInfoHash { + std::size_t operator()(const ContactInfo& ci) const { + std::size_t djb = 5381; // djb hash + for (const auto c : ci.email) + djb = ((djb << 5) + djb) + g_ascii_tolower(c); + return djb; + } +}; + +struct ContactInfoEqual { + bool operator()(const Mu::ContactInfo& ci1, const Mu::ContactInfo& ci2) const { + return g_ascii_strcasecmp(ci1.email.c_str(), ci2.email.c_str()) == 0; + } +}; + +struct ContactInfoLessThan { + bool operator()(const Mu::ContactInfo& ci1, const Mu::ContactInfo& ci2) const { + + if (ci1.personal != ci2.personal) + return ci1.personal; // personal comes first + + if (ci1.last_seen != ci2.last_seen) // more recent comes first + return ci1.last_seen > ci2.last_seen; + + if (ci1.freq != ci2.freq) // more frequent comes first + return ci1.freq > ci2.freq; + + return g_ascii_strcasecmp(ci1.email.c_str(), ci2.email.c_str()) < 0; + } +}; + +using ContactUMap = std::unordered_map<const std::string, ContactInfo, EmailHash, EmailEqual>; +//using ContactUSet = std::unordered_set<ContactInfo, ContactInfoHash, ContactInfoEqual>; +using ContactSet = std::set<std::reference_wrapper<const ContactInfo>, ContactInfoLessThan>; + +struct Contacts::Private { + Private(const std::string& serialized): + contacts_{deserialize(serialized)} + {} + + ContactUMap deserialize(const std::string&) const; + std::string serialize() const; + + ContactUMap contacts_; + std::mutex mtx_; +}; + +constexpr auto Separator = "\xff"; // Invalid in UTF-8 + +ContactUMap +Contacts::Private::deserialize(const std::string& serialized) const +{ + ContactUMap contacts; + std::stringstream ss{serialized, std::ios_base::in}; + std::string line; + + while (getline (ss, line)) { + + const auto parts = Mu::split (line, Separator); + if (G_UNLIKELY(parts.size() != 6)) { + g_warning ("error: '%s'", line.c_str()); + continue; + } + + ContactInfo ci(std::move(parts[0]), // full address + parts[1], // email + std::move(parts[2]), // name + parts[3][0] == '1' ? true : false, // personal + (time_t)g_ascii_strtoll(parts[4].c_str(), NULL, 10), // last_seen + (std::size_t)g_ascii_strtoll(parts[5].c_str(), NULL, 10)); // freq + + contacts.emplace(std::move(parts[1]), std::move(ci)); + + } + + return contacts; +} + + +Contacts::Contacts (const std::string& serialized) : + priv_{std::make_unique<Private>(serialized)} +{} + +Contacts::~Contacts() = default; + +std::string +Contacts::serialize() const +{ + std::lock_guard<std::mutex> l_{priv_->mtx_}; + std::string s; + + for (auto& item: priv_->contacts_) { + const auto& ci{item.second}; + s += Mu::format("%s%s" + "%s%s" + "%s%s" + "%d%s" + "%" G_GINT64_FORMAT "%s" + "%" G_GINT64_FORMAT "\n", + ci.full_address.c_str(), Separator, + ci.email.c_str(), Separator, + ci.name.c_str(), Separator, + ci.personal ? 1 : 0, Separator, + (gint64)ci.last_seen, Separator, + (gint64)ci.freq); + } + + return s; +} + + +// for now, we only care about _not_ having newlines. +static void +wash (std::string& str) +{ + str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); +} + + +void +Contacts::add (ContactInfo&& ci) +{ + std::lock_guard<std::mutex> l_{priv_->mtx_}; + + auto down = g_ascii_strdown (ci.email.c_str(), -1); + std::string email{down}; + g_free(down); + + auto it = priv_->contacts_.find(email); + if (it != priv_->contacts_.end()) { + auto& ci2 = it->second; + ++ci2.freq; + if (ci.last_seen > ci2.last_seen) { + ci2.last_seen = ci.last_seen; + wash(ci.email); + ci2.email = std::move(ci.email); + if (!ci.name.empty()) { + wash(ci.name); + ci2.name = std::move(ci.name); + } + } + } + + wash(ci.name); + wash(ci.email); + wash(ci.full_address); + + priv_->contacts_.emplace( + ContactUMap::value_type(std::move(email), std::move(ci))); +} + + +const ContactInfo* +Contacts::_find (const std::string& email) const +{ + std::lock_guard<std::mutex> l_{priv_->mtx_}; + + ContactInfo ci{"", email, "", false, 0}; + const auto it = priv_->contacts_.find(ci.email); + if (it == priv_->contacts_.end()) + return {}; + else + return &it->second; +} + + +void +Contacts::clear() +{ + std::lock_guard<std::mutex> l_{priv_->mtx_}; + + priv_->contacts_.clear(); +} + + +std::size_t +Contacts::size() const +{ + std::lock_guard<std::mutex> l_{priv_->mtx_}; + + return priv_->contacts_.size(); +} + + +void +Contacts::for_each(const EachContactFunc& each_contact) const +{ + std::lock_guard<std::mutex> l_{priv_->mtx_}; + + if (!each_contact) + return; // nothing to do + + // first sort them for 'rank' + ContactSet sorted; + for (const auto& item: priv_->contacts_) + sorted.emplace(item.second); + + for (const auto& ci: sorted) + each_contact (ci); +} + +/// C binding + +size_t +mu_contacts_count (const MuContacts *self) +{ + g_return_val_if_fail (self, 0); + + auto myself = reinterpret_cast<const Mu::Contacts*>(self); + + return myself->size(); +} + +gboolean +mu_contacts_foreach (const MuContacts *self, MuContactsForeachFunc func, + gpointer user_data) +{ + g_return_val_if_fail (self, FALSE); + g_return_val_if_fail (func, FALSE); + + auto myself = reinterpret_cast<const Mu::Contacts*>(self); + + myself->for_each([&](const ContactInfo& ci) { + g_return_if_fail (!ci.email.empty()); + func(ci.full_address.c_str(), + ci.email.c_str(), + ci.name.empty() ? NULL : ci.name.c_str(), + ci.personal, + ci.last_seen, + ci.freq, + ci.tstamp, + user_data); + }); + + return TRUE; +} + +struct _MuContacts : public Mu::Contacts {}; /**< c-compat */ diff --git a/lib/mu-contacts.hh b/lib/mu-contacts.hh new file mode 100644 index 0000000..7873cd6 --- /dev/null +++ b/lib/mu-contacts.hh @@ -0,0 +1,207 @@ +/* +** Copyright (C) 2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_CONTACTS_HH__ +#define __MU_CONTACTS_HH__ + +#include <glib.h> +#include <time.h> + +struct _MuContacts; +typedef struct _MuContacts MuContacts; + +#ifdef __cplusplus + +#include <memory> +#include <functional> +#include <chrono> +#include <string> +#include <time.h> +#include <inttypes.h> + +namespace Mu { + +/// Data-structure representing information about some contact. + +struct ContactInfo { + /** + * Construct a new ContactInfo + * + * @param _full_address the full email address + name. + * @param _email email address + * @param _name name or empty + * @param _personal is this a personal contact? + * @param _last_seen when was this contact last seen? + * @param _freq how often was this contact seen? + * + * @return + */ + ContactInfo (const std::string& _full_address, + const std::string& _email, + const std::string& _name, + bool _personal, time_t _last_seen, size_t _freq=1); + + std::string full_address; /**< Full name <email> */ + std::string email; /**< email address */ + std::string name; /**< name (or empty) */ + bool personal; /**< is this a personal contact? */ + time_t last_seen; /**< when was this contact last seen? */ + std::size_t freq; /**< how often was this contact seen? */ + + int64_t tstamp; /**< Time-stamp, as per g_get_monotonic_time */ +}; + +/// All contacts +class Contacts { +public: + /** + * Construct a new contacts objects + * + * @param serialized serialized contacts + */ + Contacts (const std::string& serialized = ""); + + /** + * DTOR + * + */ + ~Contacts (); + + /** + * Add a contact + * + * @param ci A contact-info object + */ + void add(ContactInfo&& ci); + + /** + * Clear all contacts + * + */ + void clear(); + + /** + * Get the number of contacts + * + + * @return number of contacts + */ + std::size_t size() const; + + /** + * Are there no contacts? + * + * @return true or false + */ + bool empty() const { return size() == 0; } + + /** + * Get the contacts, serialized. + * + * @return serialized contacts + */ + std::string serialize() const; + + /** + * Find a contact based on the email address. This is not safe, since + * the returned ptr can be invalidated at any time; only for unit-tests. + * + * @param email email address + * + * @return contact info, or {} if not found + */ + const ContactInfo* _find (const std::string& email) const; + + /** + * Prototype for a callable that receives a contact + * + * @param contact some contact + */ + using EachContactFunc = std::function<void (const ContactInfo& contact_info)>; + + /** + * Invoke some callable for each contact, in order of rank. + * + * @param each_contact + */ + void for_each (const EachContactFunc& each_contact) const; + + /** + * For C compatiblityy + * + * @return a MuContacts* referring to this. + */ + const MuContacts* mu_contacts() const { + return reinterpret_cast<const MuContacts*>(this); + } + + + +private: + struct Private; + std::unique_ptr<Private> priv_; +}; + +} // namespace Mu + +#endif /*__cplusplus*/ + +G_BEGIN_DECLS + + +/** + * return the number of contacts + * + * @param self a contacts object + * + * @return the number of contacts + */ +size_t mu_contacts_count (const MuContacts *self); + +/** + * Function called for mu_contacts_foreach; returns the e-mail address, name + * (which may be NULL) , whether the message is 'personal', the timestamp for + * the address (when it was last seen), and the frequency (in how many message + * did this contact participate) and the tstamp (last modification) + * + */ +typedef void (*MuContactsForeachFunc) (const char *full_address, + const char *email, const char *name, + gboolean personal, + time_t last_seen, unsigned freq, + gint64 tstamp, gpointer user_data); + +/** + * call a function for either each contact, or each contact satisfying + * a regular expression, + * + * @param self contacts object + * @param func callback function to be called for each + * @param user_data user data to pass to the callback + * + * @return TRUE if the function succeeded, or FALSE if the provide regular + * expression was invalid (and not NULL) + */ +gboolean mu_contacts_foreach (const MuContacts *self, + MuContactsForeachFunc func, + gpointer user_data); + +G_END_DECLS + +#endif /* __MU_CONTACTS_HH__ */ diff --git a/lib/mu-container.c b/lib/mu-container.c new file mode 100644 index 0000000..a7e07e3 --- /dev/null +++ b/lib/mu-container.c @@ -0,0 +1,691 @@ +/* +** Copyright (C) 2011-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include <string.h> /* for memset */ +#include <math.h> /* for log, ceil */ + +#include "mu-container.h" +#include "mu-msg.h" +#include "mu-msg-iter.h" + + +/* + * path data structure, to determine the thread paths mentioned above; + * the path is filled as we're traversing the tree of MuContainers + * (messages) + */ +struct _Path { + int *_data; + guint _len; +}; +typedef struct _Path Path; + +static Path* path_new (guint initial); +static void path_destroy (Path *p); +static void path_inc (Path *p, guint index); +static gchar* path_to_string (Path *p, const char* frmt); + +MuContainer* +mu_container_new (MuMsg *msg, guint docid, const char *msgid) +{ + MuContainer *c; + + g_return_val_if_fail (!msg || docid != 0, NULL); + + c = g_slice_new0 (MuContainer); + if (msg) + c->msg = mu_msg_ref (msg); + + c->leader = c; + c->docid = docid; + c->msgid = msgid; + + return c; +} + +void +mu_container_destroy (MuContainer *c) +{ + if (!c) + return; + + if (c->msg) + mu_msg_unref (c->msg); + + g_slice_free (MuContainer, c); +} + + +static void +set_parent (MuContainer *c, MuContainer *parent) +{ + while (c) { + c->parent = parent; + c = c->next; + } +} + + +G_GNUC_UNUSED static gboolean +check_dup (MuContainer *c, GHashTable *hash) +{ + if (g_hash_table_lookup (hash, c)) { + g_warning ("ALREADY!!"); + mu_container_dump (c, TRUE); + g_assert (0); + } else + g_hash_table_insert (hash, c, GUINT_TO_POINTER(TRUE)); + + return TRUE; +} + + +G_GNUC_UNUSED static void +assert_no_duplicates (MuContainer *c) +{ + GHashTable *hash; + + hash = g_hash_table_new (g_direct_hash, g_direct_equal); + + mu_container_foreach (c, + (MuContainerForeachFunc)check_dup, + hash); + + g_hash_table_destroy (hash); +} + + +MuContainer* +mu_container_append_siblings (MuContainer *c, MuContainer *sibling) +{ + g_assert (c); + + g_return_val_if_fail (c, NULL); + g_return_val_if_fail (sibling, NULL); + g_return_val_if_fail (c != sibling, NULL); + + /* assert_no_duplicates (c); */ + + set_parent (sibling, c->parent); + + /* find the last sibling and append; first we try our cache + * 'last', otherwise we need to walk the chain. We use a + * cached last as to avoid walking the chain (which is + * O(n*n)) */ + if (c->last) + c->last->next = sibling; + else { + /* no 'last' cached, so walk the chain */ + MuContainer *c2; + for (c2 = c; c2 && c2->next; c2 = c2->next); + c2->next = sibling; + } + /* update the cached last */ + c->last = sibling->last ? sibling->last : sibling; + + /* assert_no_duplicates (c); */ + + return c; +} + +MuContainer* +mu_container_remove_sibling (MuContainer *c, MuContainer *sibling) +{ + MuContainer *cur, *prev; + + g_return_val_if_fail (c, NULL); + g_return_val_if_fail (sibling, NULL); + + for (prev = NULL, cur = c; cur; cur = cur->next) { + + if (cur == sibling) { + if (!prev) + c = cur->next; + else + prev->next = cur->next; + break; + } + prev = cur; + } + + /* unset the cached last; it's not valid anymore + * + * TODO: we could actually do a better job updating last + * rather than invalidating it. */ + if (c) + c->last = NULL; + + return c; +} + +MuContainer* +mu_container_append_children (MuContainer *c, MuContainer *child) +{ + g_return_val_if_fail (c, NULL); + g_return_val_if_fail (child, NULL); + g_return_val_if_fail (c != child, NULL); + + /* assert_no_duplicates (c); */ + + set_parent (child, c); + if (!c->child) + c->child = child; + else + c->child = mu_container_append_siblings (c->child, child); + + /* assert_no_duplicates (c->child); */ + + return c; +} + + +MuContainer* +mu_container_remove_child (MuContainer *c, MuContainer *child) +{ + g_return_val_if_fail (c, NULL); + g_return_val_if_fail (child, NULL); + + /* g_assert (!child->child); */ + /* g_return_val_if_fail (!child->child, NULL); */ + g_return_val_if_fail (c != child, NULL); + + c->child = mu_container_remove_sibling (c->child, child); + + return c; +} + +typedef void (*MuContainerPathForeachFunc) (MuContainer*, gpointer, Path*); + +static void +mu_container_path_foreach_real (MuContainer *c, guint level, Path *path, + MuContainerPathForeachFunc func, + gpointer user_data) +{ + if (!c) + return; + + path_inc (path, level); + func (c, user_data, path); + + /* children */ + mu_container_path_foreach_real (c->child, level + 1, path, + func, user_data); + + /* siblings */ + mu_container_path_foreach_real (c->next, level, path, func, user_data); +} + +static void +mu_container_path_foreach (MuContainer *c, MuContainerPathForeachFunc func, + gpointer user_data) +{ + Path *path; + + path = path_new (100); + + mu_container_path_foreach_real (c, 0, path, func, user_data); + + path_destroy (path); +} + + +gboolean +mu_container_foreach (MuContainer *c, MuContainerForeachFunc func, + gpointer user_data) +{ + g_return_val_if_fail (func, FALSE); + + if (!c) + return TRUE; + + if (!mu_container_foreach (c->child, func, user_data)) + return FALSE; /* recurse into children */ + + /* recurse into siblings */ + if (!mu_container_foreach (c->next, func, user_data)) + return FALSE; + + return func (c, user_data); +} + +MuContainer* +mu_container_splice_children (MuContainer *c, MuContainer *sibling) +{ + MuContainer *children; + + g_return_val_if_fail (c, NULL); + g_return_val_if_fail (sibling, NULL); + + children = sibling->child; + sibling->child = NULL; + + return mu_container_append_siblings (c, children); +} + +MuContainer* +mu_container_splice_grandchildren (MuContainer *parent, MuContainer *child) +{ + MuContainer *newchild; + + g_return_val_if_fail (parent, NULL); + g_return_val_if_fail (child, NULL); + g_return_val_if_fail (parent != child, NULL); + + newchild = child->child; + child->child=NULL; + + return mu_container_append_children (parent, newchild); +} + + +static GSList* +mu_container_to_list (MuContainer *c) +{ + GSList *lst; + + for (lst = NULL; c; c = c->next) + lst = g_slist_prepend (lst, c); + + return lst; +} + +static gpointer +list_last_data (GSList *lst) +{ + GSList *tail; + + tail = g_slist_last (lst); + + return tail->data; +} + +static MuContainer* +mu_container_from_list (GSList *lst) +{ + MuContainer *c, *cur, *tail; + + if (!lst) + return NULL; + + tail = list_last_data (lst); + for (c = cur = (MuContainer*)lst->data; cur; lst = g_slist_next(lst)) { + cur->next = lst ? (MuContainer*)lst->data : NULL; + cur->last = tail; + cur=cur->next; + } + + return c; +} + +struct _SortFuncData { + MuMsgFieldId mfid; + gboolean descending; + gpointer user_data; +}; +typedef struct _SortFuncData SortFuncData; + +static int +container_cmp (MuContainer *a, MuContainer *b, MuMsgFieldId mfid) +{ + if (a == b) + return 0; + else if (!a->msg) + return -1; + else if (!b->msg) + return 1; + + return mu_msg_cmp (a->msg, b->msg, mfid); +} + +static int +sort_func_root (MuContainer *a, MuContainer *b, SortFuncData *data) +{ + if (data->descending) + return container_cmp (b->leader, a->leader, data->mfid); + else + return container_cmp (a->leader, b->leader, data->mfid); +} + +static int +sort_func_child (MuContainer *a, MuContainer *b, SortFuncData *data) +{ + return container_cmp (a, b, data->mfid); +} + +static MuContainer* +container_sort(MuContainer *c, GCompareDataFunc func, SortFuncData *sfdata) +{ + GSList *lst; + + lst = mu_container_to_list (c); + lst = g_slist_sort_with_data (lst, func, sfdata); + c = mu_container_from_list (lst); + g_slist_free (lst); + + return c; +} + +static MuContainer* +container_sort_child (MuContainer *c, SortFuncData *sfdata) +{ + MuContainer *cur, *leader; + + if (!c) + return NULL; + + /* find leader */ + leader = c->leader; + for (cur = c; cur; cur = cur->next) { + if (cur->child) + cur->child = container_sort_child (cur->child, sfdata); + if (container_cmp (cur->leader, leader, sfdata->mfid) > 0) + leader = cur->leader; + } + + c = container_sort(c, (GCompareDataFunc)sort_func_child, sfdata); + + /* set parent's leader to the one found */ + c->parent->leader = leader; + + return c; +} + +static MuContainer* +container_sort_root (MuContainer *c, SortFuncData *sfdata) +{ + MuContainer *cur; + + if (!c) + return NULL; + + for (cur = c; cur; cur = cur->next) { + if (cur->child) + cur->child = container_sort_child (cur->child, sfdata); + } + + return container_sort (c, (GCompareDataFunc)sort_func_root, sfdata); +} + +MuContainer* +mu_container_sort (MuContainer *c, MuMsgFieldId mfid, gboolean descending, + gpointer user_data) +{ + SortFuncData sfdata; + + sfdata.mfid = mfid; + sfdata.descending = descending; + sfdata.user_data = user_data; + + g_return_val_if_fail (c, NULL); + g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), NULL); + + return container_sort_root (c, &sfdata); +} + + +static gboolean +unequal (MuContainer *a, MuContainer *b) +{ + return a == b ? FALSE : TRUE; +} + + +gboolean +mu_container_reachable (MuContainer *haystack, MuContainer *needle) +{ + g_return_val_if_fail (haystack, FALSE); + g_return_val_if_fail (needle, FALSE); + + if (!mu_container_foreach + (haystack, (MuContainerForeachFunc)unequal, needle)) + return TRUE; + + return FALSE; +} + + +static gboolean +dump_container (MuContainer *c) +{ + const gchar* subject; + + if (!c) { + g_print ("<empty>\n"); + return TRUE; + } + + subject = (c->msg) ? mu_msg_get_subject (c->msg) : "<none>"; + + g_print ("[%s][%s m:%p p:%p docid:%u %s]\n",c->msgid, subject, (void*)c, + (void*)c->parent, c->docid, + c->msg ? mu_msg_get_path (c->msg) : ""); + + return TRUE; +} + + +void +mu_container_dump (MuContainer *c, gboolean recursive) +{ + g_return_if_fail (c); + + if (!recursive) + dump_container (c); + else + mu_container_foreach + (c, + (MuContainerForeachFunc)dump_container, + NULL); +} + + + +static Path* +path_new (guint initial) +{ + Path *p; + + p = g_slice_new0 (Path); + + p->_data = g_new0 (int, initial); + p->_len = initial; + + return p; +} + +static void +path_destroy (Path *p) +{ + if (!p) + return; + + g_free (p->_data); + g_slice_free (Path, p); +} + +static void +path_inc (Path *p, guint index) +{ + if (index + 1 >= p->_len) { + p->_data = g_renew (int, p->_data, 2 * p->_len); + memset (&p->_data[p->_len], 0, p->_len); + p->_len *= 2; + } + + ++p->_data[index]; + p->_data[index + 1] = 0; +} + + +static gchar* +path_to_string (Path *p, const char* frmt) +{ + char *str; + guint u; + + if (!p->_data) + return NULL; + + for (u = 0, str = NULL; p->_data[u] != 0; ++u) { + + char segm[16]; + g_snprintf (segm, sizeof(segm), frmt, p->_data[u] - 1); + + if (!str) + str = g_strdup (segm); + else { + gchar *tmp; + tmp = g_strdup_printf ("%s:%s", str, segm); + g_free (str); + str = tmp; + } + } + + return str; +} + +static unsigned +count_colons (const char *str) +{ + unsigned num; + + num = 0; + while (str++ && *str) + if (*str == ':') + ++num; + + return num; +} + + + +static MuMsgIterThreadInfo* +thread_info_new (gchar *threadpath, gboolean root, gboolean first_child, + gboolean last_child, gboolean empty_parent, + gboolean has_child, gboolean is_dup) +{ + MuMsgIterThreadInfo *ti; + + ti = g_slice_new (MuMsgIterThreadInfo); + ti->threadpath = threadpath; + ti->level = count_colons (threadpath); /* hacky... */ + + ti->prop = MU_MSG_ITER_THREAD_PROP_NONE; + ti->prop |= root ? MU_MSG_ITER_THREAD_PROP_ROOT : 0; + ti->prop |= first_child ? MU_MSG_ITER_THREAD_PROP_FIRST_CHILD : 0; + ti->prop |= last_child ? MU_MSG_ITER_THREAD_PROP_LAST_CHILD : 0; + ti->prop |= empty_parent ? MU_MSG_ITER_THREAD_PROP_EMPTY_PARENT : 0; + ti->prop |= is_dup ? MU_MSG_ITER_THREAD_PROP_DUP : 0; + ti->prop |= has_child ? MU_MSG_ITER_THREAD_PROP_HAS_CHILD : 0; + + return ti; +} + +static void +thread_info_destroy (MuMsgIterThreadInfo *ti) +{ + if (ti) { + g_free (ti->threadpath); + g_slice_free (MuMsgIterThreadInfo, ti); + } +} + + +struct _ThreadInfo { + GHashTable *hash; + const char *format; +}; +typedef struct _ThreadInfo ThreadInfo; + + +static void +add_to_thread_info_hash (GHashTable *thread_info_hash, MuContainer *c, + char *threadpath) +{ + gboolean is_root, first_child, last_child, empty_parent, is_dup, has_child; + + /* 'root' means we're a child of the dummy root-container */ + is_root = (c->parent == NULL); + + first_child = is_root ? FALSE : (c->parent->child == c); + last_child = is_root ? FALSE : (c->next == NULL); + empty_parent = is_root ? FALSE : (!c->parent->msg); + is_dup = c->flags & MU_CONTAINER_FLAG_DUP; + has_child = c->child ? TRUE : FALSE; + + g_hash_table_insert (thread_info_hash, + GUINT_TO_POINTER(c->docid), + thread_info_new (threadpath, + is_root, + first_child, + last_child, + empty_parent, + has_child, + is_dup)); +} + +/* device a format string that is the minimum size to fit up to + * matchnum matches -- returns static memory */ +static const char* +thread_segment_format_string (size_t matchnum) +{ + unsigned digitnum; + static char frmt[16]; + + /* get the number of digits needed in a hex-representation of + * matchnum */ + digitnum = (unsigned) (ceil (log(matchnum)/log(16))); + g_snprintf (frmt, sizeof(frmt), "%%0%ux", digitnum); + + return frmt; +} + +static gboolean +add_thread_info (MuContainer *c, ThreadInfo *ti, Path *path) +{ + gchar *pathstr; + + pathstr = path_to_string (path, ti->format); + add_to_thread_info_hash (ti->hash, c, pathstr); + + return TRUE; +} + + +GHashTable* +mu_container_thread_info_hash_new (MuContainer *root_set, size_t matchnum) +{ + ThreadInfo ti; + + g_return_val_if_fail (root_set, NULL); + g_return_val_if_fail (matchnum > 0, NULL); + + /* create hash docid => thread-info */ + ti.hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, + (GDestroyNotify)thread_info_destroy); + + ti.format = thread_segment_format_string (matchnum); + + mu_container_path_foreach (root_set, + (MuContainerPathForeachFunc)add_thread_info, + &ti); + + return ti.hash; +} diff --git a/lib/mu-container.h b/lib/mu-container.h new file mode 100644 index 0000000..69c1950 --- /dev/null +++ b/lib/mu-container.h @@ -0,0 +1,224 @@ +/* +** Copyright (C) 2011-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_CONTAINER_H__ +#define __MU_CONTAINER_H__ + +#include <glib.h> +#include <mu-msg.h> + +enum _MuContainerFlag { + MU_CONTAINER_FLAG_NONE = 0, + MU_CONTAINER_FLAG_DELETE = 1 << 0, + MU_CONTAINER_FLAG_SPLICE = 1 << 1, + MU_CONTAINER_FLAG_DUP = 1 << 2 +}; +typedef enum _MuContainerFlag MuContainerFlag; + +/* + * MuContainer data structure, as seen in JWZs document: + * http://www.jwz.org/doc/threading.html + */ +struct _MuContainer { + struct _MuContainer *parent, *child, *next; + + /* note: we cache the last of the string of next->next->... + * `mu_container_append_siblings' shows up high in the + * profiles since it needs to walk to the end, and this give + * O(n*n) behavior. + * */ + struct _MuContainer *last; + + /* Node in the subtree rooted at this node which comes first + * in the descending sort order, e.g. the latest message if + * sorting by date. We compare the leaders when ordering + * subtrees. */ + struct _MuContainer *leader; + + MuMsg *msg; + const char *msgid; + + unsigned docid; + MuContainerFlag flags; + +}; +typedef struct _MuContainer MuContainer; + + +/** + * create a new Container object + * + * @param msg a MuMsg, or NULL; when it's NULL, docid should be 0 + * @param docid a Xapian docid, or 0 + * @param msgid a message id, or NULL + * + * @return a new Container instance, or NULL in case of error; free + * with mu_container_destroy + */ +MuContainer* mu_container_new (MuMsg *msg, guint docid, const char* msgid); + + +/** + * free a Container object + * + * @param c a Container object, or NULL + */ +void mu_container_destroy (MuContainer *c); + + + +/** + * append new child(ren) to this container; the child(ren) container's + * parent pointer will point to this one + * + * @param c a Container instance + * @param child a child + * + * @return the Container instance with a child added + */ +MuContainer* mu_container_append_children (MuContainer *c, MuContainer *child); + +/** + * append a new sibling to this (list of) containers; all the siblings + * will get the same parent that @c has + * + * @param c a container instance + * @param sibling a sibling + * + * @return the container (list) with the sibling(s) appended + */ +MuContainer* mu_container_append_siblings (MuContainer *c, MuContainer *sibling); + +/** + * remove a _single_ child container from a container + * + * @param c a container instance + * @param child the child container to remove + * + * @return the container with the child removed; if the container did + * have this child, nothing changes + */ +MuContainer* mu_container_remove_child (MuContainer *c, MuContainer *child); + +/** + * remove a _single_ sibling container from a container + * + * @param c a container instance + * @param sibling the sibling container to remove + * + * @return the container with the sibling removed; if the container did + * have this sibling, nothing changes + */ +MuContainer* mu_container_remove_sibling (MuContainer *c, MuContainer *sibling); + +/** + * promote sibling's children to be this container's siblings + * + * @param c a container instance + * @param sibling a sibling of this container + * + * @return the container with the sibling's children promoted + */ + +MuContainer* mu_container_splice_children (MuContainer *c, + MuContainer *sibling); + +/** + * promote child's children to be parent's children + * + * @param parent a container instance + * @param child a child of this container + * + * @return the new container with it's children's children promoted + */ +MuContainer* mu_container_splice_grandchildren (MuContainer *parent, + MuContainer *child); + +typedef gboolean (*MuContainerForeachFunc) (MuContainer*, gpointer); + +/** + * execute some function on all siblings an children of some container + * (recursively) until all children have been visited or the callback + * function returns FALSE + * + * @param c a container + * @param func a function to call for each container + * @param user_data a pointer to pass to the callback function + * + * @return + */ +gboolean mu_container_foreach (MuContainer *c, + MuContainerForeachFunc func, + gpointer user_data); + +/** + * check whether container needle is a child or sibling (recursively) + * of container haystack + * + * @param haystack a container + * @param needle a container + * + * @return TRUE if needle is reachable from haystack, FALSE otherwise + */ +gboolean mu_container_reachable (MuContainer *haystack, MuContainer *needle); + + +/** + * dump the container to stdout (for debugging) + * + * @param c a container + * @param recursive whether to include siblings, children + */ +void mu_container_dump (MuContainer *c, gboolean recursive); + + +typedef int (*MuContainerCmpFunc) (MuContainer *c1, MuContainer *c2, + gpointer user_data); + +/** + * sort the tree of MuContainers, recursively; ie. each of the list of + * siblings (children) will be sorted according to @func; if the + * container is empty, the first non-empty 'leftmost' child is used. + * + * @param c a container + * @param mfid the field to sort by + * @param revert if TRUE, revert the sorting order * + * @param user_data a user pointer to pass to the sorting function + * + * @return a sorted container + */ +MuContainer* mu_container_sort (MuContainer *c, MuMsgFieldId mfid, + gboolean revert, + gpointer user_data); + + +/** + * create a hashtable with maps document-ids to information about them, + * ie. Xapian docid => MuMsgIterThreadInfo + * + * @param root_set the containers @param matchnum the number of + * matches in the list (this is needed to determine the shortest + * possible collation keys ('threadpaths') for the messages + * + * @return a hash; free with g_hash_table_destroy + */ +GHashTable* mu_container_thread_info_hash_new (MuContainer *root_set, + size_t matchnum); + +#endif /*__MU_CONTAINER_H__*/ diff --git a/lib/mu-flags.c b/lib/mu-flags.c new file mode 100644 index 0000000..330fa31 --- /dev/null +++ b/lib/mu-flags.c @@ -0,0 +1,241 @@ +/* +** Copyright (C) 2011-2012 <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include <string.h> +#include "mu-flags.h" + +struct _FlagInfo { + MuFlags flag; + char kar; + const char *name; + MuFlagType flag_type; +}; +typedef struct _FlagInfo FlagInfo; + +static const FlagInfo FLAG_INFO[] = { + + /* NOTE: order of this is significant, due to optimizations + * below */ + + { MU_FLAG_DRAFT, 'D', "draft", MU_FLAG_TYPE_MAILFILE }, + { MU_FLAG_FLAGGED, 'F', "flagged", MU_FLAG_TYPE_MAILFILE }, + { MU_FLAG_PASSED, 'P', "passed", MU_FLAG_TYPE_MAILFILE }, + { MU_FLAG_REPLIED, 'R', "replied", MU_FLAG_TYPE_MAILFILE }, + { MU_FLAG_SEEN, 'S', "seen", MU_FLAG_TYPE_MAILFILE }, + { MU_FLAG_TRASHED, 'T', "trashed", MU_FLAG_TYPE_MAILFILE }, + + { MU_FLAG_NEW, 'N', "new", MU_FLAG_TYPE_MAILDIR }, + + { MU_FLAG_SIGNED, 'z', "signed", MU_FLAG_TYPE_CONTENT }, + { MU_FLAG_ENCRYPTED, 'x', "encrypted", MU_FLAG_TYPE_CONTENT }, + { MU_FLAG_HAS_ATTACH, 'a', "attach", MU_FLAG_TYPE_CONTENT }, + { MU_FLAG_LIST, 'l', "list", MU_FLAG_TYPE_CONTENT }, + + + { MU_FLAG_UNREAD, 'u', "unread", MU_FLAG_TYPE_PSEUDO } +}; + + +MuFlagType +mu_flag_type (MuFlags flag) +{ + unsigned u; + + for (u = 0; u != G_N_ELEMENTS (FLAG_INFO); ++u) + if (FLAG_INFO[u].flag == flag) + return FLAG_INFO[u].flag_type; + + return MU_FLAG_TYPE_INVALID; +} + + +char +mu_flag_char (MuFlags flag) +{ + unsigned u; + + for (u = 0; u != G_N_ELEMENTS (FLAG_INFO); ++u) + if (FLAG_INFO[u].flag == flag) + return FLAG_INFO[u].kar; + return 0; +} + + +MuFlags +mu_flag_char_from_name (const char *str) +{ + unsigned u; + + g_return_val_if_fail (str, MU_FLAG_INVALID); + + for (u = 0; u != G_N_ELEMENTS (FLAG_INFO); ++u) + if (g_strcmp0(FLAG_INFO[u].name, str) == 0) + return FLAG_INFO[u].kar; + + return 0; +} + + +static MuFlags +mu_flag_from_char (char kar) +{ + unsigned u; + + for (u = 0; u != G_N_ELEMENTS (FLAG_INFO); ++u) + if (FLAG_INFO[u].kar == kar) + return FLAG_INFO[u].flag; + + return MU_FLAG_INVALID; +} + + +const char* +mu_flag_name (MuFlags flag) +{ + unsigned u; + + for (u = 0; u != G_N_ELEMENTS (FLAG_INFO); ++u) + if (FLAG_INFO[u].flag == flag) + return FLAG_INFO[u].name; + + return NULL; +} + + +const char* +mu_flags_to_str_s (MuFlags flags, MuFlagType types) +{ + unsigned u,v; + static char str[sizeof(FLAG_INFO) + 1]; + + for (u = 0, v = 0; u != G_N_ELEMENTS(FLAG_INFO); ++u) + if (flags & FLAG_INFO[u].flag && + types & FLAG_INFO[u].flag_type) + str[v++] = FLAG_INFO[u].kar; + str[v] = '\0'; + + return str; +} + + +MuFlags +mu_flags_from_str (const char *str, MuFlagType types, + gboolean ignore_invalid) +{ + const char *cur; + MuFlags flag; + + g_return_val_if_fail (str, MU_FLAG_INVALID); + + for (cur = str, flag = MU_FLAG_NONE; *cur; ++cur) { + + MuFlags f; + + f = mu_flag_from_char (*cur); + + if (f == MU_FLAG_INVALID) { + if (ignore_invalid) + continue; + return MU_FLAG_INVALID; + } + + if (mu_flag_type (f) & types) + flag |= f; + } + + return flag; +} + + + +char* +mu_flags_custom_from_str (const char *str) +{ + char *custom; + const char* cur; + unsigned u; + + g_return_val_if_fail (str, NULL); + + for (cur = str, u = 0, custom = NULL; *cur; ++cur) { + + MuFlags flag; + flag = mu_flag_from_char (*cur); + + /* if it's a valid file flag, ignore it */ + if (flag != MU_FLAG_INVALID && + mu_flag_type (flag) == MU_FLAG_TYPE_MAILFILE) + continue; + + /* otherwise, add it to our custom string */ + if (!custom) + custom = g_new0 (char, strlen(str) + 1); + custom[u++] = *cur; + } + + return custom; +} + + + +void +mu_flags_foreach (MuFlagsForeachFunc func, gpointer user_data) +{ + unsigned u; + + g_return_if_fail (func); + + for (u = 0; u != G_N_ELEMENTS(FLAG_INFO); ++u) + func (FLAG_INFO[u].flag, user_data); +} + + +MuFlags +mu_flags_from_str_delta (const char *str, MuFlags oldflags, + MuFlagType types) +{ + const char *cur; + MuFlags newflags; + + g_return_val_if_fail (str, MU_FLAG_INVALID); + + for (cur = str, newflags = oldflags; *cur; ++cur) { + + MuFlags f; + if (*cur == '+' || *cur == '-') { + f = mu_flag_from_char (cur[1]); + if (f == 0) + goto error; + if (*cur == '+') + newflags |= f; + else + newflags &= ~f; + ++cur; + continue; + } + + goto error; + } + + return newflags; +error: + g_warning ("invalid flag string"); + return MU_FLAG_INVALID; + +} diff --git a/lib/mu-flags.h b/lib/mu-flags.h new file mode 100644 index 0000000..9d892f3 --- /dev/null +++ b/lib/mu-flags.h @@ -0,0 +1,184 @@ +/* +** Copyright (C) 2011-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + + +#ifndef __MU_FLAGS_H__ +#define __MU_FLAGS_H__ + +#include <glib.h> + +G_BEGIN_DECLS + +enum _MuFlags { + MU_FLAG_NONE = 0, + + /* next 6 are seen in the file-info part of maildir message + * file names, ie., in a name like "1234345346:2,<fileinfo>", + * <fileinfo> consists of zero or more of the following + * characters (in ascii order) */ + MU_FLAG_DRAFT = 1 << 0, + MU_FLAG_FLAGGED = 1 << 1, + MU_FLAG_PASSED = 1 << 2, + MU_FLAG_REPLIED = 1 << 3, + MU_FLAG_SEEN = 1 << 4, + MU_FLAG_TRASHED = 1 << 5, + + /* decides on cur/ or new/ in the maildir */ + MU_FLAG_NEW = 1 << 6, + + /* content flags -- not visible in the filename, but used for + * searching */ + MU_FLAG_SIGNED = 1 << 7, + MU_FLAG_ENCRYPTED = 1 << 8, + MU_FLAG_HAS_ATTACH = 1 << 9, + + /* pseudo-flag, only for queries, so we can search for + * flag:unread, which is equivalent to 'flag:new OR NOT + * flag:seen' */ + MU_FLAG_UNREAD = 1 << 10, + + /* other content flags */ + MU_FLAG_LIST = 1 << 11 +}; +typedef enum _MuFlags MuFlags; + +#define MU_FLAG_INVALID ((MuFlags)-1) + +enum _MuFlagType { + MU_FLAG_TYPE_MAILFILE = 1 << 0, + MU_FLAG_TYPE_MAILDIR = 1 << 1, + MU_FLAG_TYPE_CONTENT = 1 << 2, + MU_FLAG_TYPE_PSEUDO = 1 << 3 +}; +typedef enum _MuFlagType MuFlagType; + +#define MU_FLAG_TYPE_ANY ((MuFlagType)-1) +#define MU_FLAG_TYPE_INVALID ((MuFlagType)-1) + + +/** + * Get the type of flag (mailfile, maildir, pseudo or content) + * + * @param flag a MuFlag + * + * @return the flag type or MU_FLAG_TYPE_INVALID in case of error + */ +MuFlagType mu_flag_type (MuFlags flag) G_GNUC_CONST; + + +/** + * Get the flag character + * + * @param flag a MuFlag (single) + * + * @return the character, or 0 if it's not a valid flag + */ +char mu_flag_char (MuFlags flag) G_GNUC_CONST; + + +/** + * Get the flag name + * + * @param flag a single MuFlag + * + * @return the name (don't free) as string or NULL in case of error + */ +const char* mu_flag_name (MuFlags flag) G_GNUC_CONST; + + +/** + * Get the string representation of an OR'ed set of flags + * + * @param flags MuFlag (OR'ed) + * @param types allowable types (OR'ed) for the result; the rest is ignored + * + * @return The string representation (static, don't free), or NULL in + * case of error + */ +const char* mu_flags_to_str_s (MuFlags flags, MuFlagType types); + + +/** + * Get the (OR'ed) flags corresponding to a string representation + * + * @param str the file info string + * @param types the flag types to accept (other will be ignored) + * @param ignore invalid if TRUE, ignore invalid flags, otherwise return + * MU_FLAG_INVALID if an invalid flag is encountered + * + * @return the (OR'ed) flags + */ +MuFlags mu_flags_from_str (const char *str, MuFlagType types, + gboolean ignore_invalid); + + + + +/** + * Get the MuFlag char for some flag name + * + * @param str a flag name + * + * @return a flag character, or 0 + */ +MuFlags mu_flag_char_from_name (const char *str); + + +/** + * return the concatenation of all non-standard file flags in str + * (ie., characters other than DFPRST) as a newly allocated string. + * + * @param str the file info string + * + * @return concatenation of all non-standard flags, as a string; free + * with g_free when done. If there are no such flags, return NULL. + */ +char* mu_flags_custom_from_str (const char *str) G_GNUC_WARN_UNUSED_RESULT; + + +/** + * Update #oldflags with the flags in #str, where #str consists of the + * the normal flag characters, but prefixed with either '+' or '-', + * which means resp. "add this flag" or "remove this flag" from + * oldflags. So, e.g. "-N+S" would unset the NEW flag and set the + * SEEN flag, without affecting other flags. + * + * @param str the string representation + * @param old flags to update + * @param types the flag types to accept (other will be ignored) + * + * @return + */ +MuFlags mu_flags_from_str_delta (const char *str, MuFlags oldflags, + MuFlagType types); + + +typedef void (*MuFlagsForeachFunc) (MuFlags flag, gpointer user_data); + +/** + * call a function for each available flag + * + * @param func a function to call + * @param user_data a user pointer to pass to the function + */ +void mu_flags_foreach (MuFlagsForeachFunc func, gpointer user_data); + +G_END_DECLS + +#endif /*__MU_FLAGS_H__*/ diff --git a/lib/mu-index.c b/lib/mu-index.c new file mode 100644 index 0000000..33aaffe --- /dev/null +++ b/lib/mu-index.c @@ -0,0 +1,475 @@ +/* +** Copyright (C) 2008-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** This program is free software; you can redistribute it and/or modify +1** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include "config.h" +#include "mu-index.h" + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <glib.h> +#include <glib/gstdio.h> +#include <errno.h> + +#include "mu-maildir.h" + +#define MU_LAST_USED_MAILDIR_KEY "last_used_maildir" +#define MU_INDEX_MAX_FILE_SIZE (500*1000*1000) /* 500 Mb */ +/* apparently, people are getting really big mails, so let us index those (by + * default)*/ + +struct _MuIndex { + MuStore *_store; + gboolean _needs_reindex; + guint _max_filesize; +}; + +MuIndex* +mu_index_new (MuStore *store, GError **err) +{ + MuIndex *index; + unsigned count; + + g_return_val_if_fail (store, NULL); + g_return_val_if_fail (!mu_store_is_read_only(store), NULL); + + index = g_new0 (MuIndex, 1); + + index->_store = mu_store_ref (store); + + /* set the default max file size */ + index->_max_filesize = MU_INDEX_MAX_FILE_SIZE; + + count = mu_store_count (store, err); + if (count == (unsigned)-1) + return NULL; + else if (count == 0) + index->_needs_reindex = TRUE; + + return index; +} + +void +mu_index_destroy (MuIndex *index) +{ + if (!index) + return; + + mu_store_unref (index->_store); + g_free (index); +} + + +struct _MuIndexCallbackData { + MuIndexMsgCallback _idx_msg_cb; + MuIndexDirCallback _idx_dir_cb; + MuStore* _store; + void* _user_data; + MuIndexStats* _stats; + gboolean _reindex; + gboolean _lazy_check; + time_t _dirstamp; + guint _max_filesize; +}; +typedef struct _MuIndexCallbackData MuIndexCallbackData; + + +/* checks to determine if we need to (re)index this message note: + * simply checking timestamps is not good enough because message may + * be moved from other dirs (e.g. from 'new' to 'cur') and the time + * stamps won't change. */ +static inline gboolean +needs_index (MuIndexCallbackData *data, const char *fullpath, + time_t filestamp) +{ + /* unconditionally reindex */ + if (data->_reindex) + return TRUE; + + /* it's not in the database yet */ + if (!mu_store_contains_message (data->_store, fullpath)) + return TRUE; + + /* it's there, but it's not up to date */ + if ((unsigned)filestamp >= (unsigned)data->_dirstamp) + return TRUE; + + return FALSE; /* index not needed */ +} + + +static MuError +insert_or_update_maybe (const char *fullpath, const char *mdir, + time_t filestamp, MuIndexCallbackData *data, + gboolean *updated) +{ + MuMsg *msg; + GError *err; + gboolean rv; + + *updated = FALSE; + if (!needs_index (data, fullpath, filestamp)) + return MU_OK; /* nothing to do for this one */ + + err = NULL; + msg = mu_msg_new_from_file (fullpath, mdir, &err); + if (!msg) { + if (!err) + g_warning ("error creating message object: %s", + fullpath); + else { + g_warning ("%s", err->message); + g_clear_error (&err); + } + /* warn, then simply continue */ + return MU_OK; + } + + /* we got a valid id; scan the message contents as well */ + rv = mu_store_add_msg (data->_store, msg, &err); + mu_msg_unref (msg); + + if (!rv) { + g_warning ("error storing message object: %s", + err ? err->message : "cause unknown"); + g_clear_error (&err); + return MU_ERROR; + } + + *updated = TRUE; + return MU_OK; +} + + +static MuError +run_msg_callback_maybe (MuIndexCallbackData *data) +{ + MuError result; + + if (!data || !data->_idx_msg_cb) + return MU_OK; + + result = data->_idx_msg_cb (data->_stats, data->_user_data); + if (G_UNLIKELY(result != MU_OK && result != MU_STOP)) + g_warning ("error in callback"); + + return result; +} + + +static MuError +on_run_maildir_msg (const char *fullpath, const char *mdir, + struct stat *statbuf, MuIndexCallbackData *data) +{ + MuError result; + gboolean updated; + + /* protect against too big messages */ + if (G_UNLIKELY(statbuf->st_size > data->_max_filesize)) { + g_warning ("ignoring because bigger than %u bytes: %s", + data->_max_filesize, fullpath); + return MU_OK; /* not an error */ + } + + result = run_msg_callback_maybe (data); + if (result != MU_OK) + return result; + + /* see if we need to update/insert anything... + * use the ctime, so any status change will be visible (perms, + * filename etc.)*/ + result = insert_or_update_maybe (fullpath, mdir, statbuf->st_ctime, + data, &updated); + + if (result == MU_OK && data && data->_stats) { /* update statistics */ + ++data->_stats->_processed; + updated ? ++data->_stats->_updated : ++data->_stats->_uptodate; + } + + return result; +} + +static time_t +get_dir_timestamp (const char *path) +{ + struct stat statbuf; + + if (stat (path, &statbuf) != 0) { + g_warning ("failed to stat %s: %s", + path, strerror(errno)); + return 0; + } + + return statbuf.st_ctime; +} + +static MuError +on_run_maildir_dir (const char* fullpath, gboolean enter, + MuIndexCallbackData *data) +{ + GError *err; + + err = NULL; + + /* xapian stores a per-dir timestamp; we use this timestamp to determine + * whether a message is up-to-date + */ + if (enter) { + data->_dirstamp = + mu_store_get_dirstamp (data->_store, fullpath, &err); + /* in 'lazy' mode, we only check the dir timestamp, and if it's + * up to date, we don't bother with this dir. This fails to + * account for messages below this dir that have merely + * _changed_ though */ + if (data->_lazy_check && mu_maildir_is_leaf_dir(fullpath)) { + time_t dirstamp; + dirstamp = get_dir_timestamp (fullpath); + if (dirstamp <= data->_dirstamp) { + g_debug ("ignore %s (up-to-date)", fullpath); + return MU_IGNORE; + } + } + g_debug ("entering %s", fullpath); + } else { + mu_store_set_dirstamp (data->_store, fullpath, + time(NULL), &err); + g_debug ("leaving %s", fullpath); + } + + if (data->_idx_dir_cb) + return data->_idx_dir_cb (fullpath, enter, + data->_user_data); + + if (err) { + MU_WRITE_LOG ("%s: %s", __func__, err->message); + g_clear_error(&err); + } + + return MU_OK; +} + +static gboolean +check_path (const char *path) +{ + g_return_val_if_fail (path, FALSE); + + if (!g_path_is_absolute (path)) { + g_warning ("%s: not an absolute path: '%s'", __func__, path); + return FALSE; + } + + if (access (path, R_OK) != 0) { + g_warning ("%s: cannot open '%s': %s", + __func__, path, strerror (errno)); + return FALSE; + } + + return TRUE; +} + +static void +init_cb_data (MuIndexCallbackData *cb_data, MuStore *xapian, + gboolean reindex, gboolean lazycheck, + guint max_filesize, MuIndexStats *stats, + MuIndexMsgCallback msg_cb, MuIndexDirCallback dir_cb, + void *user_data) +{ + cb_data->_idx_msg_cb = msg_cb; + cb_data->_idx_dir_cb = dir_cb; + + cb_data->_user_data = user_data; + cb_data->_store = xapian; + + cb_data->_reindex = reindex; + cb_data->_lazy_check = lazycheck; + cb_data->_dirstamp = 0; + cb_data->_max_filesize = max_filesize; + + cb_data->_stats = stats; + if (cb_data->_stats) + memset (cb_data->_stats, 0, sizeof(MuIndexStats)); +} + + +void +mu_index_set_max_msg_size (MuIndex *index, guint max_size) +{ + g_return_if_fail (index); + + if (max_size == 0) + index->_max_filesize = MU_INDEX_MAX_FILE_SIZE; + else + index->_max_filesize = max_size; +} + + +MuError +mu_index_run (MuIndex *index, gboolean reindex, gboolean lazycheck, + MuIndexStats *stats, + MuIndexMsgCallback msg_cb, MuIndexDirCallback dir_cb, + void *user_data) +{ + MuIndexCallbackData cb_data; + MuError rv; + const char *path; + + g_return_val_if_fail (index && index->_store, MU_ERROR); + g_return_val_if_fail (msg_cb, MU_ERROR); + + path = mu_store_root_maildir (index->_store); + if (!check_path (path)) + return MU_ERROR; + + if (index->_needs_reindex) + reindex = TRUE; + + init_cb_data (&cb_data, index->_store, reindex, lazycheck, + index->_max_filesize, stats, + msg_cb, dir_cb, user_data); + + rv = mu_maildir_walk (path, + (MuMaildirWalkMsgCallback)on_run_maildir_msg, + (MuMaildirWalkDirCallback)on_run_maildir_dir, + reindex, /* re-index, ie. do a full update */ + &cb_data); + + mu_store_flush (index->_store); + + return rv; +} + +static MuError +on_stats_maildir_file (const char *fullpath, const char *mdir, + struct stat *statbuf, + MuIndexCallbackData *cb_data) +{ + MuError result; + + if (cb_data && cb_data->_idx_msg_cb) + result = cb_data->_idx_msg_cb (cb_data->_stats, + cb_data->_user_data); + else + result = MU_OK; + + if (result == MU_OK) { + if (cb_data->_stats) + ++cb_data->_stats->_processed; + return MU_OK; + } + + return result; /* MU_STOP or MU_OK */ +} + + +MuError +mu_index_stats (MuIndex *index, + MuIndexStats *stats, MuIndexMsgCallback cb_msg, + MuIndexDirCallback cb_dir, void *user_data) +{ + const char *path; + MuIndexCallbackData cb_data; + + g_return_val_if_fail (index, MU_ERROR); + g_return_val_if_fail (cb_msg, MU_ERROR); + + path = mu_store_root_maildir (index->_store); + if (!check_path (path)) + return MU_ERROR; + + if (stats) + memset (stats, 0, sizeof(MuIndexStats)); + + cb_data._idx_msg_cb = cb_msg; + cb_data._idx_dir_cb = cb_dir; + + cb_data._stats = stats; + cb_data._user_data = user_data; + + cb_data._dirstamp = 0; + + return mu_maildir_walk (path, + (MuMaildirWalkMsgCallback)on_stats_maildir_file, + NULL, FALSE, &cb_data); +} + +struct _CleanupData { + MuStore *_store; + MuIndexStats *_stats; + MuIndexCleanupDeleteCallback _cb; + void *_user_data; + +}; +typedef struct _CleanupData CleanupData; + + +static MuError +foreach_doc_cb (const char* path, CleanupData *cudata) +{ + if (access (path, R_OK) != 0) { + if (errno != EACCES) + g_debug ("cannot access %s: %s", path, strerror(errno)); + if (!mu_store_remove_path (cudata->_store, path)) + return MU_ERROR; /* something went wrong... bail out */ + if (cudata->_stats) + ++cudata->_stats->_cleaned_up; + } + + if (cudata->_stats) + ++cudata->_stats->_processed; + + if (!cudata->_cb) + return MU_OK; + + return cudata->_cb (cudata->_stats, cudata->_user_data); +} + + +MuError +mu_index_cleanup (MuIndex *index, MuIndexStats *stats, + MuIndexCleanupDeleteCallback cb, + void *user_data, GError **err) +{ + MuError rv; + CleanupData cudata; + + g_return_val_if_fail (index, MU_ERROR); + + cudata._store = index->_store; + cudata._stats = stats; + cudata._cb = cb; + cudata._user_data = user_data; + + rv = mu_store_foreach (index->_store, + (MuStoreForeachFunc)foreach_doc_cb, + &cudata, err); + + mu_store_flush (index->_store); + + return rv; +} + +gboolean +mu_index_stats_clear (MuIndexStats *stats) +{ + if (!stats) + return FALSE; + + memset (stats, 0, sizeof(MuIndexStats)); + return TRUE; +} diff --git a/lib/mu-index.h b/lib/mu-index.h new file mode 100644 index 0000000..c0faba8 --- /dev/null +++ b/lib/mu-index.h @@ -0,0 +1,193 @@ +/* +** Copyright (C) 2008-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_INDEX_H__ +#define __MU_INDEX_H__ + +#include <stdlib.h> +#include <glib.h> +#include <utils/mu-util.h> +#include <mu-store.hh> + +G_BEGIN_DECLS + +/* opaque structure */ +struct _MuIndex; +typedef struct _MuIndex MuIndex; + +struct _MuIndexStats { + unsigned _processed; /* number of msgs processed or counted */ + unsigned _updated; /* number of msgs new or updated */ + unsigned _cleaned_up; /* number of msgs cleaned up */ + unsigned _uptodate; /* number of msgs already up-to-date */ +}; +typedef struct _MuIndexStats MuIndexStats; + +/** + * create a new MuIndex instance. NOTE: the database does not have + * to exist yet, but the directory must already exist; NOTE(2): before + * doing anything with the returned Index object, make sure you haved + * called mu_msg_init somewhere in your code. + * + * @param store a writable MuStore object + * @param err to receive error or NULL; there are only errors when this + * function returns NULL. Possible errors: see mu-error.h + * + * @return a new MuIndex instance, or NULL in case of error + */ +MuIndex* mu_index_new (MuStore *store, GError **err) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + + +/** + * destroy the index instance + * + * @param index a MuIndex instance, or NULL + */ +void mu_index_destroy (MuIndex *index); + + +/** + * change the maximum file size that mu-index considers from its + * default (MU_INDEX_MAX_FILE_SIZE). Note that the maximum size is a + * protection against mu (or the libraries it uses) allocating too + * much memory, which can lead to problems + * + * @param index a mu index object + * @param max_size the maximum msg size, or 0 to reset to the default + */ +void mu_index_set_max_msg_size (MuIndex *index, guint max_size); + + +/** + * callback function for mu_index_(run|stats|cleanup), for each message + * + * @param stats pointer to structure to receive statistics data + * @param user_data pointer to user data + * + * @return MU_OK to continue, MU_STOP to stop, or MU_ERROR in + * case of some error. + */ +typedef MuError (*MuIndexMsgCallback) (MuIndexStats* stats, void *user_data); + + +/** + * callback function for mu_index_(run|stats|cleanup), for each dir enter/leave + * + * @param path dirpath we just entered / left + * @param enter did we enter (TRUE) or leave(FALSE) the dir? + * @param user_data pointer to user data + * + * @return MU_OK to continue, MU_STOP to stopd or MU_ERROR in + * case of some error. + */ +typedef MuError (*MuIndexDirCallback) (const char* path, gboolean enter, + void *user_data); + +/** + * start the indexing process + * + * @param index a valid MuIndex instance + * @param force if != 0, force re-indexing already index messages; this is + * obviously a lot slower than only indexing new/changed messages + * @param lazycheck whether ignore subdirectoryies that have up-to-date + * timestamps. + * @param stats a structure with some statistics about the results; + * note that this function does *not* reset the struct values to allow + * for cumulative stats from multiple calls. If needed, you can use + * @mu_index_stats_clear before calling this function + * @param cb_msg a callback function called for every msg indexed; + * @param cb_dir a callback function called for every dir entered/left or NULL + * @param user_data a user pointer that will be passed to the callback function + * + * @return MU_OK if the stats gathering was completed successfully, + * MU_STOP if the user stopped or MU_ERROR in + * case of some error. + */ +MuError mu_index_run (MuIndex *index, gboolean force, + gboolean lazycheck, MuIndexStats *stats, + MuIndexMsgCallback msg_cb, + MuIndexDirCallback dir_cb, void *user_data); + +/** + * gather some statistics about the Maildir; this is usually much faster than + * mu_index_run, and can thus be used to provide some information to the user + * note though that the statistics may be different from the reality that + * mu_index_run sees, when there are updates in the Maildir + * + * @param index a valid MuIndex instance + * @param stats a structure with some statistics about the results; + * note that this function does *not* reset the struct values to allow + * for cumulative stats from multiple calls. If needed, you can use + * @mu_index_stats_clear before calling this function + * @param msg_cb a callback function which will be called for every msg; + * @param dir_cb a callback function which will be called for every dir or NULL + * @param user_data a user pointer that will be passed to the callback function + * xb + * @return MU_OK if the stats gathering was completed successfully, + * MU_STOP if the user stopped or MU_ERROR in + * case of some error. + */ +MuError mu_index_stats (MuIndex *index, MuIndexStats *stats, + MuIndexMsgCallback msg_cb, MuIndexDirCallback dir_cb, + void *user_data); + +/** + * callback function called for each message + * + * @param MuIndexCleanupCallback + * + * @return a MuResult + */ +typedef MuError (*MuIndexCleanupDeleteCallback) (MuIndexStats *stats, + void *user_data); + +/** + * cleanup the database; ie. remove entries for which no longer a corresponding + * file exists in the maildir + * + * @param index a valid MuIndex instance + * @param stats a structure with some statistics about the results; + * note that this function does *not* reset the struct values to allow + * for cumulative stats from multiple calls. If needed, you can use + * @mu_index_stats_clear before calling this function + * @param cb a callback function which will be called for every msg; + * @param user_data a user pointer that will be passed to the callback function + * @param err to receive error info or NULL. err->code is MuError value + * + * @return MU_OK if the stats gathering was completed successfully, + * MU_STOP if the user stopped or MU_ERROR in + * case of some error. + */ +MuError mu_index_cleanup (MuIndex *index, MuIndexStats *stats, + MuIndexCleanupDeleteCallback cb, + void *user_data, GError **err); + +/** + * clear the stats structure + * + * @param stats a MuIndexStats object + * + * @return TRUE if stats != NULL, FALSE otherwise + */ +gboolean mu_index_stats_clear (MuIndexStats *stats); + +G_END_DECLS + +#endif /*__MU_INDEX_H__*/ diff --git a/lib/mu-maildir.c b/lib/mu-maildir.c new file mode 100644 index 0000000..c8c74f4 --- /dev/null +++ b/lib/mu-maildir.c @@ -0,0 +1,943 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2008-2016 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, 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 59the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> + +#include <string.h> +#include <errno.h> +#include <glib/gprintf.h> + +#include "mu-maildir.h" +#include "utils/mu-str.h" + +#define MU_MAILDIR_NOINDEX_FILE ".noindex" +#define MU_MAILDIR_NOUPDATE_FILE ".noupdate" + + +/* On Linux (and some BSD), we have entry->d_type, but some file + * systems (XFS, ReiserFS) do not support it, and set it DT_UNKNOWN. + * On other OSs, notably Solaris, entry->d_type is not present at all. + * For these cases, we use lstat (in get_dtype) as a slower fallback, + * and return it in the d_type parameter + */ +#ifdef HAVE_STRUCT_DIRENT_D_TYPE +#define GET_DTYPE(DE,FP) \ + ((DE)->d_type == DT_UNKNOWN ? mu_util_get_dtype_with_lstat((FP)) : \ + (DE)->d_type) +#else +#define GET_DTYPE(DE,FP) \ + mu_util_get_dtype_with_lstat((FP)) +#endif /*HAVE_STRUCT_DIRENT_D_TYPE*/ + + +static gboolean +create_maildir (const char *path, mode_t mode, GError **err) +{ + int i; + const gchar* subdirs[] = {"new", "cur", "tmp"}; + + for (i = 0; i != G_N_ELEMENTS(subdirs); ++i) { + + const char *fullpath; + int rv; + + /* static buffer */ + fullpath = mu_str_fullpath_s (path, subdirs[i]); + + /* if subdir already exists, don't try to re-create + * it */ + if (mu_util_check_dir (fullpath, TRUE, TRUE)) + continue; + + rv = g_mkdir_with_parents (fullpath, (int)mode); + + /* note, g_mkdir_with_parents won't detect an error if + * there's already such a dir, but with the wrong + * permissions; so we need to check */ + if (rv != 0 || !mu_util_check_dir(fullpath, TRUE, TRUE)) + return mu_util_g_set_error + (err,MU_ERROR_FILE_CANNOT_MKDIR, + "creating dir failed for %s: %s", + fullpath, strerror (errno)); + } + + return TRUE; +} + +static gboolean +create_noindex (const char *path, GError **err) +{ + /* create a noindex file if requested */ + int fd; + const char *noindexpath; + + /* static buffer */ + noindexpath = mu_str_fullpath_s (path, MU_MAILDIR_NOINDEX_FILE); + + fd = creat (noindexpath, 0644); + + /* note, if the 'close' failed, creation may still have + * succeeded...*/ + if (fd < 0 || close (fd) != 0) + return mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_CREATE, + "error in create_noindex: %s", + strerror (errno)); + return TRUE; +} + +gboolean +mu_maildir_mkdir (const char* path, mode_t mode, gboolean noindex, GError **err) +{ + g_return_val_if_fail (path, FALSE); + + MU_WRITE_LOG ("%s (%s, %o, %s)", __func__, + path, mode, noindex ? "TRUE" : "FALSE"); + + if (!create_maildir (path, mode, err)) + return FALSE; + + if (noindex && !create_noindex (path, err)) + return FALSE; + + return TRUE; +} + +/* determine whether the source message is in 'new' or in 'cur'; + * we ignore messages in 'tmp' for obvious reasons */ +static gboolean +check_subdir (const char *src, gboolean *in_cur, GError **err) +{ + gboolean rv; + gchar *srcpath; + + srcpath = g_path_get_dirname (src); + *in_cur = FALSE; + rv = TRUE; + + if (g_str_has_suffix (srcpath, "cur")) + *in_cur = TRUE; + else if (!g_str_has_suffix (srcpath, "new")) + rv = mu_util_g_set_error (err, + MU_ERROR_FILE_INVALID_SOURCE, + "invalid source message '%s'", + src); + g_free (srcpath); + return rv; +} + +static gchar* +get_target_fullpath (const char* src, const gchar *targetpath, GError **err) +{ + gchar *targetfullpath, *srcfile; + gboolean in_cur; + + if (!check_subdir (src, &in_cur, err)) + return NULL; + + srcfile = g_path_get_basename (src); + + /* create targetpath; note: make the filename *cough* unique + * by including a hash of the srcname in the targetname. This + * helps if there are copies of a message (which all have the + * same basename) + */ + targetfullpath = g_strdup_printf ("%s%c%s%c%u_%s", + targetpath, + G_DIR_SEPARATOR, + in_cur ? "cur" : "new", + G_DIR_SEPARATOR, + g_str_hash(src), + srcfile); + g_free (srcfile); + + return targetfullpath; +} + + +gboolean +mu_maildir_link (const char* src, const char *targetpath, GError **err) +{ + gchar *targetfullpath; + int rv; + + g_return_val_if_fail (src, FALSE); + g_return_val_if_fail (targetpath, FALSE); + + targetfullpath = get_target_fullpath (src, targetpath, err); + if (!targetfullpath) + return FALSE; + + rv = symlink (src, targetfullpath); + + if (rv != 0) + mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_LINK, + "error creating link %s => %s: %s", + targetfullpath, src, strerror (errno)); + g_free (targetfullpath); + + return rv == 0 ? TRUE: FALSE; +} + + +static MuError +process_dir (const char* path, const gchar *mdir, + MuMaildirWalkMsgCallback msg_cb, + MuMaildirWalkDirCallback dir_cb, gboolean full, + void *data); + +static MuError +process_file (const char* fullpath, const gchar* mdir, + MuMaildirWalkMsgCallback msg_cb, void *data) +{ + MuError result; + struct stat statbuf; + + if (!msg_cb) + return MU_OK; + + if (G_UNLIKELY(access(fullpath, R_OK) != 0)) { + g_warning ("cannot access %s: %s", fullpath, + strerror(errno)); + return MU_ERROR; + } + + if (G_UNLIKELY(stat (fullpath, &statbuf) != 0)) { + g_warning ("cannot stat %s: %s", fullpath, strerror(errno)); + return MU_ERROR; + } + + result = (msg_cb)(fullpath, mdir, &statbuf, data); + if (result == MU_STOP) + g_debug ("callback said 'MU_STOP' for %s", fullpath); + else if (result == MU_ERROR) + g_warning ("%s: error in callback (%s)", + __func__, fullpath); + + return result; +} + + +/* + * determine if path is a maildir leaf-dir; ie. if it's 'cur' or 'new' + * (we're skipping 'tmp' for obvious reasons) + */ +gboolean +mu_maildir_is_leaf_dir (const char *path) +{ + size_t len; + + /* path is the full path; it cannot possibly be shorter + * than 4 for a maildir (/cur or /new) */ + len = path ? strlen (path) : 0; + if (G_UNLIKELY(len < 4)) + return FALSE; + + /* optimization; one further idea would be cast the 4 bytes to an + * integer and compare that -- need to think about alignment, + * endianness */ + + if (path[len - 4] == G_DIR_SEPARATOR && + path[len - 3] == 'c' && + path[len - 2] == 'u' && + path[len - 1] == 'r') + return TRUE; + + if (path[len - 4] == G_DIR_SEPARATOR && + path[len - 3] == 'n' && + path[len - 2] == 'e' && + path[len - 1] == 'w') + return TRUE; + + return FALSE; +} + + +/* check if there path contains file; used for checking if there is + * MU_MAILDIR_NOINDEX_FILE or MU_MAILDIR_NOUPDATE_FILE in this + * dir; */ +static gboolean +dir_contains_file (const char *path, const char *file) +{ + const char* fullpath; + + /* static buffer */ + fullpath = mu_str_fullpath_s (path, file); + + if (access (fullpath, F_OK) == 0) + return TRUE; + else if (G_UNLIKELY(errno != ENOENT && errno != EACCES)) + g_warning ("error testing for %s/%s: %s", + fullpath, file, strerror(errno)); + return FALSE; +} + +static gboolean +is_dotdir_to_ignore (const char* dir) +{ + int i; + const char* ignore[] = { + ".notmuch", + ".nnmaildir", + ".#evolution" + }; /* when adding names, check the optimization below */ + + if (dir[0] != '.') + return FALSE; /* not a dotdir */ + + if (dir[1] == '\0' || (dir[1] == '.' && dir[2] == '\0')) + return TRUE; /* ignore '.' and '..' */ + + /* optimization: special dirs have 'n' or '#' in pos 1 */ + if (dir[1] != 'n' && dir[1] != '#') + return FALSE; /* not special: don't ignore */ + + for (i = 0; i != G_N_ELEMENTS(ignore); ++i) + if (strcmp(dir, ignore[i]) == 0) + return TRUE; + + return FALSE; /* don't ignore */ +} + +static gboolean +ignore_dir_entry (struct dirent *entry, unsigned char d_type) +{ + if (G_LIKELY(d_type == DT_REG)) { + + guint u; + + /* ignore emacs tempfiles */ + if (entry->d_name[0] == '#') + return TRUE; + /* ignore dovecot metadata */ + if (entry->d_name[0] == 'd' && + strncmp (entry->d_name, "dovecot", 7) == 0) + return TRUE; + /* ignore special files */ + if (entry->d_name[0] == '.') + return TRUE; + /* ignore core files */ + if (entry->d_name[0] == 'c' && + strncmp (entry->d_name, "core", 4) == 0) + return TRUE; + /* ignore tmp/backup files; find the last char */ + for (u = 0; entry->d_name[u] != '\0'; ++u) { + switch (entry->d_name[u]) { + case '#': + case '~': + /* looks like a backup / tempsave file */ + if (entry->d_name[u + 1] == '\0') + return TRUE; + continue; + default: + continue; + } + } + return FALSE; /* other files: don't ignore */ + + } else if (d_type == DT_DIR) + return is_dotdir_to_ignore (entry->d_name); + else + return TRUE; /* ignore non-normal files, non-dirs */ +} + +/* + * return the maildir value for the the path - this is the directory + * for the message (with the top-level dir as "/"), and without the + * leaf "/cur" or "/new". In other words, contatenate old_mdir + "/" + dir, + * unless dir is either 'new' or 'cur'. The value will be used in queries. + */ +static gchar* +get_mdir_for_path (const gchar *old_mdir, const gchar *dir) +{ + /* if the current dir is not 'new' or 'cur', contatenate + * old_mdir an dir */ + if ((dir[0] == 'n' && strcmp(dir, "new") == 0) || + (dir[0] == 'c' && strcmp(dir, "cur") == 0) || + (dir[0] == 't' && strcmp(dir, "tmp") == 0)) + return strdup (old_mdir ? old_mdir : G_DIR_SEPARATOR_S); + else + return g_strconcat (old_mdir ? old_mdir : "", + G_DIR_SEPARATOR_S, dir, NULL); + +} + + +static MuError +process_dir_entry (const char* path, const char* mdir, struct dirent *entry, + MuMaildirWalkMsgCallback cb_msg, + MuMaildirWalkDirCallback cb_dir, + gboolean full, void *data) +{ + const char *fp; + char* fullpath; + unsigned char d_type; + + /* we have to copy the buffer from fullpath_s, because it + * returns a static buffer, and we maybe called reentrantly */ + fp = mu_str_fullpath_s (path, entry->d_name); + fullpath = g_newa (char, strlen(fp) + 1); + strcpy (fullpath, fp); + + d_type = GET_DTYPE(entry, fullpath); + + /* ignore special files/dirs */ + if (ignore_dir_entry (entry, d_type)) { + /* g_debug ("ignoring %s\n", entry->d_name); */ + return MU_OK; + } + + switch (d_type) { + case DT_REG: /* we only want files in cur/ and new/ */ + if (!mu_maildir_is_leaf_dir (path)) + return MU_OK; + + return process_file (fullpath, mdir, cb_msg, data); + + case DT_DIR: { + char *my_mdir; + MuError rv; + /* my_mdir is the search maildir (the dir starting + * with the top-level maildir as /, and without the + * /tmp, /cur, /new */ + my_mdir = get_mdir_for_path (mdir, entry->d_name); + rv = process_dir (fullpath, my_mdir, cb_msg, cb_dir, full, data); + g_free (my_mdir); + + return rv; + } + + default: + return MU_OK; /* ignore other types */ + } +} + + +static const size_t DIRENT_ALLOC_SIZE = + offsetof (struct dirent, d_name) + PATH_MAX; + +static struct dirent* +dirent_new (void) +{ + return (struct dirent*) g_slice_alloc (DIRENT_ALLOC_SIZE); +} + + +static void +dirent_destroy (struct dirent *entry) +{ + g_slice_free1 (DIRENT_ALLOC_SIZE, entry); +} + +#ifdef HAVE_STRUCT_DIRENT_D_INO +static int +dirent_cmp (struct dirent *d1, struct dirent *d2) +{ + /* we do it his way instead of a simple d1->d_ino - d2->d_ino + * because this way, we don't need 64-bit numbers for the + * actual sorting */ + if (d1->d_ino < d2->d_ino) + return -1; + else if (d1->d_ino > d2->d_ino) + return 1; + else + return 0; +} +#endif /*HAVE_STRUCT_DIRENT_D_INO*/ + +static MuError +process_dir_entries (DIR *dir, const char* path, const char* mdir, + MuMaildirWalkMsgCallback msg_cb, + MuMaildirWalkDirCallback dir_cb, + gboolean full, void *data) +{ + MuError result; + GSList *lst, *c; + + for (lst = NULL;;) { + int rv; + struct dirent *entry, *res; + entry = dirent_new (); + rv = readdir_r (dir, entry, &res); + if (rv == 0) { + if (res) + lst = g_slist_prepend (lst, entry); + else { + dirent_destroy (entry); + break; /* last direntry reached */ + } + } else { + dirent_destroy (entry); + g_warning ("error scanning dir: %s", strerror(rv)); + return MU_ERROR_FILE; + } + } + + /* we sort by inode; this makes things much faster on + * extfs2,3 */ +#if HAVE_STRUCT_DIRENT_D_INO + c = lst = g_slist_sort (lst, (GCompareFunc)dirent_cmp); +#endif /*HAVE_STRUCT_DIRENT_D_INO*/ + + for (c = lst, result = MU_OK; c && result == MU_OK; c = g_slist_next(c)) + result = process_dir_entry (path, mdir, (struct dirent*)c->data, + msg_cb, dir_cb, full, data); + + g_slist_foreach (lst, (GFunc)dirent_destroy, NULL); + g_slist_free (lst); + + return result; +} + + +static MuError +process_dir (const char* path, const char* mdir, + MuMaildirWalkMsgCallback msg_cb, MuMaildirWalkDirCallback dir_cb, + gboolean full, void *data) +{ + MuError result; + DIR* dir; + + /* if it has a noindex file, we ignore this dir */ + if (dir_contains_file (path, MU_MAILDIR_NOINDEX_FILE) || + (!full && dir_contains_file (path, MU_MAILDIR_NOUPDATE_FILE))) { + g_debug ("found noindex/noupdate: ignoring dir %s", path); + return MU_OK; + } + + if (dir_cb) { + MuError rv; + rv = dir_cb (path, TRUE/*enter*/, data); + /* ignore this dir; not necessarily an _error_, dir might + * be up-to-date and return MU_IGNORE */ + if (rv == MU_IGNORE) + return MU_OK; + else if (rv != MU_OK) + return rv; + } + + dir = opendir (path); + if (!dir) { + g_warning ("cannot access %s: %s", path, strerror(errno)); + return MU_OK; + } + + result = process_dir_entries (dir, path, mdir, msg_cb, dir_cb, + full, data); + closedir (dir); + + /* only run dir_cb if it exists and so far, things went ok */ + if (dir_cb && result == MU_OK) + return dir_cb (path, FALSE/*leave*/, data); + + return result; +} + + +MuError +mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg, + MuMaildirWalkDirCallback cb_dir, gboolean full, + void *data) +{ + MuError rv; + char *mypath; + + g_return_val_if_fail (path && cb_msg, MU_ERROR); + g_return_val_if_fail (mu_util_check_dir(path, TRUE, FALSE), MU_ERROR); + + /* strip the final / or \ */ + mypath = g_strdup (path); + if (mypath[strlen(mypath)-1] == G_DIR_SEPARATOR) + mypath[strlen(mypath)-1] = '\0'; + + rv = process_dir (mypath, NULL, cb_msg, cb_dir, full, data); + g_free (mypath); + + return rv; +} + + +static gboolean +clear_links (const char *path, DIR *dir) +{ + gboolean rv; + struct dirent *dentry; + + rv = TRUE; + errno = 0; + + while ((dentry = readdir (dir))) { + + guint8 d_type; + char *fullpath; + + if (dentry->d_name[0] == '.') + continue; /* ignore .,.. other dotdirs */ + + fullpath = g_build_path ("/", path, dentry->d_name, NULL); + d_type = GET_DTYPE (dentry, fullpath); + + if (d_type == DT_LNK) { + if (unlink (fullpath) != 0 ) { + g_warning ("error unlinking %s: %s", + fullpath, strerror(errno)); + rv = FALSE; + } + } else if (d_type == DT_DIR) { + DIR *subdir; + subdir = opendir (fullpath); + if (!subdir) { + g_warning ("failed to open dir %s: %s", + fullpath, strerror(errno)); + rv = FALSE; + goto next; + } + + if (!clear_links (fullpath, subdir)) + rv = FALSE; + + closedir (subdir); + } + + next: + g_free (fullpath); + } + + return rv; +} + +gboolean +mu_maildir_clear_links (const char *path, GError **err) +{ + DIR *dir; + gboolean rv; + + g_return_val_if_fail (path, FALSE); + + dir = opendir (path); + if (!dir) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE_CANNOT_OPEN, + "failed to open %s: %s", path, strerror(errno)); + return FALSE; + } + + rv = clear_links (path, dir); + + closedir (dir); + + return rv; +} + + + + +MuFlags +mu_maildir_get_flags_from_path (const char *path) +{ + g_return_val_if_fail (path, MU_FLAG_INVALID); + + /* try to find the info part */ + /* note that we can use either the ':' or '!' as separator; + * the former is the official, but as it does not work on e.g. VFAT + * file systems, some Maildir implementations use the latter instead + * (or both). For example, Tinymail/modest does this. The python + * documentation at http://docs.python.org/lib/mailbox-maildir.html + * mentions the '!' as well as a 'popular choice' + */ + + /* we check the dir -- */ + if (strstr (path, G_DIR_SEPARATOR_S "new" G_DIR_SEPARATOR_S)) { + + char *dir, *dir2; + MuFlags flags; + + dir = g_path_get_dirname (path); + dir2 = g_path_get_basename (dir); + + flags = MU_FLAG_NONE; + + if (g_strcmp0 (dir2, "new") == 0) + flags = MU_FLAG_NEW; + + g_free (dir); + g_free (dir2); + + /* NOTE: new/ message should not have :2,-stuff, as + * per http://cr.yp.to/proto/maildir.html. If they, do + * we ignore it + */ + if (flags == MU_FLAG_NEW) + return flags; + } + + /* get the file flags */ + { + char *info; + + info = strrchr (path, '2'); + if (!info || info == path || + (info[-1] != ':' && info[-1] != '!') || + (info[1] != ',')) + return MU_FLAG_NONE; + else + return mu_flags_from_str + (&info[2], MU_FLAG_TYPE_MAILFILE, + TRUE /*ignore invalid */); + } +} + + +/* + * take an existing message path, and return a new path, based on + * whether it should be in 'new' or 'cur'; ie. + * + * /home/user/Maildir/foo/bar/cur/abc:2,F and flags == MU_FLAG_NEW + * => /home/user/Maildir/foo/bar/new + * and + * /home/user/Maildir/foo/bar/new/abc and flags == MU_FLAG_REPLIED + * => /home/user/Maildir/foo/bar/cur + * + * so the difference is whether MU_FLAG_NEW is set or not; and in the + * latter case, no other flags are allowed. + * + */ +static gchar* +get_new_path (const char *mdir, const char *mfile, MuFlags flags, + const char* custom_flags) +{ + if (flags & MU_FLAG_NEW) + return g_strdup_printf ("%s%cnew%c%s", + mdir, G_DIR_SEPARATOR, G_DIR_SEPARATOR, + mfile); + else { + const char *flagstr; + flagstr = mu_flags_to_str_s (flags, MU_FLAG_TYPE_MAILFILE); + + return g_strdup_printf ("%s%ccur%c%s:2,%s%s", + mdir, G_DIR_SEPARATOR, G_DIR_SEPARATOR, + mfile, flagstr, + custom_flags ? custom_flags : ""); + } +} + + +char* +mu_maildir_get_maildir_from_path (const char* path) +{ + gchar *mdir; + + /* determine the maildir */ + mdir = g_path_get_dirname (path); + if (!g_str_has_suffix (mdir, "cur") && + !g_str_has_suffix (mdir, "new")) { + g_warning ("%s: not a valid maildir path: %s", + __func__, path); + g_free (mdir); + return NULL; + } + + /* remove the 'cur' or 'new' */ + mdir[strlen(mdir) - 4] = '\0'; + + return mdir; +} + + +static char* +get_new_basename (void) +{ + return g_strdup_printf ("%u.%08x%08x.%s", + (guint)time(NULL), + g_random_int(), + (gint32)g_get_monotonic_time (), + g_get_host_name ()); +} + + +char* +mu_maildir_get_new_path (const char *oldpath, const char *new_mdir, + MuFlags newflags, gboolean new_name) +{ + char *mfile, *mdir, *custom_flags, *newpath; + + g_return_val_if_fail (oldpath, NULL); + + mfile = newpath = custom_flags = NULL; + + /* determine the maildir */ + mdir = mu_maildir_get_maildir_from_path (oldpath); + if (!mdir) + return NULL; + + if (new_name) + mfile = get_new_basename (); + else { + /* determine the name of the mailfile, stripped of its flags, as + * well as any custom (non-standard) flags */ + char *cur; + mfile = g_path_get_basename (oldpath); + for (cur = &mfile[strlen(mfile)-1]; cur > mfile; --cur) { + if ((*cur == ':' || *cur == '!') && + (cur[1] == '2' && cur[2] == ',')) { + /* get the custom flags (if any) */ + custom_flags = + mu_flags_custom_from_str (cur + 3); + cur[0] = '\0'; /* strip the flags */ + break; + } + } + } + + newpath = get_new_path (new_mdir ? new_mdir : mdir, + mfile, newflags, custom_flags); + g_free (mfile); + g_free (mdir); + g_free (custom_flags); + + return newpath; +} + + +static gint64 +get_file_size (const char* path) +{ + int rv; + struct stat statbuf; + + rv = stat (path, &statbuf); + if (rv != 0) { + /* g_warning ("error: %s", strerror (errno)); */ + return -1; + } + + return (gint64)statbuf.st_size; +} + + +static gboolean +msg_move_check_pre (const gchar *src, const gchar *dst, GError **err) +{ + gint size1, size2; + + if (!g_path_is_absolute(src)) + return mu_util_g_set_error + (err, MU_ERROR_FILE, + "source is not an absolute path: '%s'", src); + + if (!g_path_is_absolute(dst)) + return mu_util_g_set_error + (err, MU_ERROR_FILE, + "target is not an absolute path: '%s'", dst); + + if (access (src, R_OK) != 0) + return mu_util_g_set_error (err, MU_ERROR_FILE, + "cannot read %s", src); + + if (access (dst, F_OK) != 0) + return TRUE; + + /* target exist; we simply overwrite it, unless target has a different + * size. ignore the exceedingly rare case where have duplicate message + * file names with different content yet the same length. (md5 etc. is a + * bit slow) */ + size1 = get_file_size (src); + size2 = get_file_size (dst); + if (size1 != size2) + return mu_util_g_set_error (err, MU_ERROR_FILE, + "%s already exists", dst); + + return TRUE; +} + +static gboolean +msg_move_check_post (const char *src, const char *dst, GError **err) +{ + /* double check -- is the target really there? */ + if (access (dst, F_OK) != 0) + return mu_util_g_set_error + (err, MU_ERROR_FILE, "can't find target (%s)", dst); + + if (access (src, F_OK) == 0) + return mu_util_g_set_error + (err, MU_ERROR_FILE, "source still there (%s)", src); + + return TRUE; +} + + +static gboolean +msg_move (const char* src, const char *dst, GError **err) +{ + if (!msg_move_check_pre (src, dst, err)) + return FALSE; + + if (rename (src, dst) != 0) + return mu_util_g_set_error + (err, MU_ERROR_FILE,"error moving %s to %s", src, dst); + + return msg_move_check_post (src, dst, err); +} + +gchar* +mu_maildir_move_message (const char* oldpath, const char* targetmdir, + MuFlags newflags, gboolean ignore_dups, + gboolean new_name, GError **err) +{ + char *newfullpath; + gboolean rv; + gboolean src_is_target; + + g_return_val_if_fail (oldpath, FALSE); + + newfullpath = mu_maildir_get_new_path (oldpath, targetmdir, + newflags, new_name); + if (!newfullpath) { + mu_util_g_set_error (err, MU_ERROR_FILE, + "failed to determine targetpath"); + return NULL; + } + + src_is_target = (g_strcmp0 (oldpath, newfullpath) == 0); + + if (!ignore_dups && src_is_target) { + mu_util_g_set_error (err, MU_ERROR_FILE_TARGET_EQUALS_SOURCE, + "target equals source"); + return NULL; + } + + if (!src_is_target) { + rv = msg_move (oldpath, newfullpath, err); + if (!rv) { + g_free (newfullpath); + return NULL; + } + } + + return newfullpath; +} diff --git a/lib/mu-maildir.h b/lib/mu-maildir.h new file mode 100644 index 0000000..790c345 --- /dev/null +++ b/lib/mu-maildir.h @@ -0,0 +1,223 @@ +/* +** Copyright (C) 2008-2015 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_MAILDIR_H__ +#define __MU_MAILDIR_H__ + +#include <glib.h> +#include <time.h> +#include <sys/types.h> /* for mode_t */ +#include <utils/mu-util.h> +#include <mu-flags.h> + + +G_BEGIN_DECLS + +/** + * create a new maildir. if parts of the maildir already exists, those + * will simply be ignored. IOW, if you try to create the same maildir + * twice, the second will simply be a no-op (without any errors). + * Note, if the function fails 'halfway', it will *not* try to remove + * the parts the were created. it *will* create any parent dirs that + * are not yet existent. + * + * + * @param path the path (missing components will be created, as in 'mkdir -p') + * @param mode the file mode (e.g., 0755) + * @param noindex add a .noindex file to the maildir, so it will be excluded + * from indexing by 'mu index' + * @param err if function returns FALSE, receives error + * information. err may be NULL. + * + * @return TRUE if creation succeeded (or already existed), FALSE otherwise + */ +gboolean mu_maildir_mkdir (const char* path, mode_t mode, gboolean noindex, + GError **err); + + +/** + * create a symbolic link to a mail message + * + * @param src the full path to the source message + * @param targetpath the path to the target maildir; ie., *not* + * MyMaildir/cur, but just MyMaildir/. The function will figure out + * the correct subdir then. + * @param err if function returns FALSE, err may contain extra + * information. if err is NULL, does nothing + * + * @return + */ +gboolean mu_maildir_link (const char* src, const char *targetpath, + GError **err); + +/** + * MuMaildirWalkMsgCallback -- callback function for + * mu_path_walk_maildir; see the documentation there. It will be + * called for each message found, with fullpath containing the full + * path to the message, mdir containing the maildir -- that is, when + * indexing ~/Maildir, a message ~/Maildir/foo/bar/cur/msg would have + * the maildir "foo/bar". Then, the information from 'stat' of this + * file (see stat(3)), and a user_data pointer + */ +typedef MuError (*MuMaildirWalkMsgCallback) + (const char* fullpath, const char* mdir, struct stat *statinfo, + void *user_data); + +/** + * MuPathWalkDirCallback -- callback function for mu_path_walk_maildir; see the + * documentation there. It will be called each time a dir is entered or left, + * with 'enter' being TRUE upon entering, FALSE otherwise + */ +typedef MuError (*MuMaildirWalkDirCallback) + (const char* fullpath, gboolean enter, void *user_data); + +/** + * start a recursive walk of a maildir; for each file found, we call + * callback with the path (with the Maildir path of scanner_new as + * root), the filename, the timestamp (mtime) of the file,and the + * *data pointer, for user data. dot-files are ignored, as well as + * files outside cur/ and new/ dirs and unreadable files; however, + * dotdirs are visited (ie. '.dotdir/cur'), so this enables Maildir++. + * (http://www.inter7.com/courierimap/README.maildirquota.html, search + * for 'Mission statement'). In addition, dirs containing a file named + * '.noindex' are ignored, as are their subdirectories, and dirs + * containing a file called '.noupdate' are ignored, unless @param + * full is TRUE. + * + * mu_walk_maildir stops if the callbacks return something different + * from MU_OK. For example, it can return MU_STOP to stop the scan, or + * some error. + * + * @param path the maildir path to scan + * @param cb_msg the callback function called for each msg + * @param cb_dir the callback function called for each dir + * @param full whether do a full scan, i.e., to ignore .noupdate files + * @param data user data pointer + * + * @return a scanner result; MU_OK if everything went ok, + * MU_STOP if we want to stop, or MU_ERROR in + * case of error + */ +MuError mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg, + MuMaildirWalkDirCallback cb_dir, gboolean full, + void *data); +/** + * recursively delete all the symbolic links in a directory tree + * + * @param dir top dir + * @param err if function returns FALSE, err may contain extra + * information. if err is NULL, does nothing + * + * @return TRUE if it worked, FALSE in case of error + */ +gboolean mu_maildir_clear_links (const gchar* dir, GError **err); + + + +/** + * whether the directory path ends in '/cur/' or '/new/' + * + * @param path some path + */ +gboolean mu_maildir_is_leaf_dir (const char *path); + + +/** + * get the Maildir flags from the full path of a mailfile. The flags + * are as specified in http://cr.yp.to/proto/maildir.html, plus + * MU_MSG_FLAG_NEW for new messages, ie the ones that live in + * new/. The flags are logically OR'ed. Note that the file does not + * have to exist; the flags are based on the path only. + * + * @param pathname of a mailfile; it does not have to refer to an + * actual message + * + * @return the flags, or MU_MSG_FILE_FLAG_UNKNOWN in case of error + */ +MuFlags mu_maildir_get_flags_from_path (const char* pathname); + +/** + * get the new pathname for a message, based on the old path and the + * new flags and (optionally) a new maildir. Note that + * setting/removing the MU_FLAG_NEW will change the directory in which + * a message lives. The flags are as specified in + * http://cr.yp.to/proto/maildir.html, plus MU_FLAG_NEW for new + * messages, ie the ones that live in new/. The flags are logically + * OR'ed. Note that the file does not have to exist; the flags are + * based on the path only. + * + * + * @param oldpath the old (current) full path to the message + * (including the filename) + * @param new_mdir the new maildir for this message, or NULL to keep + * it in the current one. The maildir is the absolute file system + * path, without the 'cur' or 'new' + * @param new_flags the new flags for this message + * @param new_name whether to create a new unique name, or keep the + * old one + * + * @return a new path name; use g_free when done with. NULL in case of + * error. + */ +char* mu_maildir_get_new_path (const char *oldpath, const char *new_mdir, + MuFlags new_flags, gboolean new_name) + G_GNUC_WARN_UNUSED_RESULT; + +/** + * get the maildir for a certain message path, ie, the path *before* + * cur/ or new/ + * + * @param path path for some message + * + * @return the maildir (free with g_free), or NULL in case of error + */ +char* mu_maildir_get_maildir_from_path (const char* path) + G_GNUC_WARN_UNUSED_RESULT; + + +/** + * move a message file to another maildir; the function returns the full path to + * the new message. if the target file already exists, it is overwritten. + * + * @param msgpath an absolute file system path to an existing message in an + * actual maildir + * @param targetmdir the target maildir; note that this the base-level + * Maildir, ie. /home/user/Maildir/archive, and must _not_ include the + * 'cur' or 'new' part. Note that the target maildir must be on the + * same filesystem. If you specify NULL for targetmdir, only the flags + * of the message are affected; note that this may still involve a + * moved to another directory (say, from new/ to cur/) + * @param flags to set for the target (influences the filename, path) + * @param ignore_dups whether to silently ignore the src=target case + * (and return TRUE) + * @param new_name whether to create a new unique name, or keep the + * old one + * @param err receives error information + * + * @return return the full path name of the target file (g_free) if + * the move succeeded, NULL otherwise + */ +gchar* mu_maildir_move_message (const char* oldpath, const char* targetmdir, + MuFlags newflags, gboolean ignore_dups, + gboolean new_name, GError **err) + G_GNUC_WARN_UNUSED_RESULT; + +G_END_DECLS + +#endif /*__MU_MAILDIR_H__*/ diff --git a/lib/mu-msg-crypto.c b/lib/mu-msg-crypto.c new file mode 100644 index 0000000..c7ca8ba --- /dev/null +++ b/lib/mu-msg-crypto.c @@ -0,0 +1,374 @@ +/* +** Copyright (C) 2012-2018 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include <string.h> + +#include "mu-msg.h" +#include "mu-msg-priv.h" +#include "mu-msg-part.h" +#include "utils/mu-date.h" + +#include <gmime/gmime.h> +#include <gmime/gmime-multipart-signed.h> + + +static const char* +get_pubkey_algo_name (GMimePubKeyAlgo algo) +{ + switch (algo) { + case GMIME_PUBKEY_ALGO_DEFAULT: + return "default"; + case GMIME_PUBKEY_ALGO_RSA: + return "RSA"; + case GMIME_PUBKEY_ALGO_RSA_E: + return "RSA (encryption only)"; + case GMIME_PUBKEY_ALGO_RSA_S: + return "RSA (signing only)"; + case GMIME_PUBKEY_ALGO_ELG_E: + return "ElGamal (encryption only)"; + case GMIME_PUBKEY_ALGO_DSA: + return "DSA"; + case GMIME_PUBKEY_ALGO_ELG: + return "ElGamal"; + default: + return "unknown pubkey algorithm"; + } +} + +static const gchar* +get_digestkey_algo_name (GMimeDigestAlgo algo) +{ + switch (algo) { + case GMIME_DIGEST_ALGO_DEFAULT: + return "default"; + case GMIME_DIGEST_ALGO_MD5: + return "MD5"; + case GMIME_DIGEST_ALGO_SHA1: + return "SHA-1"; + case GMIME_DIGEST_ALGO_RIPEMD160: + return "RIPEMD160"; + case GMIME_DIGEST_ALGO_MD2: + return "MD2"; + case GMIME_DIGEST_ALGO_TIGER192: + return "TIGER-192"; + case GMIME_DIGEST_ALGO_HAVAL5160: + return "HAVAL-5-160"; + case GMIME_DIGEST_ALGO_SHA256: + return "SHA-256"; + case GMIME_DIGEST_ALGO_SHA384: + return "SHA-384"; + case GMIME_DIGEST_ALGO_SHA512: + return "SHA-512"; + case GMIME_DIGEST_ALGO_SHA224: + return "SHA-224"; + case GMIME_DIGEST_ALGO_MD4: + return "MD4"; + default: + return "unknown digest algorithm"; + } +} + + +/* get data from the 'certificate' */ +static char* +get_cert_data (GMimeCertificate *cert) +{ + const char /**email,*/ *name, *digest_algo, *pubkey_algo, + *keyid, *trust; + + /* email = g_mime_certificate_get_email (cert); */ + name = g_mime_certificate_get_name (cert); + keyid = g_mime_certificate_get_key_id (cert); + + digest_algo = get_digestkey_algo_name + (g_mime_certificate_get_digest_algo (cert)); + pubkey_algo = get_pubkey_algo_name + (g_mime_certificate_get_pubkey_algo (cert)); + + switch (g_mime_certificate_get_trust (cert)) { + case GMIME_TRUST_UNKNOWN: trust = "unknown"; break; + case GMIME_TRUST_UNDEFINED: trust = "undefined"; break; + case GMIME_TRUST_NEVER: trust = "never"; break; + case GMIME_TRUST_MARGINAL: trust = "marginal"; break; + case GMIME_TRUST_FULL: trust = "full"; break; + case GMIME_TRUST_ULTIMATE: trust = "ultimate"; break; + default: + g_return_val_if_reached (NULL); + } + + return g_strdup_printf ( + "signer:%s, key:%s (%s,%s), trust:%s", + name ? name : "?", + /* email ? email : "?", */ + keyid, pubkey_algo, digest_algo, + trust); +} + + +static char* +get_signature_status (GMimeSignatureStatus status) +{ + size_t n; + GString *descr; + + struct { + GMimeSignatureStatus status; + const char *name; + } status_info[] = { + { GMIME_SIGNATURE_STATUS_VALID, "valid" }, + { GMIME_SIGNATURE_STATUS_GREEN, "green" }, + { GMIME_SIGNATURE_STATUS_RED, "red" }, + { GMIME_SIGNATURE_STATUS_KEY_REVOKED, "key revoked" }, + { GMIME_SIGNATURE_STATUS_KEY_EXPIRED, "key expired" }, + { GMIME_SIGNATURE_STATUS_SIG_EXPIRED, "signature expired" }, + { GMIME_SIGNATURE_STATUS_KEY_MISSING, "key missing" }, + { GMIME_SIGNATURE_STATUS_CRL_MISSING, "crl missing" }, + { GMIME_SIGNATURE_STATUS_CRL_TOO_OLD, "crl too old" }, + { GMIME_SIGNATURE_STATUS_BAD_POLICY, "bad policy" }, + { GMIME_SIGNATURE_STATUS_SYS_ERROR, "system error" }, + { GMIME_SIGNATURE_STATUS_TOFU_CONFLICT, "tofu conflict " }, + }; + + descr = g_string_new(""); + for (n = 0; n != G_N_ELEMENTS(status_info); ++n) { + + if (!(status & status_info[n].status)) + continue; + + g_string_append_printf (descr, "%s%s", + descr->len > 0 ? ", " : "", + status_info[n].name); + } + + return g_string_free (descr, FALSE); +} + + +/* get a human-readable report about the signature */ +static char* +get_verdict_report (GMimeSignature *msig) +{ + time_t t; + const char *created, *expires; + gchar *certdata, *report, *status; + GMimeSignatureStatus sigstat; + + sigstat = g_mime_signature_get_status (msig); + status = get_signature_status(sigstat); + + t = g_mime_signature_get_created (msig); + created = (t == 0 || t == (time_t)-1) ? "?" : mu_date_str_s ("%x", t); + + t = g_mime_signature_get_expires (msig); + expires = (t == 0 || t == (time_t)-1) ? "?" : mu_date_str_s ("%x", t); + + certdata = get_cert_data (g_mime_signature_get_certificate (msig)); + report = g_strdup_printf ("%s; created:%s, expires:%s, %s", + status, created, expires, + certdata ? certdata : "?"); + g_free (certdata); + g_free (status); + + return report; +} + + +static char* +get_signers (GHashTable *signerhash) +{ + GString *gstr; + GHashTableIter iter; + const char *name; + + if (!signerhash || g_hash_table_size(signerhash) == 0) + return NULL; + + gstr = g_string_new (NULL); + g_hash_table_iter_init (&iter, signerhash); + while (g_hash_table_iter_next (&iter, (gpointer)&name, NULL)) { + if (gstr->len != 0) + g_string_append_c (gstr, ','); + gstr = g_string_append (gstr, name); + } + + return g_string_free (gstr, FALSE); +} + + +static MuMsgPartSigStatusReport* +get_status_report (GMimeSignatureList *sigs) +{ + int i; + MuMsgPartSigStatus status; + MuMsgPartSigStatusReport *status_report; + char *report; + GHashTable *signerhash; + + status = MU_MSG_PART_SIG_STATUS_GOOD; /* let's start positive! */ + signerhash = g_hash_table_new (g_str_hash, g_str_equal); + + for (i = 0, report = NULL; i != g_mime_signature_list_length (sigs); + ++i) { + + GMimeSignature *msig; + GMimeCertificate *cert; + GMimeSignatureStatus sigstat; + gchar *rep; + + msig = g_mime_signature_list_get_signature (sigs, i); + sigstat = g_mime_signature_get_status (msig); + + /* downgrade our expectations */ + if ((sigstat & GMIME_SIGNATURE_STATUS_ERROR_MASK) && + status != MU_MSG_PART_SIG_STATUS_ERROR) + status = MU_MSG_PART_SIG_STATUS_ERROR; + else if ((sigstat & GMIME_SIGNATURE_STATUS_RED) && + status == MU_MSG_PART_SIG_STATUS_GOOD) + status = MU_MSG_PART_SIG_STATUS_BAD; + + rep = get_verdict_report (msig); + report = g_strdup_printf ("%s%s%d: %s", + report ? report : "", + report ? "; " : "", i + 1, + rep); + g_free (rep); + + cert = g_mime_signature_get_certificate (msig); + if (cert && g_mime_certificate_get_name (cert)) + g_hash_table_add ( + signerhash, + (gpointer)g_mime_certificate_get_name (cert)); + } + + status_report = g_slice_new0 (MuMsgPartSigStatusReport); + + status_report->verdict = status; + status_report->report = report; + status_report->signers = get_signers(signerhash); + + g_hash_table_unref (signerhash); + + return status_report; +} + +void +mu_msg_part_sig_status_report_destroy (MuMsgPartSigStatusReport *report) +{ + if (!report) + return; + + g_free ((char*)report->report); + g_free ((char*)report->signers); + + g_slice_free (MuMsgPartSigStatusReport, report); +} + + +static inline void +tag_with_sig_status(GObject *part, + MuMsgPartSigStatusReport *report) +{ + g_object_set_data_full + (part, SIG_STATUS_REPORT, report, + (GDestroyNotify)mu_msg_part_sig_status_report_destroy); +} + + +void +mu_msg_crypto_verify_part (GMimeMultipartSigned *sig, MuMsgOptions opts, + GError **err) +{ + /* the signature status */ + MuMsgPartSigStatusReport *report; + GMimeSignatureList *sigs; + + g_return_if_fail (GMIME_IS_MULTIPART_SIGNED(sig)); + + sigs = g_mime_multipart_signed_verify (sig, GMIME_VERIFY_NONE, err); + if (!sigs) { + if (err && !*err) + mu_util_g_set_error (err, MU_ERROR_CRYPTO, + "verification failed"); + return; + } + + report = get_status_report (sigs); + g_clear_object (&sigs); + + /* tag this part with the signature status check */ + tag_with_sig_status(G_OBJECT(sig), report); +} + + +static inline void +check_decrypt_result(GMimeMultipartEncrypted *part, GMimeDecryptResult *res, + GError **err) +{ + GMimeSignatureList *sigs; + MuMsgPartSigStatusReport *report; + + if (res) { + /* Check if the decrypted part had any embed signatures */ + sigs = res->signatures; + if (sigs) { + report = get_status_report (sigs); + g_mime_signature_list_clear (sigs); + + /* tag this part with the signature status check */ + tag_with_sig_status(G_OBJECT(part), report); + } + else { + if (err && !*err) + mu_util_g_set_error (err, MU_ERROR_CRYPTO, + "verification failed"); + } + g_object_unref (res); + } + +} + + +GMimeObject* /* this is declared in mu-msg-priv.h */ +mu_msg_crypto_decrypt_part (GMimeMultipartEncrypted *enc, MuMsgOptions opts, + MuMsgPartPasswordFunc func, gpointer user_data, + GError **err) +{ + GMimeObject *dec; + GMimeDecryptResult *res; + + g_return_val_if_fail (GMIME_IS_MULTIPART_ENCRYPTED(enc), NULL); + + res = NULL; + dec = g_mime_multipart_encrypted_decrypt (enc, GMIME_DECRYPT_NONE, NULL, + &res, err); + check_decrypt_result(enc, res, err); + + if (!dec) { + if (err && !*err) + mu_util_g_set_error (err, MU_ERROR_CRYPTO, + "decryption failed"); + return NULL; + } + + return dec; +} diff --git a/lib/mu-msg-doc.cc b/lib/mu-msg-doc.cc new file mode 100644 index 0000000..21c3c8b --- /dev/null +++ b/lib/mu-msg-doc.cc @@ -0,0 +1,124 @@ +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include <stdlib.h> +#include <iostream> +#include <string.h> +#include <errno.h> +#include <xapian.h> + +#include "mu-msg-fields.h" +#include "mu-msg-doc.h" + +#include "utils/mu-util.h" +#include "utils/mu-str.h" +#include "utils/mu-date.h" +#include "utils/mu-utils.hh" + +struct _MuMsgDoc { + + _MuMsgDoc (Xapian::Document *doc): _doc (doc) { } + ~_MuMsgDoc () { delete _doc; } + const Xapian::Document doc() const { return *_doc; } +private: + Xapian::Document *_doc; +}; + + +MuMsgDoc* +mu_msg_doc_new (XapianDocument *doc, GError **err) +{ + g_return_val_if_fail (doc, NULL); + + try { + return new MuMsgDoc ((Xapian::Document*)doc); + + } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(err, MU_ERROR_XAPIAN, NULL); + + return FALSE; +} + +void +mu_msg_doc_destroy (MuMsgDoc *self) +{ + try { + delete self; + + } MU_XAPIAN_CATCH_BLOCK; +} + + +gchar* +mu_msg_doc_get_str_field (MuMsgDoc *self, MuMsgFieldId mfid) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), NULL); + + // disable this check: + // g_return_val_if_fail (mu_msg_field_is_string(mfid), NULL); + // because it's useful to get numerical field as strings, + // for example when sorting (which is much faster if don't + // have to convert to numbers first, esp. when it's a date + // time_t) + + try { + const std::string s (self->doc().get_value(mfid)); + return s.empty() ? NULL : g_strdup (s.c_str()); + + } MU_XAPIAN_CATCH_BLOCK_RETURN(NULL); +} + + +GSList* +mu_msg_doc_get_str_list_field (MuMsgDoc *self, MuMsgFieldId mfid) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), NULL); + g_return_val_if_fail (mu_msg_field_is_string_list(mfid), NULL); + + try { + /* return a comma-separated string as a GSList */ + const std::string s (self->doc().get_value(mfid)); + return s.empty() ? NULL : mu_str_to_list(s.c_str(),',',TRUE); + + } MU_XAPIAN_CATCH_BLOCK_RETURN(NULL); +} + + +gint64 +mu_msg_doc_get_num_field (MuMsgDoc *self, MuMsgFieldId mfid) +{ + g_return_val_if_fail (self, -1); + g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), -1); + g_return_val_if_fail (mu_msg_field_is_numeric(mfid), -1); + + try { + const std::string s (self->doc().get_value(mfid)); + if (s.empty()) + return 0; + else if (mfid == MU_MSG_FIELD_ID_DATE || + mfid == MU_MSG_FIELD_ID_SIZE) + return strtol (s.c_str(), NULL, 10); + else { + return static_cast<gint64> + (Xapian::sortable_unserialise(s)); + } + + } MU_XAPIAN_CATCH_BLOCK_RETURN(-1); +} diff --git a/lib/mu-msg-doc.h b/lib/mu-msg-doc.h new file mode 100644 index 0000000..2f5fe5c --- /dev/null +++ b/lib/mu-msg-doc.h @@ -0,0 +1,96 @@ +/* +** Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_MSG_DOC_H__ +#define __MU_MSG_DOC_H__ + +#include <glib.h> +#include <utils/mu-util.h> + +G_BEGIN_DECLS + +struct _MuMsgDoc; +typedef struct _MuMsgDoc MuMsgDoc; + +/** + * create a new MuMsgDoc instance + * + * @param doc a Xapian::Document* (you'll need to cast the + * Xapian::Document* to XapianDocument*, because only C (not C++) is + * allowed in this header file. MuMsgDoc takes _ownership_ of this pointer; + * don't touch it afterwards + * @param err receives error info, or NULL + * + * @return a new MuMsgDoc instance (free with mu_msg_doc_destroy), or + * NULL in case of error. + */ +MuMsgDoc* mu_msg_doc_new (XapianDocument *doc, GError **err) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +/** + * destroy a MuMsgDoc instance -- free all the resources. Note, after + * destroying, any strings returned from mu_msg_doc_get_str_field with + * do_free==FALSE are no longer valid + * + * @param self a MuMsgDoc instance + */ +void mu_msg_doc_destroy (MuMsgDoc *self); + + +/** + * get a string parameter from the msgdoc + * + * @param self a MuMsgDoc instance + * @param mfid a MuMsgFieldId for a string field + * + * @return a string for the given field (see do_free), or NULL in case of error. + * free with g_free + */ +gchar* mu_msg_doc_get_str_field (MuMsgDoc *self, MuMsgFieldId mfid) + G_GNUC_WARN_UNUSED_RESULT; + +/** + * get a string-list parameter from the msgdoc + * + * @param self a MuMsgDoc instance + * @param mfid a MuMsgFieldId for a string-list field + * + * @return a list for the given field (see do_free), or NULL in case + * of error. free with mu_str_free_list + */ +GSList* mu_msg_doc_get_str_list_field (MuMsgDoc *self, MuMsgFieldId mfid) + G_GNUC_WARN_UNUSED_RESULT; + + +/** + * + * get a numeric parameter from the msgdoc + * + * @param self a MuMsgDoc instance + * @param mfid a MuMsgFieldId for a numeric field + * + * @return the numerical value, or -1 in case of error. You'll need to + * cast this value to the actual type (e.g. time_t for MU_MSG_FIELD_ID_DATE) + */ +gint64 mu_msg_doc_get_num_field (MuMsgDoc *self, MuMsgFieldId mfid); + + +G_END_DECLS + +#endif /*__MU_MSG_DOC_H__*/ diff --git a/lib/mu-msg-fields.c b/lib/mu-msg-fields.c new file mode 100644 index 0000000..daf3c2f --- /dev/null +++ b/lib/mu-msg-fields.c @@ -0,0 +1,425 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2008-2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include <string.h> +#include "mu-msg-fields.h" + +/* + * note: the differences for our purposes between a xapian field and a + * term: - there is only a single value for some item in per document + * (msg), ie. one value containing the list of To: addresses - there + * can be multiple terms, each containing e.g. one of the To: + * addresses - searching uses terms, but to display some field, it + * must be in the value (at least when using MuMsgIter) + */ +enum _FieldFlags { + FLAG_GMIME = 1 << 0, /* field retrieved through + * gmime */ + FLAG_XAPIAN_INDEX = 1 << 1, /* field is indexed in + * xapian (i.e., the text + * is processed */ + FLAG_XAPIAN_TERM = 1 << 2, /* field stored as term in + * xapian (so it can be searched) */ + FLAG_XAPIAN_VALUE = 1 << 3, /* field stored as value in + * xapian (so the literal + * value can be + * retrieved) */ + FLAG_XAPIAN_CONTACT = 1 << 4, /* field contains one or more + * e-mail-addresses */ + FLAG_XAPIAN_BOOLEAN = 1 << 5, /* use 'add_boolean_prefix' + * for Xapian queries; + * wildcards do NOT WORK + * for such fields */ + FLAG_DONT_CACHE = 1 << 6, /* don't cache this field in + * the MuMsg cache */ + FLAG_RANGE_FIELD = 1 << 7 /* whether this is a range field */ + +}; +typedef enum _FieldFlags FieldFlags; + +/* + * this struct describes the fields of an e-mail + /*/ +struct _MuMsgField { + MuMsgFieldId _id; /* the id of the field */ + MuMsgFieldType _type; /* the type of the field */ + const char *_name; /* the name of the field */ + const char _shortcut; /* the shortcut for use in + * --fields and sorting */ + const char _xprefix; /* the Xapian-prefix */ + FieldFlags _flags; /* the flags that tells us + * what to do */ +}; +typedef struct _MuMsgField MuMsgField; + +/* the name and shortcut fields must be lower case, or they might be + * misinterpreted by the query-preprocesser which turns queries into + * lowercase */ +static const MuMsgField FIELD_DATA[] = { + + { + MU_MSG_FIELD_ID_BCC, + MU_MSG_FIELD_TYPE_STRING, + "bcc" , 'h', 'H', /* 'hidden */ + FLAG_GMIME | FLAG_XAPIAN_CONTACT | + FLAG_XAPIAN_VALUE + }, + + { + MU_MSG_FIELD_ID_BODY_TEXT, + MU_MSG_FIELD_TYPE_STRING, + "body", 'b', 'B', + FLAG_GMIME | FLAG_XAPIAN_INDEX | + FLAG_DONT_CACHE + }, + + { + MU_MSG_FIELD_ID_BODY_HTML, + MU_MSG_FIELD_TYPE_STRING, + "bodyhtml", 0, 0, + FLAG_GMIME | FLAG_DONT_CACHE + }, + + { + MU_MSG_FIELD_ID_CC, + MU_MSG_FIELD_TYPE_STRING, + "cc", 'c', 'C', + FLAG_GMIME | FLAG_XAPIAN_CONTACT | FLAG_XAPIAN_VALUE + }, + + { + MU_MSG_FIELD_ID_DATE, + MU_MSG_FIELD_TYPE_TIME_T, + "date", 'd', 'D', + FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE | + FLAG_XAPIAN_BOOLEAN | FLAG_RANGE_FIELD + }, + + { + MU_MSG_FIELD_ID_EMBEDDED_TEXT, + MU_MSG_FIELD_TYPE_STRING, + "embed", 'e', 'E', + FLAG_GMIME | FLAG_XAPIAN_INDEX | FLAG_DONT_CACHE + }, + + { + MU_MSG_FIELD_ID_FILE, + MU_MSG_FIELD_TYPE_STRING, + "file" , 'j', 'J', + FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_DONT_CACHE + }, + + + { + MU_MSG_FIELD_ID_FLAGS, + MU_MSG_FIELD_TYPE_INT, + "flag", 'g', 'G', /* flaGs */ + FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE + }, + + { + MU_MSG_FIELD_ID_FROM, + MU_MSG_FIELD_TYPE_STRING, + "from", 'f', 'F', + FLAG_GMIME | FLAG_XAPIAN_CONTACT | FLAG_XAPIAN_VALUE + }, + + + { + MU_MSG_FIELD_ID_MAILDIR, + MU_MSG_FIELD_TYPE_STRING, + "maildir", 'm', 'M', + FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE + }, + + + { + MU_MSG_FIELD_ID_MAILING_LIST, + MU_MSG_FIELD_TYPE_STRING, + "list", 'v', 'V', + FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE + }, + + + { + MU_MSG_FIELD_ID_MIME, + MU_MSG_FIELD_TYPE_STRING, + "mime" , 'y', 'Y', + FLAG_XAPIAN_TERM + }, + + + { + MU_MSG_FIELD_ID_MSGID, + MU_MSG_FIELD_TYPE_STRING, + "msgid", 'i', 'I', /* 'i' for Id */ + FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE + }, + + + { + MU_MSG_FIELD_ID_PATH, + MU_MSG_FIELD_TYPE_STRING, + "path", 'l', 'L', /* 'l' for location */ + FLAG_GMIME | FLAG_XAPIAN_VALUE | + FLAG_XAPIAN_BOOLEAN + }, + + + { + MU_MSG_FIELD_ID_PRIO, + MU_MSG_FIELD_TYPE_INT, + "prio", 'p', 'P', + FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE + }, + + + { + MU_MSG_FIELD_ID_REFS, + MU_MSG_FIELD_TYPE_STRING_LIST, + "refs", 'r', 'R', + FLAG_GMIME | FLAG_XAPIAN_VALUE + }, + + + { + MU_MSG_FIELD_ID_SIZE, + MU_MSG_FIELD_TYPE_BYTESIZE, + "size", 'z', 'Z', /* siZe */ + FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE | + FLAG_RANGE_FIELD + }, + + { + MU_MSG_FIELD_ID_SUBJECT, + MU_MSG_FIELD_TYPE_STRING, + "subject", 's', 'S', + FLAG_GMIME | FLAG_XAPIAN_INDEX | FLAG_XAPIAN_VALUE | + FLAG_XAPIAN_TERM + }, + + { + MU_MSG_FIELD_ID_TAGS, + MU_MSG_FIELD_TYPE_STRING_LIST, + "tag", 'x', 'X', + FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE + }, + + + { /* remember which thread this message is in */ + MU_MSG_FIELD_ID_THREAD_ID, + MU_MSG_FIELD_TYPE_STRING, + "thread", 0, 'W', + FLAG_XAPIAN_TERM + }, + + { + MU_MSG_FIELD_ID_TO, + MU_MSG_FIELD_TYPE_STRING, + "to", 't', 'T', + FLAG_GMIME | FLAG_XAPIAN_CONTACT | FLAG_XAPIAN_VALUE + }, + + { /* special, internal field, to get a unique key */ + MU_MSG_FIELD_ID_UID, + MU_MSG_FIELD_TYPE_STRING, + "uid", 0, 'U', + FLAG_XAPIAN_TERM + } + + /* note, mu-store also use the 'Q' internal prefix for its uids */ +}; + +/* the MsgField data in an array, indexed by the MsgFieldId; + * this allows for O(1) access + */ +static MuMsgField* _msg_field_data[MU_MSG_FIELD_ID_NUM]; +static const MuMsgField* mu_msg_field (MuMsgFieldId id) +{ + static gboolean _initialized = FALSE; + + /* initialize the array, but only once... */ + if (G_UNLIKELY(!_initialized)) { + int i; + for (i = 0; i != G_N_ELEMENTS(FIELD_DATA); ++i) + _msg_field_data[FIELD_DATA[i]._id] = + (MuMsgField*)&FIELD_DATA[i]; + _initialized = TRUE; + } + + return _msg_field_data[id]; +} + + +void +mu_msg_field_foreach (MuMsgFieldForeachFunc func, gconstpointer data) +{ + int i; + for (i = 0; i != MU_MSG_FIELD_ID_NUM; ++i) + func (i, data); +} + + +MuMsgFieldId +mu_msg_field_id_from_name (const char* str, gboolean err) +{ + int i; + + g_return_val_if_fail (str, MU_MSG_FIELD_ID_NONE); + + for (i = 0; i != G_N_ELEMENTS(FIELD_DATA); ++i) + if (g_strcmp0(str, FIELD_DATA[i]._name) == 0) + return FIELD_DATA[i]._id; + if (err) + g_return_val_if_reached (MU_MSG_FIELD_ID_NONE); + + return MU_MSG_FIELD_ID_NONE; +} + + +MuMsgFieldId +mu_msg_field_id_from_shortcut (char kar, gboolean err) +{ + int i; + for (i = 0; i != G_N_ELEMENTS(FIELD_DATA); ++i) + if (kar == FIELD_DATA[i]._shortcut) + return FIELD_DATA[i]._id; + + if (err) + g_return_val_if_reached (MU_MSG_FIELD_ID_NONE); + + return MU_MSG_FIELD_ID_NONE; +} + + +gboolean +mu_msg_field_gmime (MuMsgFieldId id) +{ + g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); + return mu_msg_field(id)->_flags & FLAG_GMIME ? TRUE: FALSE; +} + + +gboolean +mu_msg_field_xapian_index (MuMsgFieldId id) +{ + g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); + return mu_msg_field(id)->_flags & + (FLAG_XAPIAN_INDEX | FLAG_XAPIAN_CONTACT) ? TRUE: FALSE; +} + +gboolean +mu_msg_field_xapian_value (MuMsgFieldId id) +{ + g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); + return mu_msg_field(id)->_flags & FLAG_XAPIAN_VALUE ? TRUE: FALSE; +} + +gboolean +mu_msg_field_xapian_term (MuMsgFieldId id) +{ + g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); + return mu_msg_field(id)->_flags & FLAG_XAPIAN_TERM ? TRUE: FALSE; +} + + +gboolean +mu_msg_field_is_range_field (MuMsgFieldId id) +{ + g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); + return mu_msg_field(id)->_flags & FLAG_RANGE_FIELD ? TRUE: FALSE; +} + + + +gboolean +mu_msg_field_uses_boolean_prefix (MuMsgFieldId id) +{ + g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); + return mu_msg_field(id)->_flags & FLAG_XAPIAN_BOOLEAN ? TRUE:FALSE; +} + + + +gboolean +mu_msg_field_is_cacheable (MuMsgFieldId id) +{ + g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); + /* note the FALSE: TRUE */ + return mu_msg_field(id)->_flags & FLAG_DONT_CACHE ? FALSE : TRUE; +} + +gboolean +mu_msg_field_xapian_contact (MuMsgFieldId id) +{ + g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); + return mu_msg_field(id)->_flags & FLAG_XAPIAN_CONTACT ? TRUE: FALSE; +} + + + +gboolean +mu_msg_field_is_numeric (MuMsgFieldId mfid) +{ + MuMsgFieldType type; + + g_return_val_if_fail (mu_msg_field_id_is_valid(mfid),FALSE); + + type = mu_msg_field_type (mfid); + + return type == MU_MSG_FIELD_TYPE_BYTESIZE || + type == MU_MSG_FIELD_TYPE_TIME_T || + type == MU_MSG_FIELD_TYPE_INT; +} + +const char* +mu_msg_field_name (MuMsgFieldId id) +{ + g_return_val_if_fail (mu_msg_field_id_is_valid(id),NULL); + return mu_msg_field(id)->_name; +} + + +char +mu_msg_field_shortcut (MuMsgFieldId id) +{ + g_return_val_if_fail (mu_msg_field_id_is_valid(id),0); + return mu_msg_field(id)->_shortcut; +} + + +char +mu_msg_field_xapian_prefix (MuMsgFieldId id) +{ + g_return_val_if_fail (mu_msg_field_id_is_valid(id),0); + return mu_msg_field(id)->_xprefix; +} + + + + +MuMsgFieldType +mu_msg_field_type (MuMsgFieldId id) +{ + g_return_val_if_fail (mu_msg_field_id_is_valid(id), + MU_MSG_FIELD_TYPE_NONE); + return mu_msg_field(id)->_type; +} diff --git a/lib/mu-msg-fields.h b/lib/mu-msg-fields.h new file mode 100644 index 0000000..08bfe60 --- /dev/null +++ b/lib/mu-msg-fields.h @@ -0,0 +1,292 @@ +/* +** Copyright (C) 2008-2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_MSG_FIELDS_H__ +#define __MU_MSG_FIELDS_H__ + +#include <glib.h> + +G_BEGIN_DECLS + +/* don't change the order, add new types at the end, as these numbers + * are used in the database */ +enum _MuMsgFieldId { + + /* first all the string-based ones */ + MU_MSG_FIELD_ID_BCC = 0, + MU_MSG_FIELD_ID_BODY_HTML, + MU_MSG_FIELD_ID_BODY_TEXT, + MU_MSG_FIELD_ID_CC, + MU_MSG_FIELD_ID_EMBEDDED_TEXT, + MU_MSG_FIELD_ID_FILE, + MU_MSG_FIELD_ID_FROM, + MU_MSG_FIELD_ID_MAILDIR, + MU_MSG_FIELD_ID_MIME, /* mime-type */ + MU_MSG_FIELD_ID_MSGID, + MU_MSG_FIELD_ID_PATH, + MU_MSG_FIELD_ID_SUBJECT, + MU_MSG_FIELD_ID_TO, + + MU_MSG_FIELD_ID_UID, /* special, generated from path */ + + /* string list items... */ + MU_MSG_FIELD_ID_REFS, + MU_MSG_FIELD_ID_TAGS, + + /* then the numerical ones */ + MU_MSG_FIELD_ID_DATE, + MU_MSG_FIELD_ID_FLAGS, + MU_MSG_FIELD_ID_PRIO, + MU_MSG_FIELD_ID_SIZE, + + /* add new ones here... */ + MU_MSG_FIELD_ID_MAILING_LIST, /* mailing list */ + MU_MSG_FIELD_ID_THREAD_ID, + + MU_MSG_FIELD_ID_NUM +}; +typedef guint8 MuMsgFieldId; + +/* some specials... */ +static const MuMsgFieldId MU_MSG_FIELD_ID_NONE = (MuMsgFieldId)-1; +#define MU_MSG_STRING_FIELD_ID_NUM (MU_MSG_FIELD_ID_UID + 1) + +/* this is a shortcut for To/From/Cc/Bcc in queries; handled specially + * in mu-query.cc and mu-str.c */ +#define MU_MSG_FIELD_PSEUDO_CONTACT "contact" + +/* this is a shortcut for To/Cc/Bcc in queries; handled specially in + * mu-query.cc and mu-str.c */ +#define MU_MSG_FIELD_PSEUDO_RECIP "recip" + +#define mu_msg_field_id_is_valid(MFID) \ + ((MFID) < MU_MSG_FIELD_ID_NUM) + +/* don't change the order, add new types at the end (before _NUM)*/ +enum _MuMsgFieldType { + MU_MSG_FIELD_TYPE_STRING, + MU_MSG_FIELD_TYPE_STRING_LIST, + + MU_MSG_FIELD_TYPE_BYTESIZE, + MU_MSG_FIELD_TYPE_TIME_T, + MU_MSG_FIELD_TYPE_INT, + + MU_MSG_FIELD_TYPE_NUM +}; +typedef guint8 MuMsgFieldType; +static const MuMsgFieldType MU_MSG_FIELD_TYPE_NONE = (MuMsgFieldType)-1; + +typedef void (*MuMsgFieldForeachFunc) (MuMsgFieldId id, + gconstpointer data); + +/** + * iterator over all possible message fields + * + * @param func a function called for each field + * @param data a user data pointer passed the callback function + */ +void mu_msg_field_foreach (MuMsgFieldForeachFunc func, gconstpointer data); + + +/** + * get the name of the field -- this a name that can be use in queries, + * ie. 'subject:foo', with 'subject' being the name + * + * @param id a MuMsgFieldId + * + * @return the name of the field as a constant string, or + * NULL if the field is unknown + */ +const char* mu_msg_field_name (MuMsgFieldId id) G_GNUC_PURE; + +/** + * get the shortcut of the field -- this a shortcut that can be use in + * queries, ie. 's:foo', with 's' meaning 'subject' being the name + * + * @param id a MuMsgFieldId + * + * @return the shortcut character, or 0 if the field is unknown + */ +char mu_msg_field_shortcut (MuMsgFieldId id) G_GNUC_PURE; + +/** + * get the xapian prefix of the field -- that is, the prefix used in + * the Xapian database to identify the field + * + * @param id a MuMsgFieldId + * + * @return the xapian prefix char or 0 if the field is unknown + */ +char mu_msg_field_xapian_prefix (MuMsgFieldId id) G_GNUC_PURE; + + +/** + * get the type of the field (string, size, time etc.) + * + * @param field a MuMsgField + * + * @return the type of the field (a #MuMsgFieldType), or + * MU_MSG_FIELD_TYPE_NONE if it is not found + */ +MuMsgFieldType mu_msg_field_type (MuMsgFieldId id) G_GNUC_PURE; + + + +/** + * is the field a string? + * + * @param id a MuMsgFieldId + * + * @return TRUE if the field a string, FALSE otherwise + */ +#define mu_msg_field_is_string(MFID)\ + (mu_msg_field_type((MFID))==MU_MSG_FIELD_TYPE_STRING?TRUE:FALSE) + + + +/** + * is the field a string-list? + * + * @param id a MuMsgFieldId + * + * @return TRUE if the field a string-list, FALSE otherwise + */ +#define mu_msg_field_is_string_list(MFID)\ + (mu_msg_field_type((MFID))==MU_MSG_FIELD_TYPE_STRING_LIST?TRUE:FALSE) + +/** + * is the field numeric (has type MU_MSG_FIELD_TYPE_(BYTESIZE|TIME_T|INT))? + * + * @param id a MuMsgFieldId + * + * @return TRUE if the field is numeric, FALSE otherwise + */ +gboolean mu_msg_field_is_numeric (MuMsgFieldId id) G_GNUC_PURE; + + +/** + * whether the field value should be cached (in MuMsg) -- we cache + * values so we can use the MuMsg without needing to keep the + * underlying data source (the GMimeMessage or the database ptr) alive + * in practice, the fields we *don't* cache are the message body + * (html, txt), because they take too much memory + */ +gboolean mu_msg_field_is_cacheable (MuMsgFieldId id) G_GNUC_PURE; + + +/** + * is the field Xapian-indexable? That is, should this field be + * indexed in the Xapian database, so we can use the all the + * phrasing, stemming etc. magic + * + * @param id a MuMsgFieldId + * + * @return TRUE if the field is Xapian-enabled, FALSE otherwise + */ +gboolean mu_msg_field_xapian_index (MuMsgFieldId id) G_GNUC_PURE; + +/** + * should this field be stored as a xapian term? + * + * @param id a MuMsgFieldId + * + * @return TRUE if the field is Xapian-enabled, FALSE otherwise + */ +gboolean mu_msg_field_xapian_term (MuMsgFieldId id) G_GNUC_PURE; + +/** + * should this field be stored as a xapian value? + * + * @param field a MuMsgField + * + * @return TRUE if the field is Xapian-enabled, FALSE otherwise + */ +gboolean mu_msg_field_xapian_value (MuMsgFieldId id) G_GNUC_PURE; + + +/** + * whether we should use add_boolean_prefix (see Xapian documentation) + * for this field in queries. Used in mu-query.cc + * + * @param id a MuMsgFieldId + * + * @return TRUE if this field wants add_boolean_prefix, FALSE + * otherwise + */ +gboolean mu_msg_field_uses_boolean_prefix (MuMsgFieldId id) G_GNUC_PURE; + +/** + * is this a range-field? ie. date, or size + * + * @param id a MuMsgField + * + * @return TRUE if this field is a range field, FALSE otherwise + */ +gboolean mu_msg_field_is_range_field (MuMsgFieldId id) G_GNUC_PURE; + + +/** + * should this field be stored as contact information? This means that + * e-mail address will be stored as terms, and names will be indexed + * + * @param id a MuMsgFieldId + * + * @return TRUE if the field should be stored as contact information, + * FALSE otherwise + */ +gboolean mu_msg_field_xapian_contact (MuMsgFieldId id) G_GNUC_PURE; + +/** + * is the field gmime-enabled? That is, can be field be retrieved + * using GMime? + * + * @param id a MuMsgFieldId + * + * @return TRUE if the field is Gmime-enabled, FALSE otherwise + */ +gboolean mu_msg_field_gmime (MuMsgFieldId id) G_GNUC_PURE; + + +/** + * get the corresponding MuMsgField for a name (as in mu_msg_field_name) + * + * @param str a name + * @param err, if TRUE, when the shortcut is not found, will issue a + * g_critical warning + * + * @return a MuMsgField, or NULL if it could not be found + */ +MuMsgFieldId mu_msg_field_id_from_name (const char* str, + gboolean err) G_GNUC_PURE; + + +/** + * get the corresponding MuMsgField for a shortcut (as in mu_msg_field_shortcut) + * + * @param kar a shortcut character + * @param err, if TRUE, when the shortcut is not found, will issue a + * g_critical warning + * + * @return a MuMsgField, or NULL if it could not be found + */ +MuMsgFieldId mu_msg_field_id_from_shortcut (char kar, + gboolean err) G_GNUC_PURE; +G_END_DECLS + +#endif /*__MU_MSG_FIELDS_H__*/ diff --git a/lib/mu-msg-file.c b/lib/mu-msg-file.c new file mode 100644 index 0000000..f0fa306 --- /dev/null +++ b/lib/mu-msg-file.c @@ -0,0 +1,815 @@ +/* -*- mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +** +** Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#include <stdlib.h> +#include <ctype.h> +#include <inttypes.h> + +#include <gmime/gmime.h> +#include "mu-maildir.h" +#include "mu-store.hh" +#include "mu-msg-priv.h" + +#include "utils/mu-util.h" +#include "utils/mu-str.h" + +static gboolean init_file_metadata (MuMsgFile *self, const char* path, + const char *mdir, GError **err); +static gboolean init_mime_msg (MuMsgFile *msg, const char *path, GError **err); + +MuMsgFile* +mu_msg_file_new (const char* filepath, const char *mdir, GError **err) +{ + MuMsgFile *self; + + g_return_val_if_fail (filepath, NULL); + + self = g_slice_new0 (MuMsgFile); + + if (!init_file_metadata (self, filepath, mdir, err)) { + mu_msg_file_destroy (self); + return NULL; + } + + if (!init_mime_msg (self, filepath, err)) { + mu_msg_file_destroy (self); + return NULL; + } + + return self; +} + +void +mu_msg_file_destroy (MuMsgFile *self) +{ + if (!self) + return; + + if (self->_mime_msg) + g_object_unref (self->_mime_msg); + + g_slice_free (MuMsgFile, self); +} + +static gboolean +init_file_metadata (MuMsgFile *self, const char* path, const gchar* mdir, + GError **err) +{ + struct stat statbuf; + + if (access (path, R_OK) != 0) { + mu_util_g_set_error (err, MU_ERROR_FILE, + "cannot read file %s: %s", + path, strerror(errno)); + return FALSE; + } + + if (stat (path, &statbuf) < 0) { + mu_util_g_set_error (err, MU_ERROR_FILE, + "cannot stat %s: %s", + path, strerror(errno)); + return FALSE; + } + + if (!S_ISREG(statbuf.st_mode)) { + mu_util_g_set_error (err, MU_ERROR_FILE, + "not a regular file: %s", path); + return FALSE; + } + + self->_timestamp = statbuf.st_mtime; + self->_size = (size_t)statbuf.st_size; + + /* remove double slashes, relative paths etc. from path & mdir */ + if (!realpath (path, self->_path)) { + mu_util_g_set_error (err, MU_ERROR_FILE, + "could not get realpath for %s: %s", + path, strerror(errno)); + return FALSE; + } + + strncpy (self->_maildir, mdir ? mdir : "", PATH_MAX); + return TRUE; +} + +static GMimeStream* +get_mime_stream (MuMsgFile *self, const char *path, GError **err) +{ + FILE *file; + GMimeStream *stream; + + file = fopen (path, "r"); + if (!file) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, + "cannot open %s: %s", + path, strerror (errno)); + return NULL; + } + + stream = g_mime_stream_file_new (file); + if (!stream) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, + "cannot create mime stream for %s", + path); + fclose (file); + return NULL; + } + + return stream; +} + +static gboolean +init_mime_msg (MuMsgFile *self, const char* path, GError **err) +{ + GMimeStream *stream; + GMimeParser *parser; + + stream = get_mime_stream (self, path, err); + if (!stream) + return FALSE; + + parser = g_mime_parser_new_with_stream (stream); + g_object_unref (stream); + if (!parser) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, + "cannot create mime parser for %s", path); + return FALSE; + } + + self->_mime_msg = g_mime_parser_construct_message (parser, NULL); + g_object_unref (parser); + if (!self->_mime_msg) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, + "message seems invalid, ignoring (%s)", path); + return FALSE; + } + + return TRUE; +} + +static char* +get_recipient (MuMsgFile *self, GMimeAddressType atype) +{ + char *recip; + InternetAddressList *recips; + + recips = g_mime_message_get_addresses (self->_mime_msg, atype); + + /* FALSE --> don't encode */ + recip = (char*)internet_address_list_to_string (recips, NULL, FALSE); + + if (recip && !g_utf8_validate (recip, -1, NULL)) { + g_debug ("invalid recipient in %s\n", self->_path); + mu_str_asciify_in_place (recip); /* ugly... */ + } + + if (mu_str_is_empty(recip)) { + g_free (recip); + return NULL; + } + + if (recip) + mu_str_remove_ctrl_in_place (recip); + + return recip; +} + +/* + * let's try to guess the mailing list from some other + * headers in the mail + */ +static gchar* +get_fake_mailing_list_maybe (MuMsgFile *self) +{ + const char* hdr; + + hdr = g_mime_object_get_header (GMIME_OBJECT(self->_mime_msg), + "X-Feed2Imap-Version"); + if (!hdr) + return NULL; + + /* looks like a feed2imap header; guess the source-blog + * from the msgid */ + { + const char *msgid, *e; + msgid = g_mime_message_get_message_id (self->_mime_msg); + if (msgid && (e = strchr (msgid, '-'))) + return g_strndup (msgid, e - msgid); + } + + return NULL; +} + +static gchar* +get_mailing_list (MuMsgFile *self) +{ + char *dechdr, *res; + const char *hdr, *b, *e; + + hdr = g_mime_object_get_header (GMIME_OBJECT(self->_mime_msg), + "List-Id"); + if (mu_str_is_empty (hdr)) + return get_fake_mailing_list_maybe (self); + + dechdr = g_mime_utils_header_decode_phrase (NULL, hdr); + if (!dechdr) + return NULL; + + e = NULL; + b = strchr (dechdr, '<'); + if (b) + e = strchr (b, '>'); + + if (b && e) + res = g_strndup (b + 1, e - b - 1); + else + res = g_strdup (dechdr); + + g_free (dechdr); + + return res; +} + +static gboolean +looks_like_attachment (GMimeObject *part) +{ + + GMimeContentDisposition *disp; + GMimeContentType *ctype; + const char *dispstr; + guint u; + const struct { + const char *type; + const char *sub_type; + } att_types[] = { + { "image", "*" }, + { "audio", "*" }, + { "application", "*"}, + { "application", "x-patch"} + }; + + disp = g_mime_object_get_content_disposition (part); + + if (!GMIME_IS_CONTENT_DISPOSITION(disp)) + return FALSE; + + dispstr = g_mime_content_disposition_get_disposition (disp); + + if (g_ascii_strcasecmp (dispstr, "attachment") == 0) + return TRUE; + + /* we also consider patches, images, audio, and non-pgp-signature + * application attachments to be attachments... */ + ctype = g_mime_object_get_content_type (part); + + if (g_mime_content_type_is_type (ctype, "*", "pgp-signature")) + return FALSE; /* don't consider as a signature */ + + if (g_mime_content_type_is_type (ctype, "text", "*")) { + if (g_mime_content_type_is_type (ctype, "*", "plain") || + g_mime_content_type_is_type (ctype, "*", "html")) + return FALSE; + else + return TRUE; + } + + for (u = 0; u != G_N_ELEMENTS(att_types); ++u) + if (g_mime_content_type_is_type ( + ctype, att_types[u].type, att_types[u].sub_type)) + return TRUE; + + return FALSE; +} + +static void +msg_cflags_cb (GMimeObject *parent, GMimeObject *part, MuFlags *flags) +{ + if (GMIME_IS_MULTIPART_SIGNED(part)) + *flags |= MU_FLAG_SIGNED; + + /* FIXME: An encrypted part might be signed at the same time. + * In that case the signed flag is lost. */ + if (GMIME_IS_MULTIPART_ENCRYPTED(part)) + *flags |= MU_FLAG_ENCRYPTED; + + if (*flags & MU_FLAG_HAS_ATTACH) + return; + + if (!GMIME_IS_PART(part)) + return; + + if (*flags & MU_FLAG_HAS_ATTACH) + return; + + if (looks_like_attachment (part)) + *flags |= MU_FLAG_HAS_ATTACH; +} + +static MuFlags +get_content_flags (MuMsgFile *self) +{ + MuFlags flags; + char *ml; + + flags = MU_FLAG_NONE; + + if (GMIME_IS_MESSAGE(self->_mime_msg)) + mu_mime_message_foreach (self->_mime_msg, + FALSE, /* never decrypt for this */ + (GMimeObjectForeachFunc)msg_cflags_cb, + &flags); + + ml = get_mailing_list (self); + if (ml) { + flags |= MU_FLAG_LIST; + g_free (ml); + } + + return flags; +} + +static MuFlags +get_flags (MuMsgFile *self) +{ + MuFlags flags; + + g_return_val_if_fail (self, MU_FLAG_INVALID); + + flags = mu_maildir_get_flags_from_path (self->_path); + flags |= get_content_flags (self); + + /* pseudo-flag --> unread means either NEW or NOT SEEN, just + * for searching convenience */ + if ((flags & MU_FLAG_NEW) || !(flags & MU_FLAG_SEEN)) + flags |= MU_FLAG_UNREAD; + + return flags; +} + +static size_t +get_size (MuMsgFile *self) +{ + g_return_val_if_fail (self, 0); + return self->_size; +} + +static MuMsgPrio +parse_prio_str (const char* priostr) +{ + int i; + struct { + const char* _str; + MuMsgPrio _prio; + } str_prio[] = { + { "high", MU_MSG_PRIO_HIGH }, + { "1", MU_MSG_PRIO_HIGH }, + { "2", MU_MSG_PRIO_HIGH }, + + { "normal", MU_MSG_PRIO_NORMAL }, + { "3", MU_MSG_PRIO_NORMAL }, + + { "low", MU_MSG_PRIO_LOW }, + { "list", MU_MSG_PRIO_LOW }, + { "bulk", MU_MSG_PRIO_LOW }, + { "4", MU_MSG_PRIO_LOW }, + { "5", MU_MSG_PRIO_LOW } + }; + + for (i = 0; i != G_N_ELEMENTS(str_prio); ++i) + if (g_ascii_strcasecmp (priostr, str_prio[i]._str) == 0) + return str_prio[i]._prio; + + /* e.g., last-fm uses 'fm-user'... as precedence */ + return MU_MSG_PRIO_NORMAL; +} + +static MuMsgPrio +get_prio (MuMsgFile *self) +{ + GMimeObject *obj; + const char* priostr; + + g_return_val_if_fail (self, MU_MSG_PRIO_NONE); + + obj = GMIME_OBJECT(self->_mime_msg); + + priostr = g_mime_object_get_header (obj, "Precedence"); + if (!priostr) + priostr = g_mime_object_get_header (obj, "X-Priority"); + if (!priostr) + priostr = g_mime_object_get_header (obj, "Importance"); + + return priostr ? parse_prio_str (priostr) : MU_MSG_PRIO_NORMAL; +} + +/* NOTE: buffer will be *freed* or returned unchanged */ +static char* +convert_to_utf8 (GMimePart *part, char *buffer) +{ + GMimeContentType *ctype; + const char* charset; + + ctype = g_mime_object_get_content_type (GMIME_OBJECT(part)); + g_return_val_if_fail (GMIME_IS_CONTENT_TYPE(ctype), NULL); + + /* of course, the charset specified may be incorrect... */ + charset = g_mime_content_type_get_parameter (ctype, "charset"); + if (charset) { + char *utf8; + if ((utf8 = mu_str_convert_to_utf8 + (buffer, g_mime_charset_iconv_name (charset)))) { + g_free (buffer); + buffer = utf8; + } + } else if (!g_utf8_validate (buffer, -1, NULL)) { + /* if it's already utf8, nothing to do otherwise: no + charset at all, or conversion failed; ugly * hack: + replace all non-ascii chars with '.' */ + mu_str_asciify_in_place (buffer); + } + + return buffer; +} + +static gchar* +stream_to_string (GMimeStream *stream, size_t buflen) +{ + char *buffer; + ssize_t bytes; + + buffer = g_new(char, buflen + 1); + g_mime_stream_reset (stream); + + /* we read everything in one go */ + bytes = g_mime_stream_read (stream, buffer, buflen); + if (bytes < 0) { + g_warning ("%s: failed to read from stream", __func__); + g_free (buffer); + return NULL; + } + + buffer[bytes]='\0'; + + return buffer; +} + +gchar* +mu_msg_mime_part_to_string (GMimePart *part, gboolean *err) +{ + GMimeDataWrapper *wrapper; + GMimeStream *stream; + ssize_t buflen; + char *buffer; + + buffer = NULL; + stream = NULL; + + g_return_val_if_fail (err, NULL); + + *err = TRUE; /* guilty until proven innocent */ + g_return_val_if_fail (GMIME_IS_PART(part), NULL); + + wrapper = g_mime_part_get_content (part); + if (!wrapper) { + /* this happens with invalid mails */ + g_debug ("failed to create data wrapper"); + goto cleanup; + } + + stream = g_mime_stream_mem_new (); + if (!stream) { + g_warning ("failed to create mem stream"); + goto cleanup; + } + + buflen = g_mime_data_wrapper_write_to_stream (wrapper, stream); + if (buflen <= 0) {/* empty buffer, not an error */ + *err = FALSE; + goto cleanup; + } + + buffer = stream_to_string (stream, (size_t)buflen); + + /* convert_to_utf8 will free the old 'buffer' if needed */ + buffer = convert_to_utf8 (part, buffer); + *err = FALSE; + +cleanup: + if (G_IS_OBJECT(stream)) + g_object_unref (stream); + + return buffer; +} + +static gboolean +contains (GSList *lst, const char *str) +{ + for (; lst; lst = g_slist_next(lst)) + if (g_strcmp0 ((char*)lst->data, str) == 0) + return TRUE; + return FALSE; +} + +/* + * NOTE: this will get the list of references with the oldest parent + * at the beginning */ +static GSList* +get_references (MuMsgFile *self) +{ + GSList *msgids; + unsigned u; + const char *headers[] = { "References", "In-reply-to", NULL }; + + for (msgids = NULL, u = 0; headers[u]; ++u) { + + char *str; + GMimeReferences *mime_refs; + int i, refs_len; + + str = mu_msg_file_get_header (self, headers[u]); + if (!str) + continue; + + mime_refs = g_mime_references_parse (NULL, str); + g_free (str); + + refs_len = g_mime_references_length (mime_refs); + for (i = 0; i < refs_len; ++i) { + const char* msgid; + msgid = g_mime_references_get_message_id (mime_refs, i); + + /* don't include duplicates */ + if (msgid && !contains (msgids, msgid)) + /* explicitly ensure it's utf8-safe, + * as GMime does not ensure that */ + msgids = g_slist_prepend (msgids, + g_strdup((msgid))); + } + g_mime_references_free (mime_refs); + } + + /* reverse, because we used g_slist_prepend for performance + * reasons */ + return g_slist_reverse (msgids); +} + +/* see: http://does-not-exist.org/mail-archives/mutt-dev/msg08249.html */ +static GSList* +get_tags (MuMsgFile *self) +{ + GSList *lst; + unsigned u; + struct { + const char *header; + char sepa; + } tagfields[] = { + { "X-Label", ' ' }, + { "X-Keywords", ',' }, + { "Keywords", ' ' } + }; + + for (lst = NULL, u = 0; u != G_N_ELEMENTS(tagfields); ++u) { + gchar *hdr; + hdr = mu_msg_file_get_header (self, tagfields[u].header); + if (hdr) { + GSList *hlst; + hlst = mu_str_to_list (hdr, tagfields[u].sepa, TRUE); + + if (lst) + (g_slist_last (lst))->next = hlst; + else + lst = hlst; + + g_free (hdr); + } + } + + return lst; +} + +static char* +cleanup_maybe (const char *str, gboolean *do_free) +{ + char *s; + + if (!str) + return NULL; + + if (!g_utf8_validate(str, -1, NULL)) { + if (*do_free) + s = mu_str_asciify_in_place ((char*)str); + else { + *do_free = TRUE; + s = mu_str_asciify_in_place(g_strdup (str)); + } + } else + s = (char*)str; + + mu_str_remove_ctrl_in_place (s); + + return s; +} + +G_GNUC_CONST static GMimeAddressType +address_type (MuMsgFieldId mfid) +{ + switch (mfid) { + case MU_MSG_FIELD_ID_BCC : return GMIME_ADDRESS_TYPE_BCC; + case MU_MSG_FIELD_ID_CC : return GMIME_ADDRESS_TYPE_CC; + case MU_MSG_FIELD_ID_TO : return GMIME_ADDRESS_TYPE_TO; + case MU_MSG_FIELD_ID_FROM: return GMIME_ADDRESS_TYPE_FROM; + default: g_return_val_if_reached (-1); + } +} + +static gchar* +get_msgid (MuMsgFile *self, gboolean *do_free) +{ + const char *msgid; + + msgid = g_mime_message_get_message_id (self->_mime_msg); + if (msgid && strlen(msgid) < MU_STORE_MAX_TERM_LENGTH) { + return (char*)msgid; + } else { /* if there is none, fake it */ + *do_free = TRUE; + return g_strdup_printf ("%016" PRIx64 "@fake-msgid", + mu_util_get_hash (self->_path)); + } +} + +char* +mu_msg_file_get_str_field (MuMsgFile *self, MuMsgFieldId mfid, + gboolean *do_free) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (mu_msg_field_is_string(mfid), NULL); + + *do_free = FALSE; /* default */ + + switch (mfid) { + + case MU_MSG_FIELD_ID_BCC: + case MU_MSG_FIELD_ID_CC: + case MU_MSG_FIELD_ID_FROM: + case MU_MSG_FIELD_ID_TO: + *do_free = TRUE; + return get_recipient (self, address_type(mfid)); + + case MU_MSG_FIELD_ID_PATH: return self->_path; + + case MU_MSG_FIELD_ID_MAILING_LIST: + *do_free = TRUE; + return (char*)get_mailing_list (self); + + case MU_MSG_FIELD_ID_SUBJECT: + return (char*)cleanup_maybe + (g_mime_message_get_subject (self->_mime_msg), do_free); + + case MU_MSG_FIELD_ID_MSGID: + return get_msgid (self, do_free); + + case MU_MSG_FIELD_ID_MAILDIR: return self->_maildir; + + case MU_MSG_FIELD_ID_BODY_TEXT: /* use mu_msg_get_body_text */ + case MU_MSG_FIELD_ID_BODY_HTML: /* use mu_msg_get_body_html */ + case MU_MSG_FIELD_ID_EMBEDDED_TEXT: + g_warning ("%s is not retrievable through: %s", + mu_msg_field_name (mfid), __func__); + return NULL; + + default: g_return_val_if_reached (NULL); + } +} + +GSList* +mu_msg_file_get_str_list_field (MuMsgFile *self, MuMsgFieldId mfid) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (mu_msg_field_is_string_list(mfid), NULL); + + switch (mfid) { + case MU_MSG_FIELD_ID_REFS: return get_references (self); + case MU_MSG_FIELD_ID_TAGS: return get_tags (self); + default: g_return_val_if_reached (NULL); + } +} + +gint64 +mu_msg_file_get_num_field (MuMsgFile *self, const MuMsgFieldId mfid) +{ + g_return_val_if_fail (self, -1); + g_return_val_if_fail (mu_msg_field_is_numeric(mfid), -1); + + switch (mfid) { + + case MU_MSG_FIELD_ID_DATE: { + GDateTime *dt; + dt = g_mime_message_get_date (self->_mime_msg); + return dt ? g_date_time_to_unix (dt) : 0; + } + + case MU_MSG_FIELD_ID_FLAGS: + return (gint64)get_flags(self); + + case MU_MSG_FIELD_ID_PRIO: + return (gint64)get_prio(self); + + case MU_MSG_FIELD_ID_SIZE: + return (gint64)get_size(self); + + default: g_return_val_if_reached (-1); + } +} + +char* +mu_msg_file_get_header (MuMsgFile *self, const char *header) +{ + const gchar *hdr; + + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (header, NULL); + + /* sadly, g_mime_object_get_header may return non-ascii; + * so, we need to ensure that + */ + hdr = g_mime_object_get_header (GMIME_OBJECT(self->_mime_msg), + header); + + return hdr ? mu_str_utf8ify(hdr) : NULL; +} + +struct _ForeachData { + GMimeObjectForeachFunc user_func; + gpointer user_data; + gboolean decrypt; +}; +typedef struct _ForeachData ForeachData; + +static void +foreach_cb (GMimeObject *parent, GMimeObject *part, ForeachData *fdata) +{ + /* invoke the callback function */ + fdata->user_func (parent, part, fdata->user_data); + + /* maybe iterate over decrypted parts */ + if (fdata->decrypt && + GMIME_IS_MULTIPART_ENCRYPTED (part)) { + GMimeObject *dec; + dec = mu_msg_crypto_decrypt_part + (GMIME_MULTIPART_ENCRYPTED(part), + MU_MSG_OPTION_NONE, NULL, NULL, NULL); + if (!dec) + return; + + if (GMIME_IS_MULTIPART (dec)) + g_mime_multipart_foreach ( + (GMIME_MULTIPART(dec)), + (GMimeObjectForeachFunc)foreach_cb, + fdata); + else + foreach_cb (parent, dec, fdata); + + g_object_unref (dec); + } +} + +void +mu_mime_message_foreach (GMimeMessage *msg, gboolean decrypt, + GMimeObjectForeachFunc func, gpointer user_data) +{ + ForeachData fdata; + + g_return_if_fail (GMIME_IS_MESSAGE (msg)); + g_return_if_fail (func); + + fdata.user_func = func; + fdata.user_data = user_data; + fdata.decrypt = decrypt; + + g_mime_message_foreach + (msg, + (GMimeObjectForeachFunc)foreach_cb, + &fdata); +} diff --git a/lib/mu-msg-file.h b/lib/mu-msg-file.h new file mode 100644 index 0000000..e26c4a7 --- /dev/null +++ b/lib/mu-msg-file.h @@ -0,0 +1,105 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_MSG_FILE_H__ +#define __MU_MSG_FILE_H__ + +struct _MuMsgFile; +typedef struct _MuMsgFile MuMsgFile; + +/** + * create a new message from a file + * + * @param path full path to the message + * @param mdir + * @param err error to receive (when function returns NULL), or NULL + * + * @return a new MuMsg, or NULL in case of error + */ +MuMsgFile *mu_msg_file_new (const char *path, + const char* mdir, GError **err) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +/** + * destroy a MuMsgFile object + * + * @param self object to destroy, or NULL + */ +void mu_msg_file_destroy (MuMsgFile *self); + + + +/** + * get a specific header + * + * @param self a MuMsgFile instance + * @param header a header (e.g. 'X-Mailer' or 'List-Id') + * + * @return the value of the header or NULL if not found; free with g_free + */ +char* mu_msg_file_get_header (MuMsgFile *self, const char *header); + + +/** + * get a string value for this message + * + * @param self a valid MuMsgFile + * @param msfid the message field id to get (must be of type string) + * @param do_free receives TRUE or FALSE, conveying if this string + * should be owned & freed (TRUE) or not by caller. In case 'FALSE', + * this function should be treated as if it were returning a const + * char*, and note that in that case the string is only valid as long + * as the MuMsgFile is alive, ie. before mu_msg_file_destroy + * + * @return a string, or NULL + */ +char* mu_msg_file_get_str_field (MuMsgFile *self, + MuMsgFieldId msfid, + gboolean *do_free) + G_GNUC_WARN_UNUSED_RESULT; + + +/** + * get a string-list value for this message + * + * @param self a valid MuMsgFile + * @param msfid the message field id to get (must be of type string-list) + * + * @return a GSList*, or NULL; free with mu_str_free_list + */ +GSList* mu_msg_file_get_str_list_field (MuMsgFile *self, MuMsgFieldId msfid) + G_GNUC_WARN_UNUSED_RESULT; + + + +/** + * get a numeric value for this message -- the return value should be + * cast into the actual type, e.g., time_t, MuMsgPrio etc. + * + * @param self a valid MuMsgFile + * @param msfid the message field id to get (must be string-based one) + * + * @return the numeric value, or -1 in case of error + */ +gint64 mu_msg_file_get_num_field (MuMsgFile *self, MuMsgFieldId mfid); + + +#endif /*__MU_MSG_FILE_H__*/ diff --git a/lib/mu-msg-iter.cc b/lib/mu-msg-iter.cc new file mode 100644 index 0000000..a401976 --- /dev/null +++ b/lib/mu-msg-iter.cc @@ -0,0 +1,437 @@ +/* -*- mode: c++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +** +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include <stdlib.h> +#include <unistd.h> + +#include <iostream> + +#include <string.h> +#include <errno.h> +#include <algorithm> +#include <xapian.h> + +#include <string> +#include <set> +#include <map> + +#include "utils/mu-util.h" +#include "utils/mu-utils.hh" + +#include "mu-msg.h" +#include "mu-msg-iter.h" +#include "mu-threader.h" + +struct ltstr { + bool operator () (const std::string &s1, + const std::string &s2) const { + return g_strcmp0 (s1.c_str(), s2.c_str()) < 0; + } +}; +typedef std::map <std::string, unsigned, ltstr> msgid_docid_map; + +class ThreadKeyMaker: public Xapian::KeyMaker { +public: + ThreadKeyMaker (GHashTable *threadinfo): _threadinfo(threadinfo) {} + virtual std::string operator()(const Xapian::Document &doc) const { + MuMsgIterThreadInfo *ti; + ti = (MuMsgIterThreadInfo*)g_hash_table_lookup + (_threadinfo, + GUINT_TO_POINTER(doc.get_docid())); + return std::string (ti && ti->threadpath ? ti->threadpath : ""); + } +private: + GHashTable *_threadinfo; +}; + +struct _MuMsgIter { +public: + _MuMsgIter (Xapian::Enquire &enq, size_t maxnum, + MuMsgFieldId sortfield, MuMsgIterFlags flags): + _enq(enq), _thread_hash (0), _msg(0), _flags(flags), + _skip_unreadable(flags & MU_MSG_ITER_FLAG_SKIP_UNREADABLE), + _skip_dups (flags & MU_MSG_ITER_FLAG_SKIP_DUPS) { + + bool descending = (flags & MU_MSG_ITER_FLAG_DESCENDING); + bool threads = (flags & MU_MSG_ITER_FLAG_THREADS); + + // first, we get _all_ matches (G_MAXINT), based the threads + // on that, then return <maxint> of those + _matches = _enq.get_mset (0, G_MAXINT); + + if (_matches.empty()) + return; + + if (threads) { + _matches.fetch(); + _cursor = _matches.begin(); + // NOTE: temporarily turn-off skipping duplicates, since we + // need threadinfo for *all* + _skip_dups = false; + _thread_hash = mu_threader_calculate + (this, _matches.size(), sortfield, descending); + _skip_dups = (flags & MU_MSG_ITER_FLAG_SKIP_DUPS); + ThreadKeyMaker keymaker(_thread_hash); + enq.set_sort_by_key (&keymaker, false); + _matches = _enq.get_mset (0, maxnum); + + } else if (sortfield != MU_MSG_FIELD_ID_NONE) { + enq.set_sort_by_value ((Xapian::valueno)sortfield, + descending); + _matches = _enq.get_mset (0, maxnum); + _cursor = _matches.begin(); + } + _cursor = _matches.begin(); + } + + ~_MuMsgIter () { + if (_thread_hash) + g_hash_table_destroy (_thread_hash); + + set_msg (NULL); + } + + const Xapian::Enquire& enquire() const { return _enq; } + Xapian::MSet& matches() { return _matches; } + + Xapian::MSet::const_iterator cursor () const { return _cursor; } + void set_cursor (Xapian::MSetIterator cur) { _cursor = cur; } + void cursor_next () { ++_cursor; } + + GHashTable *thread_hash () { return _thread_hash; } + + MuMsg *msg() const { return _msg; } + MuMsg *set_msg (MuMsg *msg) { + if (_msg) + mu_msg_unref (_msg); + return _msg = msg; + } + + MuMsgIterFlags flags() const { return _flags; } + + const std::string msgid () const { + const Xapian::Document doc (cursor().get_document()); + return doc.get_value(MU_MSG_FIELD_ID_MSGID); + } + + unsigned docid () const { + const Xapian::Document doc (cursor().get_document()); + return doc.get_docid(); + } + + bool looks_like_dup () const { + try { + const Xapian::Document doc (cursor().get_document()); + // is this message in the preferred map? if + // so, it's not a duplicate, otherwise, it + // isn't + msgid_docid_map::const_iterator pref_iter (_preferred_map.find (msgid())); + if (pref_iter != _preferred_map.end()) { + //std::cerr << "in the set!" << std::endl; + if ((*pref_iter).second == docid()) + return false; // in the set: not a dup! + else + return true; + } + + // otherwise, simply check if we've already seen this message-id, + // and, if so, it's considered a dup + if (_msg_uid_set.find (msgid()) != _msg_uid_set.end()) { + return true; + } else { + _msg_uid_set.insert (msgid()); + return false; + } + } catch (...) { + return true; + } + } + + static void each_preferred (const char *msgid, gpointer docidp, + msgid_docid_map *preferred_map) { + (*preferred_map)[msgid] = GPOINTER_TO_SIZE(docidp); + } + + void set_preferred_map (GHashTable *preferred_hash) { + if (!preferred_hash) + _preferred_map.clear(); + else + g_hash_table_foreach (preferred_hash, + (GHFunc)each_preferred, &_preferred_map); + } + + bool skip_dups () const { return _skip_dups; } + bool skip_unreadable () const { return _skip_unreadable; } + +private: + const Xapian::Enquire _enq; + Xapian::MSet _matches; + Xapian::MSet::const_iterator _cursor; + + GHashTable *_thread_hash; + MuMsg *_msg; + + MuMsgIterFlags _flags; + + mutable std::set <std::string, ltstr> _msg_uid_set; + bool _skip_unreadable; + + // the 'preferred map' (msgid->docid) is used when checking + // for duplicates; if a message is in the preferred map, it + // will not be excluded (but other messages with the same + // msgid will) + msgid_docid_map _preferred_map; + bool _skip_dups; +}; + +static gboolean +is_msg_file_readable (MuMsgIter *iter) +{ + gboolean readable; + std::string path + (iter->cursor().get_document().get_value(MU_MSG_FIELD_ID_PATH)); + + if (path.empty()) + return FALSE; + + readable = (access (path.c_str(), R_OK) == 0) ? TRUE : FALSE; + return readable; +} + + +MuMsgIter* +mu_msg_iter_new (XapianEnquire *enq, size_t maxnum, + MuMsgFieldId sortfield, MuMsgIterFlags flags, + GError **err) +{ + g_return_val_if_fail (enq, NULL); + /* sortfield should be set to .._NONE when we're not threading */ + g_return_val_if_fail (mu_msg_field_id_is_valid (sortfield) || + sortfield == MU_MSG_FIELD_ID_NONE, + FALSE); + try { + MuMsgIter *iter (new MuMsgIter ((Xapian::Enquire&)*enq, + maxnum, + sortfield, + flags)); + // note: we check if it's a dup even for the first message, + // since we need its uid in the set for checking later messages + if ((iter->skip_unreadable() && !is_msg_file_readable (iter)) || + (iter->skip_dups() && iter->looks_like_dup ())) + mu_msg_iter_next (iter); /* skip! */ + + return iter; + + } catch (const Xapian::DatabaseModifiedError &dbmex) { + mu_util_g_set_error (err, MU_ERROR_XAPIAN_MODIFIED, + "database was modified; please reopen"); + return 0; + + } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN (err, MU_ERROR_XAPIAN, 0); +} + +void +mu_msg_iter_destroy (MuMsgIter *iter) +{ + try { delete iter; } MU_XAPIAN_CATCH_BLOCK; +} + +void +mu_msg_iter_set_preferred (MuMsgIter *iter, GHashTable *preferred_hash) +{ + g_return_if_fail (iter); + iter->set_preferred_map (preferred_hash); +} + +MuMsg* +mu_msg_iter_get_msg_floating (MuMsgIter *iter) +{ + g_return_val_if_fail (iter, NULL); + g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL); + + try { + MuMsg *msg; + GError *err; + Xapian::Document *docp; + + docp = new Xapian::Document(iter->cursor().get_document()); + + err = NULL; + msg = iter->set_msg (mu_msg_new_from_doc((XapianDocument*)docp, + &err)); + if (!msg) + MU_HANDLE_G_ERROR(err); + + return msg; + + } MU_XAPIAN_CATCH_BLOCK_RETURN (NULL); +} + +gboolean +mu_msg_iter_reset (MuMsgIter *iter) +{ + g_return_val_if_fail (iter, FALSE); + + iter->set_msg (NULL); + + try { + iter->set_cursor(iter->matches().begin()); + + } MU_XAPIAN_CATCH_BLOCK_RETURN (FALSE); + + return TRUE; +} + +gboolean +mu_msg_iter_next (MuMsgIter *iter) +{ + g_return_val_if_fail (iter, FALSE); + + iter->set_msg (NULL); + + if (mu_msg_iter_is_done(iter)) + return FALSE; + + try { + iter->cursor_next(); + + if (iter->cursor() == iter->matches().end()) + return FALSE; + + if ((iter->skip_unreadable() && !is_msg_file_readable (iter)) || + (iter->skip_dups() && iter->looks_like_dup ())) + return mu_msg_iter_next (iter); /* skip! */ + + return TRUE; + + } MU_XAPIAN_CATCH_BLOCK_RETURN(FALSE); +} + + +gboolean +mu_msg_iter_is_done (MuMsgIter *iter) +{ + g_return_val_if_fail (iter, TRUE); + + try { + return iter->cursor() == iter->matches().end() ? TRUE : FALSE; + + } MU_XAPIAN_CATCH_BLOCK_RETURN (TRUE); +} + +gboolean +mu_msg_iter_is_first (MuMsgIter *iter) +{ + g_return_val_if_fail (iter, FALSE); + + return iter->cursor() == iter->matches().begin(); +} + +gboolean +mu_msg_iter_is_last (MuMsgIter *iter) +{ + g_return_val_if_fail (iter, FALSE); + + if (mu_msg_iter_is_done (iter)) + return FALSE; + + return iter->cursor() + 1 == iter->matches().end(); +} + +/* hmmm.... is it impossible to get a 0 docid, or just very improbable? */ +unsigned +mu_msg_iter_get_docid (MuMsgIter *iter) +{ + g_return_val_if_fail (iter, (unsigned int)-1); + g_return_val_if_fail (!mu_msg_iter_is_done(iter), + (unsigned int)-1); + try { + return iter->docid(); + + } MU_XAPIAN_CATCH_BLOCK_RETURN ((unsigned int)-1); +} + + +char* +mu_msg_iter_get_msgid (MuMsgIter *iter) +{ + g_return_val_if_fail (iter, NULL); + g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL); + + try { + return g_strdup (iter->msgid().c_str()); + + } MU_XAPIAN_CATCH_BLOCK_RETURN (NULL); +} + +char** +mu_msg_iter_get_refs (MuMsgIter *iter) +{ + g_return_val_if_fail (iter, NULL); + g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL); + + try { + std::string refs ( + iter->cursor().get_document().get_value(MU_MSG_FIELD_ID_REFS)); + if (refs.empty()) + return NULL; + return g_strsplit (refs.c_str(),",", -1); + + } MU_XAPIAN_CATCH_BLOCK_RETURN (NULL); +} + +char* +mu_msg_iter_get_thread_id (MuMsgIter *iter) +{ + g_return_val_if_fail (iter, NULL); + g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL); + + try { + const std::string thread_id ( + iter->cursor().get_document().get_value(MU_MSG_FIELD_ID_THREAD_ID).c_str()); + return thread_id.empty() ? NULL : g_strdup (thread_id.c_str()); + + } MU_XAPIAN_CATCH_BLOCK_RETURN (NULL); +} + +const MuMsgIterThreadInfo* +mu_msg_iter_get_thread_info (MuMsgIter *iter) +{ + g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL); + + /* maybe we don't have thread info */ + if (!iter->thread_hash()) + return NULL; + + try { + const MuMsgIterThreadInfo *ti; + unsigned int docid; + + docid = mu_msg_iter_get_docid (iter); + ti = (const MuMsgIterThreadInfo*)g_hash_table_lookup + (iter->thread_hash(), GUINT_TO_POINTER(docid)); + + if (!ti) + g_warning ("no ti for %u\n", docid); + + return ti; + + } MU_XAPIAN_CATCH_BLOCK_RETURN (NULL); +} diff --git a/lib/mu-msg-iter.h b/lib/mu-msg-iter.h new file mode 100644 index 0000000..bce6a50 --- /dev/null +++ b/lib/mu-msg-iter.h @@ -0,0 +1,246 @@ +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_MSG_ITER_H__ +#define __MU_MSG_ITER_H__ + +#include <glib.h> +#include <mu-msg.h> + +G_BEGIN_DECLS + + +/** + * MuMsgIter is a structure to iterate over the results of a + * query. You can iterate only in one-direction, and you can do it + * only once. + * + */ + +struct _MuMsgIter; +typedef struct _MuMsgIter MuMsgIter; + + +enum _MuMsgIterFlags { + MU_MSG_ITER_FLAG_NONE = 0, + /* sort Z->A (only for threads) */ + MU_MSG_ITER_FLAG_DESCENDING = 1 << 0, + /* ignore results for which there is no existing + * readable message-file? */ + MU_MSG_ITER_FLAG_SKIP_UNREADABLE = 1 << 1, + /* ignore duplicate messages? */ + MU_MSG_ITER_FLAG_SKIP_DUPS = 1 << 2, + /* calculate threads? */ + MU_MSG_ITER_FLAG_THREADS = 1 << 3 +}; +typedef unsigned MuMsgIterFlags; + +/** + * create a new MuMsgIter -- basically, an iterator over the search + * results + * + * @param enq a Xapian::Enquire* cast to XapianEnquire* (because this + * is C, not C++),providing access to search results + * @param maxnum the maximum number of results + * @param sortfield field to sort by + * @param flags flags for this iterator (see MsgIterFlags) + + * @param err receives error information. if the error is + * MU_ERROR_XAPIAN_MODIFIED, the database should be reloaded. + * + * @return a new MuMsgIter, or NULL in case of error + */ +MuMsgIter *mu_msg_iter_new (XapianEnquire *enq, + size_t maxnum, + MuMsgFieldId sortfield, + MuMsgIterFlags flags, + GError **err) G_GNUC_WARN_UNUSED_RESULT; + +/** + * get the next message (which you got from + * e.g. mu_query_run) + * + * @param iter a valid MuMsgIter iterator + * + * @return TRUE if it succeeded, FALSE otherwise (e.g., because there + * are no more messages in the query result) + */ +gboolean mu_msg_iter_next (MuMsgIter *iter); + +/** + * Does this iterator point to the first item? + * + * @param iter a valid MuMsgIter iterator + * + * @return TRUE or FALSE + */ +gboolean mu_msg_iter_is_first (MuMsgIter *iter); + +/** + * Does this iterator point to the last item? + * + * @param iter a valid MuMsgIter iterator + * + * @return TRUE or FALSE + */ +gboolean mu_msg_iter_is_last (MuMsgIter *iter); + + +/** + * reset the iterator to the beginning + * + * @param iter a valid MuMsgIter iterator + * + * @return TRUE if it succeeded, FALSE otherwise + */ +gboolean mu_msg_iter_reset (MuMsgIter *iter); + +/** + * does this iterator point past the end of the list? + * + * @param iter a valid MuMsgIter iterator + * + * @return TRUE if the iter points past end of the list, FALSE + * otherwise + */ +gboolean mu_msg_iter_is_done (MuMsgIter *iter); + + +/** + * destroy the sequence of messages; ie. /all/ of them + * + * @param msg a valid MuMsgIter message or NULL + */ +void mu_msg_iter_destroy (MuMsgIter *iter); + + +/** + * get the corresponding MuMsg for this iter; this instance is owned + * by MuMsgIter, and becomes invalid after either mu_msg_iter_destroy + * or mu_msg_iter_next. _do not_ unref it; it's a floating reference. + * + * @param iter a valid MuMsgIter instance* + * + * @return a MuMsg instance, or NULL in case of error + */ +MuMsg* mu_msg_iter_get_msg_floating (MuMsgIter *iter) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +/** + * Provide a preferred_hash, which is a hashtable msgid->docid to + * indicate the messages which should /not/ be seen as duplicates. + * + * @param iter a valid MuMsgIter iterator + * @param preferred_hash a hashtable msgid->docid of message /not/ to + * mark as duplicates, or NULL + */ +void mu_msg_iter_set_preferred (MuMsgIter *iter, GHashTable *preferred_hash); + +/** + * get the document id for the current message + * + * @param iter a valid MuMsgIter iterator + * + * @return the docid or (unsigned int)-1 in case of error + */ +guint mu_msg_iter_get_docid (MuMsgIter *iter); + + +/** + * calculate the message threads + * + * @param iter a valid MuMsgIter iterator + * + * @return TRUE if it worked, FALSE otherwise. + */ +gboolean mu_msg_iter_calculate_threads (MuMsgIter *iter); + + +enum _MuMsgIterThreadProp { + MU_MSG_ITER_THREAD_PROP_NONE = 0 << 0, + + MU_MSG_ITER_THREAD_PROP_ROOT = 1 << 0, + MU_MSG_ITER_THREAD_PROP_FIRST_CHILD = 1 << 1, + MU_MSG_ITER_THREAD_PROP_LAST_CHILD = 1 << 2, + MU_MSG_ITER_THREAD_PROP_EMPTY_PARENT = 1 << 3, + MU_MSG_ITER_THREAD_PROP_DUP = 1 << 4, + MU_MSG_ITER_THREAD_PROP_HAS_CHILD = 1 << 5 +}; +typedef guint8 MuMsgIterThreadProp; + +struct _MuMsgIterThreadInfo { + gchar *threadpath; /* a string describing the thread-path in + * such a way that we can sort by this + * string to get the right order. */ + guint level; /* thread-depth -- [0...] */ + MuMsgIterThreadProp prop; +}; +typedef struct _MuMsgIterThreadInfo MuMsgIterThreadInfo; + +/** + * get a the MuMsgThreaderInfo struct for this message; this only + * works when you created the mu-msg-iter with threading enabled + * (otherwise, return NULL) + * + * @param iter a valid MuMsgIter iterator + * + * @return an info struct + */ +const MuMsgIterThreadInfo* mu_msg_iter_get_thread_info (MuMsgIter *iter); + +/** + * get the message-id for this message + * + * @param iter a valid MuMsgIter iterator + * + * @return the message-id; free with g_free(). + */ +char* mu_msg_iter_get_msgid (MuMsgIter *iter) + G_GNUC_WARN_UNUSED_RESULT; + +/** + * get the list of references for this messages as a NULL-terminated + * string array + * + * @param iter a valid MuMsgIter iterator + * + * @return a NULL-terminated string array. free with g_strfreev when + * it's no longer needed. + */ +char** mu_msg_iter_get_refs (MuMsgIter *iter) + G_GNUC_WARN_UNUSED_RESULT; + + +/** + * get the thread-id for this message + * + * @param iter a valid MuMsgIter iterator + * + * @return the thread-id; free with g_free(). + */ +char* mu_msg_iter_get_thread_id (MuMsgIter *iter) + G_GNUC_WARN_UNUSED_RESULT; + + +/* FIXME */ +const char* mu_msg_iter_get_path (MuMsgIter *iter); + +G_END_DECLS + +#endif /*__MU_MSG_ITER_H__*/ diff --git a/lib/mu-msg-json.c b/lib/mu-msg-json.c new file mode 100644 index 0000000..52b20f9 --- /dev/null +++ b/lib/mu-msg-json.c @@ -0,0 +1,524 @@ +/* +** Copyright (C) 2018 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include <string.h> +#include <ctype.h> + +#include <json-glib/json-glib.h> + +#include "mu-msg.h" +#include "mu-msg-iter.h" +#include "mu-msg-part.h" +#include "mu-maildir.h" + +static void +add_list_member (JsonBuilder *bob, const char* elm, const GSList *lst) +{ + const GSList *cur; + + if (!lst) + return; /* empty list, don't include */ + + bob = json_builder_set_member_name (bob, elm); + bob = json_builder_begin_array (bob); + + for (cur = lst; cur; cur = g_slist_next(cur)) + bob = json_builder_add_string_value (bob, (const char*)cur->data); + + bob = json_builder_end_array (bob); +} + +static void +add_string_member (JsonBuilder *bob, const char* elm, const char *str) +{ + if (!str) + return; /* don't include */ + + bob = json_builder_set_member_name (bob, elm); + bob = json_builder_add_string_value (bob, str); +} + +static void +add_int_member (JsonBuilder *bob, const char* elm, gint64 num) +{ + bob = json_builder_set_member_name (bob, elm); + bob = json_builder_add_int_value (bob, num); +} + +static void +add_bool_member (JsonBuilder *bob, const char* elm, gboolean b) +{ + bob = json_builder_set_member_name (bob, elm); + bob = json_builder_add_boolean_value (bob, b); +} + + +static void +consume_array_member (JsonBuilder *bob, const char* elm, JsonArray *arr) +{ + JsonNode *node; + + if (!arr) + return; /* nothing to do */ + + node = json_node_new (JSON_NODE_ARRAY); + json_node_init_array (node, arr); + json_array_unref (arr); + + bob = json_builder_set_member_name (bob, elm); + bob = json_builder_add_value (bob, node); /* consumes */ +} + + + +typedef struct { + JsonArray *from, *to, *cc, *bcc, *reply_to; +} ContactData; + +static void +add_contact (JsonArray **arr, MuMsgContact *c) +{ + JsonObject *cell; + + if (!*arr) + *arr = json_array_new (); + + cell = json_object_new (); + if (c->name) + json_object_set_string_member (cell, "name", c->name); + if (c->email) + json_object_set_string_member (cell, "email", c->email); + + json_array_add_object_element (*arr, cell); /* consumes */ +} + +static gboolean +each_contact (MuMsgContact *c, ContactData *cdata) +{ + switch (mu_msg_contact_type (c)) { + + case MU_MSG_CONTACT_TYPE_FROM: + add_contact(&cdata->from, c); + break; + case MU_MSG_CONTACT_TYPE_TO: + add_contact(&cdata->to ,c); + break; + case MU_MSG_CONTACT_TYPE_CC: + add_contact(&cdata->cc, c); + break; + case MU_MSG_CONTACT_TYPE_BCC: + add_contact(&cdata->bcc, c); + break; + case MU_MSG_CONTACT_TYPE_REPLY_TO: + add_contact(&cdata->reply_to, c); + break; + default: g_return_val_if_reached (FALSE); + } + + return TRUE; +} + + +static void +maybe_append_list_post_as_reply_to (JsonBuilder *bob, MuMsg *msg) +{ + /* some mailing lists do not set the reply-to; see pull #1278. So for + * those cases, check the List-Post address and use that instead */ + + GMatchInfo *minfo; + GRegex *rx; + const char* list_post; + + list_post = mu_msg_get_header (msg, "List-Post"); + if (!list_post) + return; + + rx = g_regex_new ("^(<?mailto:)?([a-z0-9%+@.-]+)>?", G_REGEX_CASELESS, 0, NULL); + g_return_if_fail(rx); + + if (g_regex_match (rx, list_post, 0, &minfo)) { + char *addr; + addr = g_match_info_fetch (minfo, 2); + + bob = json_builder_set_member_name (bob, "reply-to"); + bob = json_builder_begin_array(bob); + bob = json_builder_begin_object(bob); + add_string_member(bob, "email", addr); + g_free (addr); + + bob = json_builder_end_object(bob); + bob = json_builder_end_array(bob); + } + + g_match_info_free (minfo); + g_regex_unref (rx); +} + + +static void +add_contacts (JsonBuilder *bob, MuMsg *msg) +{ + ContactData cdata; + memset (&cdata, 0, sizeof(cdata)); + + mu_msg_contact_foreach (msg, + (MuMsgContactForeachFunc)each_contact, + &cdata); + + consume_array_member (bob, "to" , cdata.to); + consume_array_member (bob, "from" , cdata.from); + consume_array_member (bob, "cc" , cdata.cc); + consume_array_member (bob, "bcc" , cdata.bcc); + consume_array_member (bob, "reply-to", cdata.reply_to); + + if (!cdata.reply_to) + maybe_append_list_post_as_reply_to (bob, msg); +} + +struct _FlagData { + JsonBuilder *bob; + MuFlags msgflags; +}; +typedef struct _FlagData FlagData; + +static void +each_flag (MuFlags flag, FlagData *fdata) +{ + if (!(flag & fdata->msgflags)) + return; + + json_builder_add_string_value (fdata->bob, + mu_flag_name(flag)); +} + +static void +add_flags (JsonBuilder *bob, MuMsg *msg) +{ + FlagData fdata; + + fdata.msgflags = mu_msg_get_flags (msg); + fdata.bob = bob; + + bob = json_builder_set_member_name (bob, "flags"); + + bob = json_builder_begin_array (bob); + mu_flags_foreach ((MuFlagsForeachFunc)each_flag, &fdata); + bob = json_builder_end_array (bob); + +} + +static char* +get_temp_file (MuMsg *msg, MuMsgOptions opts, unsigned index) +{ + char *path; + GError *err; + + err = NULL; + path = mu_msg_part_get_cache_path (msg, opts, index, &err); + if (!path) + goto errexit; + + if (!mu_msg_part_save (msg, opts, path, index, &err)) + goto errexit; + + return path; + +errexit: + g_warning ("failed to save mime part: %s", + err->message ? err->message : "something went wrong"); + g_clear_error (&err); + g_free (path); + return NULL; +} + + +static gchar* +get_temp_file_maybe (MuMsg *msg, MuMsgPart *part, MuMsgOptions opts) +{ + opts |= MU_MSG_OPTION_USE_EXISTING; + + if (!(opts & MU_MSG_OPTION_EXTRACT_IMAGES) || + g_ascii_strcasecmp (part->type, "image") != 0) + return NULL; + + return get_temp_file (msg, opts, part->index); +} + + +struct _PartInfo { + JsonBuilder *bob; + MuMsgOptions opts; +}; +typedef struct _PartInfo PartInfo; + + +static void +add_part_crypto (JsonBuilder *bob, MuMsgPart *mpart, PartInfo *pinfo) +{ + const char *verdict; + MuMsgPartSigStatusReport *report; + + + add_string_member (bob, "decryption", + pinfo->opts & MU_MSG_PART_TYPE_DECRYPTED ? "ok" : + pinfo->opts & MU_MSG_PART_TYPE_ENCRYPTED ? "failed" : + NULL); + + report = mpart->sig_status_report; + if (!report) + return; + + switch (report->verdict) { + case MU_MSG_PART_SIG_STATUS_GOOD: verdict = "verified"; break; + case MU_MSG_PART_SIG_STATUS_BAD: verdict = "bad"; break; + case MU_MSG_PART_SIG_STATUS_ERROR: verdict = "unverified"; break; + default: verdict = NULL; + } + + add_string_member (bob, "signature", verdict); + add_string_member (bob, "signers", report->signers); +} + +static void +add_part_type (JsonBuilder *bob, MuMsgPartType ptype) +{ + unsigned u; + struct PartTypes { + MuMsgPartType ptype; + const char* name; + } ptypes[] = { + { MU_MSG_PART_TYPE_LEAF, "leaf" }, + { MU_MSG_PART_TYPE_MESSAGE, "message" }, + { MU_MSG_PART_TYPE_INLINE, "inline" }, + { MU_MSG_PART_TYPE_ATTACHMENT, "attachment" }, + { MU_MSG_PART_TYPE_SIGNED, "signed" }, + { MU_MSG_PART_TYPE_ENCRYPTED, "encrypted" } + }; + + bob = json_builder_set_member_name (bob, "type"); + bob = json_builder_begin_array(bob); + + for (u = 0; u!= G_N_ELEMENTS(ptypes); ++u) + if (ptype & ptypes[u].ptype) + json_builder_add_string_value (bob, ptypes[u].name); + + bob = json_builder_end_array(bob); +} + + +static void +each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo) +{ + char *name, *tmpfile; + + pinfo->bob = json_builder_begin_object(pinfo->bob); + + name = mu_msg_part_get_filename (part, TRUE); + tmpfile = get_temp_file_maybe (msg, part, pinfo->opts); + + add_int_member (pinfo->bob, "index", part->index); + add_string_member (pinfo->bob, "name", name); + + if (part->type && part->subtype) { + char *mime_type = + g_strdup_printf ("%s/%s", part->type, part->subtype); + add_string_member (pinfo->bob, "mime-type", mime_type); + g_free(mime_type); + } + + add_string_member (pinfo->bob, "temp", tmpfile); + add_part_type (pinfo->bob, part->part_type); + + if (mu_msg_part_maybe_attachment (part)) + add_bool_member (pinfo->bob, "attachment", TRUE); + + add_string_member (pinfo->bob, "cid", mu_msg_part_get_content_id(part)); + add_int_member (pinfo->bob, "size", part->size); + + add_part_crypto (pinfo->bob, part, pinfo); + + g_free (name); + g_free (tmpfile); + + pinfo->bob = json_builder_end_object(pinfo->bob); +} + + +static void +add_parts (JsonBuilder *bob, MuMsg *msg, MuMsgOptions opts) +{ + PartInfo pinfo; + + pinfo.opts = opts; + bob = json_builder_set_member_name (bob, "parts"); + bob = json_builder_begin_array (bob); + + mu_msg_part_foreach (msg, opts, (MuMsgPartForeachFunc)each_part, &pinfo); + + bob = json_builder_end_array (bob); +} + +static void +add_thread_info (JsonBuilder *bob, const MuMsgIterThreadInfo *ti) +{ + bob = json_builder_set_member_name (bob, "thread"); + bob = json_builder_begin_object(bob); + + add_string_member (bob, "path", ti->threadpath); + add_int_member (bob, "level", ti->level); + + bob = json_builder_set_member_name (bob, "flags"); + bob = json_builder_begin_array (bob); + + if (ti->prop & MU_MSG_ITER_THREAD_PROP_FIRST_CHILD) + bob = json_builder_add_string_value (bob, "first-child"); + if (ti->prop & MU_MSG_ITER_THREAD_PROP_LAST_CHILD) + bob = json_builder_add_string_value (bob, "last-child"); + if (ti->prop & MU_MSG_ITER_THREAD_PROP_EMPTY_PARENT) + bob = json_builder_add_string_value (bob, "empty-parent"); + if (ti->prop & MU_MSG_ITER_THREAD_PROP_DUP) + bob = json_builder_add_string_value (bob, "duplicate"); + if (ti->prop & MU_MSG_ITER_THREAD_PROP_HAS_CHILD) + bob = json_builder_add_string_value (bob, "has-child"); + + bob = json_builder_end_array (bob); + bob = json_builder_end_object(bob); +} + +static void +add_body_txt_params (JsonBuilder *bob, MuMsg *msg, MuMsgOptions opts) +{ + const GSList *params; + + params = mu_msg_get_body_text_content_type_parameters (msg, opts); + if (!params) + return; + + bob = json_builder_set_member_name (bob, "body-txt-params"); + bob = json_builder_begin_array (bob); + + while (params) { + const char *key, *val; + + key = (const char *)params->data; + params = g_slist_next(params); + if (!params) + break; + val = (const char *)params->data; + + if (key && val) { + bob = json_builder_begin_object(bob); + add_string_member(bob, key, val); + bob = json_builder_end_object(bob); + } + + params = g_slist_next(params); + } + + bob = json_builder_end_array(bob); +} + +static void /* ie., parts that require opening the message file */ +add_file_parts (JsonBuilder *bob, MuMsg *msg, MuMsgOptions opts) +{ + const char *str; + GError *err; + + err = NULL; + + if (!mu_msg_load_msg_file (msg, &err)) { + g_warning ("failed to load message file: %s", + err ? err->message : "some error occurred"); + g_clear_error (&err); + return; + } + + add_parts (bob, msg, opts); + add_contacts (bob, msg); + + /* add the user-agent / x-mailer */ + str = mu_msg_get_header (msg, "User-Agent"); + if (!str) + str = mu_msg_get_header (msg, "X-Mailer"); + add_string_member (bob, "user-agent", str); + add_body_txt_params (bob, msg, opts); + add_string_member (bob, "body-txt", mu_msg_get_body_text(msg, opts)); + add_string_member (bob, "body-html", mu_msg_get_body_html(msg, opts)); +} + +struct _JsonNode* +mu_msg_to_json (MuMsg *msg, unsigned docid, const MuMsgIterThreadInfo *ti, + MuMsgOptions opts) +{ + JsonNode *node; + JsonBuilder *bob; + + time_t t; + size_t s; + + g_return_val_if_fail (msg, NULL); + g_return_val_if_fail (!((opts & MU_MSG_OPTION_HEADERS_ONLY) && + (opts & MU_MSG_OPTION_EXTRACT_IMAGES)),NULL); + bob = json_builder_new (); + bob = json_builder_begin_object (bob); + + if (ti) + add_thread_info (bob, ti); + + add_string_member (bob, "subject", mu_msg_get_subject (msg)); + + /* in the no-headers-only case (see below) we get a more complete list + * of contacts, so no need to get them here if that's the case */ + if (opts & MU_MSG_OPTION_HEADERS_ONLY) + add_contacts (bob, msg); + + t = mu_msg_get_date (msg); + if (t != (time_t)-1) + add_int_member (bob, "date", t); + + s = mu_msg_get_size (msg); + if (s != (size_t)-1) + add_int_member (bob, "size", s); + + add_string_member (bob, "message-id", mu_msg_get_msgid (msg)); + add_string_member (bob, "mailing-list", mu_msg_get_mailing_list (msg)); + add_string_member (bob, "path", mu_msg_get_path (msg)); + add_string_member (bob, "maildir", mu_msg_get_maildir (msg)); + add_string_member (bob, "priority", mu_msg_prio_name(mu_msg_get_prio(msg))); + + add_flags (bob, msg); + + add_list_member (bob, "tags", mu_msg_get_tags(msg)); + add_list_member (bob, "references", mu_msg_get_references (msg)); + add_string_member (bob, "in-reply-to", + mu_msg_get_header (msg, "In-Reply-To")); + + /* headers are retrieved from the database, views from the + * message file file attr things can only be gotten from the + * file (ie., mu view), not from the database (mu find). */ + if (!(opts & MU_MSG_OPTION_HEADERS_ONLY)) + add_file_parts (bob, msg, opts); + + bob = json_builder_end_object (bob); + node = json_builder_get_root (bob); + + g_clear_object (&bob); + + return node; +} diff --git a/lib/mu-msg-part.c b/lib/mu-msg-part.c new file mode 100644 index 0000000..099274d --- /dev/null +++ b/lib/mu-msg-part.c @@ -0,0 +1,1009 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ +/* +** Copyright (C) 2008-2014 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include <string.h> +#include <unistd.h> + +#include "utils/mu-util.h" +#include "utils/mu-str.h" +#include "mu-msg-priv.h" +#include "mu-msg-part.h" + +struct _DoData { + GMimeObject *mime_obj; + unsigned index; +}; +typedef struct _DoData DoData; + +static void +do_it_with_index (MuMsg *msg, MuMsgPart *part, DoData *ddata) +{ + if (ddata->mime_obj) + return; + + if (part->index == ddata->index) { + /* Add a reference to this object, this way if it is + * encrypted it will not be garbage collected before + * we are done with it. */ + g_object_ref (part->data); + ddata->mime_obj = (GMimeObject*)part->data; + } +} + +static GMimeObject* +get_mime_object_at_index (MuMsg *msg, MuMsgOptions opts, unsigned index) +{ + DoData ddata; + + ddata.mime_obj = NULL; + ddata.index = index; + + /* wipe out some irrelevant options */ + opts &= ~MU_MSG_OPTION_VERIFY; + opts &= ~MU_MSG_OPTION_EXTRACT_IMAGES; + + mu_msg_part_foreach (msg, opts, + (MuMsgPartForeachFunc)do_it_with_index, + &ddata); + + return ddata.mime_obj; +} + + +typedef gboolean (*MuMsgPartMatchFunc) (MuMsgPart *, gpointer); +struct _MatchData { + MuMsgPartMatchFunc match_func; + gpointer user_data; + int index; +}; +typedef struct _MatchData MatchData; + +static void +check_match (MuMsg *msg, MuMsgPart *part, MatchData *mdata) +{ + if (mdata->index != -1) + return; + + if (mdata->match_func (part, mdata->user_data)) + mdata->index = part->index; +} + +static int +get_matching_part_index (MuMsg *msg, MuMsgOptions opts, + MuMsgPartMatchFunc func, gpointer user_data) +{ + MatchData mdata; + + mdata.match_func = func; + mdata.user_data = user_data; + mdata.index = -1; + + mu_msg_part_foreach (msg, opts, + (MuMsgPartForeachFunc)check_match, + &mdata); + return mdata.index; +} + + +static void +accumulate_text_message (MuMsg *msg, MuMsgPart *part, GString **gstrp) +{ + const gchar *str; + char *adrs; + GMimeMessage *mimemsg; + InternetAddressList *addresses; + + /* put sender, recipients and subject in the string, so they + * can be indexed as well */ + mimemsg = GMIME_MESSAGE (part->data); + addresses = g_mime_message_get_addresses (mimemsg, GMIME_ADDRESS_TYPE_FROM); + adrs = internet_address_list_to_string (addresses, NULL, FALSE); + + g_string_append_printf + (*gstrp, "%s%s", adrs ? adrs : "", adrs ? "\n" : ""); + g_free (adrs); + + str = g_mime_message_get_subject (mimemsg); + g_string_append_printf + (*gstrp, "%s%s", str ? str : "", str ? "\n" : ""); + + addresses = g_mime_message_get_all_recipients (mimemsg); + adrs = internet_address_list_to_string (addresses, NULL, FALSE); + g_object_unref (addresses); + + g_string_append_printf + (*gstrp, "%s%s", adrs ? adrs : "", adrs ? "\n" : ""); + g_free (adrs); +} + +static void +accumulate_text_part (MuMsg *msg, MuMsgPart *part, GString **gstrp) +{ + GMimeContentType *ctype; + gboolean err; + char *txt; + + ctype = g_mime_object_get_content_type ((GMimeObject*)part->data); + if (!g_mime_content_type_is_type (ctype, "text", "plain")) + return; /* not plain text */ + + txt = mu_msg_mime_part_to_string((GMimePart*)part->data, &err); + if (txt) + g_string_append (*gstrp, txt); + + g_free (txt); +} + +static void +accumulate_text (MuMsg *msg, MuMsgPart *part, GString **gstrp) +{ + if (GMIME_IS_MESSAGE(part->data)) + accumulate_text_message (msg, part, gstrp); + else if (GMIME_IS_PART (part->data)) + accumulate_text_part (msg, part, gstrp); +} + +/* declaration, so we can use it earlier */ +static gboolean +handle_mime_object (MuMsg *msg, GMimeObject *mobj, GMimeObject *parent, + MuMsgOptions opts, unsigned *index, gboolean decrypted, + MuMsgPartForeachFunc func, gpointer user_data); + +static char* +get_text_from_mime_msg (MuMsg *msg, GMimeMessage *mmsg, MuMsgOptions opts) +{ + GString *gstr; + unsigned index; + + index = 1; + gstr = g_string_sized_new (4096); + handle_mime_object (msg, + mmsg->mime_part, + (GMimeObject *) mmsg, + opts, + &index, + FALSE, + (MuMsgPartForeachFunc)accumulate_text, + &gstr); + + return g_string_free (gstr, FALSE); +} + + +char* +mu_msg_part_get_text (MuMsg *msg, MuMsgPart *self, MuMsgOptions opts) +{ + GMimeObject *mobj; + GMimeMessage *mime_msg; + gboolean err; + + g_return_val_if_fail (msg, NULL); + g_return_val_if_fail (self && GMIME_IS_OBJECT(self->data), + NULL); + + mobj = (GMimeObject*)self->data; + + err = FALSE; + if (GMIME_IS_PART (mobj)) { + if (self->part_type & MU_MSG_PART_TYPE_TEXT_PLAIN) + return mu_msg_mime_part_to_string ((GMimePart*)mobj, + &err); + else + return NULL; /* non-text MimePart */ + } + + mime_msg = NULL; + + if (GMIME_IS_MESSAGE_PART (mobj)) + mime_msg = g_mime_message_part_get_message + ((GMimeMessagePart*)mobj); + else if (GMIME_IS_MESSAGE (mobj)) + mime_msg = (GMimeMessage*)mobj; + + /* apparently, g_mime_message_part_get_message may still + * return NULL */ + if (mime_msg) + return get_text_from_mime_msg (msg, mime_msg, opts); + return NULL; +} + + +/* note: this will return -1 in case of error or if the size is + * unknown */ +static ssize_t +get_part_size (GMimePart *part) +{ + GMimeDataWrapper *wrapper; + GMimeStream *stream; + + wrapper = g_mime_part_get_content (part); + if (!GMIME_IS_DATA_WRAPPER(wrapper)) + return -1; + + stream = g_mime_data_wrapper_get_stream (wrapper); + if (!stream) + return -1; /* no stream -> size is 0 */ + else + return g_mime_stream_length (stream); + + /* NOTE: stream/wrapper are owned by gmime, no unreffing */ +} + + +static char* +cleanup_filename (char *fname) +{ + GString *gstr; + gchar *cur; + gunichar uc; + + gstr = g_string_sized_new (strlen (fname)); + + /* replace control characters, slashes, and colons by '-' */ + for (cur = fname; cur && *cur; cur = g_utf8_next_char (cur)) { + uc = g_utf8_get_char (cur); + if (g_unichar_iscntrl (uc) || uc == '/' || uc == ':') + g_string_append_unichar (gstr, '-'); + else + g_string_append_unichar (gstr, uc); + } + + g_free (fname); + return g_string_free (gstr, FALSE); +} + + +/* + * when a part doesn't have a filename, it can be useful to 'guess' one based on + * its mime-type, which allows other tools to handle them correctly, e.g. from + * mu4e. + * + * For now, we only handle calendar invitations in that way, but others may + * follow. + */ +static char* +guess_file_name (GMimeObject *mobj, unsigned index) +{ + GMimeContentType *ctype; + + ctype = g_mime_object_get_content_type (mobj); + + /* special case for calendars; map to '.vcs' */ + if (g_mime_content_type_is_type (ctype, "text", "calendar")) + return g_strdup_printf ("vcal-%u.vcs", index); + + /* fallback */ + return g_strdup_printf ("%u.msgpart", index); +} + + +static char* +mime_part_get_filename (GMimeObject *mobj, unsigned index, + gboolean construct_if_needed) +{ + gchar *fname; + + fname = NULL; + + if (GMIME_IS_PART (mobj)) { + /* the easy case: the part has a filename */ + fname = (gchar*)g_mime_part_get_filename (GMIME_PART(mobj)); + if (fname) /* don't include directory components */ + fname = g_path_get_basename (fname); + } + + if (!fname && !construct_if_needed) + return NULL; + + if (GMIME_IS_MESSAGE_PART(mobj)) { + GMimeMessage *msg; + const char *subj; + msg = g_mime_message_part_get_message + (GMIME_MESSAGE_PART(mobj)); + subj = g_mime_message_get_subject (msg); + fname = g_strdup_printf ("%s.eml", subj ? subj : "message"); + } + + if (!fname) + fname = guess_file_name (mobj, index); + + /* replace control characters, slashes, and colons */ + fname = cleanup_filename (fname); + + return fname; +} + + +char* +mu_msg_part_get_filename (MuMsgPart *mpart, gboolean construct_if_needed) +{ + g_return_val_if_fail (mpart, NULL); + g_return_val_if_fail (GMIME_IS_OBJECT(mpart->data), NULL); + + return mime_part_get_filename ((GMimeObject*)mpart->data, + mpart->index, construct_if_needed); +} + +const gchar* +mu_msg_part_get_content_id (MuMsgPart *mpart) +{ + g_return_val_if_fail (mpart, NULL); + g_return_val_if_fail (GMIME_IS_OBJECT(mpart->data), NULL); + return g_mime_object_get_content_id((GMimeObject*)mpart->data); +} + + + +static MuMsgPartType +get_disposition (GMimeObject *mobj) +{ + const char *disp; + + disp = g_mime_object_get_disposition (mobj); + if (!disp) + return MU_MSG_PART_TYPE_NONE; + + if (strcasecmp (disp, GMIME_DISPOSITION_ATTACHMENT) == 0) + return MU_MSG_PART_TYPE_ATTACHMENT; + + if (strcasecmp (disp, GMIME_DISPOSITION_INLINE) == 0) + return MU_MSG_PART_TYPE_INLINE; + + return MU_MSG_PART_TYPE_NONE; +} + +/* call 'func' with information about this MIME-part */ +static inline void +check_signature (MuMsg *msg, GMimeMultipartSigned *part, MuMsgOptions opts) +{ + GError *err; + + err = NULL; + mu_msg_crypto_verify_part (part, opts, &err); + if (err) { + g_warning ("error verifying signature: %s", err->message); + g_clear_error (&err); + } +} + + +/* Note: this is function will be called by GMime when it needs a + * password. However, GMime <= 2.6.10 does not handle + * getting passwords correctly, so this might fail. see: + * password_requester in mu-msg-crypto.c */ +static gchar* +get_console_pw (const char* user_id, const char *prompt_ctx, + gboolean reprompt, gpointer user_data) +{ + char *prompt, *pass; + + if (!g_mime_check_version(2,6,11)) + g_printerr ( + "*** the gmime library you are using has version " + "%u.%u.%u (<= 2.6.10)\n" + "*** this version has a bug in its password " + "retrieval routine, and probably won't work.\n", + gmime_major_version, gmime_minor_version, + gmime_micro_version); + + if (reprompt) + g_print ("Authentication failed. Please try again\n"); + + prompt = g_strdup_printf ("Password for %s: ", user_id); + + pass = mu_util_read_password (prompt); + g_free (prompt); + + return pass; +} + + +static gboolean +handle_encrypted_part (MuMsg *msg, GMimeMultipartEncrypted *part, + MuMsgOptions opts, unsigned *index, + MuMsgPartForeachFunc func, gpointer user_data) +{ + GError *err; + gboolean rv; + GMimeObject *dec; + MuMsgPartPasswordFunc pw_func; + + if (opts & MU_MSG_OPTION_CONSOLE_PASSWORD) + pw_func = (MuMsgPartPasswordFunc)get_console_pw; + else + pw_func = NULL; + + + err = NULL; + dec = mu_msg_crypto_decrypt_part (part, opts, pw_func, NULL, &err); + if (err) { + g_warning ("error decrypting part: %s", err->message); + g_clear_error (&err); + } + + if (dec) { + rv = handle_mime_object (msg, dec, (GMimeObject *) part, + opts, index, TRUE, func, user_data); + g_object_unref (dec); + } else { + /* On failure to decrypt, list the encrypted part as + * an attachment + */ + GMimeObject *encrypted; + + encrypted = g_mime_multipart_get_part ( + GMIME_MULTIPART (part), 1); + + g_return_val_if_fail (GMIME_IS_PART(encrypted), FALSE); + + rv = handle_mime_object (msg, encrypted, (GMimeObject *) part, + opts, index, FALSE, func, user_data); + } + + return rv; +} + +static gboolean +looks_like_text_body_part (GMimeContentType *ctype) +{ + unsigned u; + static struct { + const char *type; + const char *subtype; + } types[] = { + { "text", "plain" }, + { "text", "x-markdown" }, + { "text", "x-diff" }, + { "text", "x-patch" }, + { "application", "x-patch"} + /* possible other types */ + }; + + for (u = 0; u != G_N_ELEMENTS(types); ++u) + if (g_mime_content_type_is_type ( + ctype, types[u].type, types[u].subtype)) + return TRUE; + + return FALSE; +} + + +static MuMsgPartSigStatusReport* +copy_status_report_maybe (GObject *obj) +{ + MuMsgPartSigStatusReport *report, *copy; + + report = g_object_get_data (obj, SIG_STATUS_REPORT); + if (!report) + return NULL; /* nothing to copy */ + + copy = g_slice_new0(MuMsgPartSigStatusReport); + copy->verdict = report->verdict; + + if (report->report) + copy->report = g_strdup (report->report); + if (report->signers) + copy->signers = g_strdup (report->signers); + + return copy; +} + + + +/* call 'func' with information about this MIME-part */ +static gboolean +handle_part (MuMsg *msg, GMimePart *part, GMimeObject *parent, + MuMsgOptions opts, unsigned *index, gboolean decrypted, + MuMsgPartForeachFunc func, gpointer user_data) +{ + GMimeContentType *ct; + MuMsgPart msgpart; + + memset (&msgpart, 0, sizeof(MuMsgPart)); + + msgpart.size = get_part_size (part); + msgpart.part_type = MU_MSG_PART_TYPE_LEAF; + msgpart.part_type |= get_disposition ((GMimeObject*)part); + if (decrypted) + msgpart.part_type |= MU_MSG_PART_TYPE_DECRYPTED; + else if ((opts & MU_MSG_OPTION_DECRYPT) && + GMIME_IS_MULTIPART_ENCRYPTED (parent)) + msgpart.part_type |= MU_MSG_PART_TYPE_ENCRYPTED; + + + ct = g_mime_object_get_content_type ((GMimeObject*)part); + if (GMIME_IS_CONTENT_TYPE(ct)) { + msgpart.type = g_mime_content_type_get_media_type (ct); + msgpart.subtype = g_mime_content_type_get_media_subtype (ct); + /* store in the part_type as well, for quick checking */ + if (looks_like_text_body_part (ct)) + msgpart.part_type |= MU_MSG_PART_TYPE_TEXT_PLAIN; + else if (g_mime_content_type_is_type (ct, "text", "html")) + msgpart.part_type |= MU_MSG_PART_TYPE_TEXT_HTML; + } + + /* put the verification info in the pgp-signature and every + * descendent of a pgp-encrypted part */ + msgpart.sig_status_report = NULL; + if (g_ascii_strcasecmp (msgpart.subtype, "pgp-signature") == 0 || + decrypted) { + msgpart.sig_status_report = + copy_status_report_maybe (G_OBJECT(parent)); + if (msgpart.sig_status_report) + msgpart.part_type |= MU_MSG_PART_TYPE_SIGNED; + } + + msgpart.data = (gpointer)part; + msgpart.index = (*index)++; + + func (msg, &msgpart, user_data); + + mu_msg_part_sig_status_report_destroy (msgpart.sig_status_report); + + return TRUE; +} + + +/* call 'func' with information about this MIME-part */ +static gboolean +handle_message_part (MuMsg *msg, GMimeMessagePart *mimemsgpart, + GMimeObject *parent, MuMsgOptions opts, unsigned *index, + gboolean decrypted, + MuMsgPartForeachFunc func, gpointer user_data) +{ + MuMsgPart msgpart; + + memset (&msgpart, 0, sizeof(MuMsgPart)); + + msgpart.type = "message"; + msgpart.subtype = "rfc822"; + msgpart.index = (*index)++; + + /* msgpart.size = 0; /\* maybe calculate this? *\/ */ + + msgpart.part_type = MU_MSG_PART_TYPE_MESSAGE; + msgpart.part_type |= get_disposition ((GMimeObject*)mimemsgpart); + + msgpart.data = (gpointer)mimemsgpart; + func (msg, &msgpart, user_data); + + if (opts & MU_MSG_OPTION_RECURSE_RFC822) { + GMimeMessage *mmsg; /* may return NULL for some + * messages */ + mmsg = g_mime_message_part_get_message (mimemsgpart); + if (mmsg) + return handle_mime_object (msg, + mmsg->mime_part, + parent, + opts, + index, + decrypted, + func, + user_data); + } + + return TRUE; +} + +static gboolean +handle_multipart (MuMsg *msg, GMimeMultipart *mpart, GMimeObject *parent, + MuMsgOptions opts, unsigned *index, gboolean decrypted, + MuMsgPartForeachFunc func, gpointer user_data) +{ + gboolean res; + GMimeObject *part; + guint i; + + res = TRUE; + for (i = 0; i < mpart->children->len; i++) { + part = (GMimeObject *) mpart->children->pdata[i]; + res &= handle_mime_object (msg, part, parent, + opts, index, decrypted, + func, user_data); + } + + return res; +} + + +static gboolean +handle_mime_object (MuMsg *msg, GMimeObject *mobj, GMimeObject *parent, + MuMsgOptions opts, unsigned *index, gboolean decrypted, + MuMsgPartForeachFunc func, gpointer user_data) +{ + if (GMIME_IS_PART (mobj)) + return handle_part + (msg, GMIME_PART(mobj), parent, + opts, index, decrypted, func, user_data); + else if (GMIME_IS_MESSAGE_PART (mobj)) + return handle_message_part + (msg, GMIME_MESSAGE_PART(mobj), + parent, opts, index, decrypted, func, user_data); + else if ((opts & MU_MSG_OPTION_VERIFY) && + GMIME_IS_MULTIPART_SIGNED (mobj)) { + check_signature + (msg, GMIME_MULTIPART_SIGNED (mobj), opts); + return handle_multipart + (msg, GMIME_MULTIPART (mobj), mobj, opts, + index, decrypted, func, user_data); + } else if ((opts & MU_MSG_OPTION_DECRYPT) && + GMIME_IS_MULTIPART_ENCRYPTED (mobj)) + return handle_encrypted_part + (msg, GMIME_MULTIPART_ENCRYPTED (mobj), + opts, index, func, user_data); + else if (GMIME_IS_MULTIPART (mobj)) + return handle_multipart + (msg, GMIME_MULTIPART (mobj), parent, opts, + index, decrypted, func, user_data); + return TRUE; +} + + +gboolean +mu_msg_part_foreach (MuMsg *msg, MuMsgOptions opts, + MuMsgPartForeachFunc func, gpointer user_data) +{ + unsigned index; + + index = 1; + g_return_val_if_fail (msg, FALSE); + + if (!mu_msg_load_msg_file (msg, NULL)) + return FALSE; + + return handle_mime_object (msg, + msg->_file->_mime_msg->mime_part, + (GMimeObject *) msg->_file->_mime_msg, + opts, + &index, + FALSE, + func, + user_data); +} + + +static gboolean +write_part_to_fd (GMimePart *part, int fd, GError **err) +{ + GMimeStream *stream; + GMimeDataWrapper *wrapper; + gboolean rv; + + stream = g_mime_stream_fs_new (fd); + if (!GMIME_IS_STREAM(stream)) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, + "failed to create stream"); + return FALSE; + } + g_mime_stream_fs_set_owner (GMIME_STREAM_FS(stream), FALSE); + + wrapper = g_mime_part_get_content (part); + if (!GMIME_IS_DATA_WRAPPER(wrapper)) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, + "failed to create wrapper"); + g_object_unref (stream); + return FALSE; + } + g_object_ref (part); /* FIXME: otherwise, the unrefs below + * give errors...*/ + + if (g_mime_data_wrapper_write_to_stream (wrapper, stream) == -1) { + rv = FALSE; + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, + "failed to write to stream"); + } else + rv = TRUE; + + /* g_object_unref (wrapper); we don't own it */ + g_object_unref (stream); + + return rv; +} + + + +static gboolean +write_object_to_fd (GMimeObject *obj, int fd, GError **err) +{ + gchar *str; + str = g_mime_object_to_string (obj, NULL); + + if (!str) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, + "could not get string from object"); + return FALSE; + } + + if (write (fd, str, strlen(str)) == -1) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, + "failed to write object: %s", + strerror(errno)); + return FALSE; + } + + return TRUE; +} + + +static gboolean +save_object (GMimeObject *obj, MuMsgOptions opts, const char *fullpath, + GError **err) +{ + int fd; + gboolean rv; + gboolean use_existing, overwrite; + + use_existing = opts & MU_MSG_OPTION_USE_EXISTING; + overwrite = opts & MU_MSG_OPTION_OVERWRITE; + + /* don't try to overwrite when we already have it; useful when + * you're sure it's not a different file with the same name */ + if (use_existing && access (fullpath, F_OK) == 0) + return TRUE; + + /* ok, try to create the file */ + fd = mu_util_create_writeable_fd (fullpath, 0600, overwrite); + if (fd == -1) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, + "could not open '%s' for writing: %s", + fullpath, errno ? strerror(errno) : "error"); + return FALSE; + } + + if (GMIME_IS_PART (obj)) + rv = write_part_to_fd ((GMimePart*)obj, fd, err); + else + rv = write_object_to_fd (obj, fd, err); + + if (close (fd) != 0 && !err) { /* don't write on top of old err */ + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, + "could not close '%s': %s", + fullpath, errno ? strerror(errno) : "error"); + return FALSE; + } + + return rv; +} + + +gchar* +mu_msg_part_get_path (MuMsg *msg, MuMsgOptions opts, + const char* targetdir, unsigned index, GError **err) +{ + char *fname, *filepath; + GMimeObject* mobj; + + g_return_val_if_fail (msg, NULL); + + if (!mu_msg_load_msg_file (msg, NULL)) + return NULL; + + mobj = get_mime_object_at_index (msg, opts, index); + if (!mobj){ + mu_util_g_set_error (err, MU_ERROR_GMIME, + "cannot find part %u", index); + return NULL; + } + + fname = mime_part_get_filename (mobj, index, TRUE); + filepath = g_build_path (G_DIR_SEPARATOR_S, targetdir ? targetdir : "", + fname, NULL); + + /* Unref it since it was referenced earlier by + * get_mime_object_at_index */ + g_object_unref (mobj); + g_free (fname); + + return filepath; +} + + + +gchar* +mu_msg_part_get_cache_path (MuMsg *msg, MuMsgOptions opts, guint partid, + GError **err) +{ + char *dirname, *filepath; + const char* path; + + g_return_val_if_fail (msg, NULL); + + if (!mu_msg_load_msg_file (msg, NULL)) + return NULL; + + path = mu_msg_get_path (msg); + + /* g_compute_checksum_for_string may be better, but requires + * rel. new glib (2.16) */ + dirname = g_strdup_printf ("%s%c%x%c%u", + mu_util_cache_dir(), G_DIR_SEPARATOR, + g_str_hash (path), G_DIR_SEPARATOR, + partid); + + if (!mu_util_create_dir_maybe (dirname, 0700, FALSE)) { + mu_util_g_set_error (err, MU_ERROR_FILE, + "failed to create dir %s", dirname); + g_free (dirname); + return NULL; + } + + filepath = mu_msg_part_get_path (msg, opts, dirname, partid, err); + g_free (dirname); + + return filepath; +} + + +gboolean +mu_msg_part_save (MuMsg *msg, MuMsgOptions opts, + const char *fullpath, guint partidx, GError **err) +{ + gboolean rv; + GMimeObject *part; + + g_return_val_if_fail (msg, FALSE); + g_return_val_if_fail (fullpath, FALSE); + g_return_val_if_fail (!((opts & MU_MSG_OPTION_OVERWRITE) && + (opts & MU_MSG_OPTION_USE_EXISTING)), FALSE); + + rv = FALSE; + + if (!mu_msg_load_msg_file (msg, err)) + return rv; + + part = get_mime_object_at_index (msg, opts, partidx); + + /* special case: convert a message-part into a message */ + if (GMIME_IS_MESSAGE_PART (part)) + part = (GMimeObject*)g_mime_message_part_get_message + (GMIME_MESSAGE_PART (part)); + + if (!part) + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, + "part %u does not exist", partidx); + else if (!GMIME_IS_PART(part) && !GMIME_IS_MESSAGE(part)) + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, + "unexpected type %s for part %u", + G_OBJECT_TYPE_NAME((GObject*)part), + partidx); + else + rv = save_object (part, opts, fullpath, err); + + g_clear_object(&part); + + return rv; +} + + +gchar* +mu_msg_part_save_temp (MuMsg *msg, MuMsgOptions opts, guint partidx, + GError **err) +{ + gchar *filepath; + + filepath = mu_msg_part_get_cache_path (msg, opts, partidx, err); + if (!filepath) + return NULL; + + if (!mu_msg_part_save (msg, opts, filepath, partidx, err)) { + g_free (filepath); + return NULL; + } + + return filepath; +} + +static gboolean +match_cid (MuMsgPart *mpart, const char *cid) +{ + const char *this_cid; + + this_cid = g_mime_object_get_content_id ((GMimeObject*)mpart->data); + + return g_strcmp0 (this_cid, cid) ? TRUE : FALSE; +} + +int +mu_msg_find_index_for_cid (MuMsg *msg, MuMsgOptions opts, + const char *sought_cid) +{ + const char* cid; + + g_return_val_if_fail (msg, -1); + g_return_val_if_fail (sought_cid, -1); + + if (!mu_msg_load_msg_file (msg, NULL)) + return -1; + + cid = g_str_has_prefix (sought_cid, "cid:") ? + sought_cid + 4 : sought_cid; + + return get_matching_part_index (msg, opts, + (MuMsgPartMatchFunc)match_cid, + (gpointer)cid); +} + +struct _RxMatchData { + GSList *_lst; + const GRegex *_rx; + guint _idx; +}; +typedef struct _RxMatchData RxMatchData; + + +static void +match_filename_rx (MuMsg *msg, MuMsgPart *mpart, RxMatchData *mdata) +{ + char *fname; + + fname = mu_msg_part_get_filename (mpart, FALSE); + if (!fname) + return; + + if (g_regex_match (mdata->_rx, fname, 0, NULL)) + mdata->_lst = g_slist_prepend (mdata->_lst, + GUINT_TO_POINTER(mpart->index)); + g_free (fname); +} + + +GSList* +mu_msg_find_files (MuMsg *msg, MuMsgOptions opts, const GRegex *pattern) +{ + RxMatchData mdata; + + g_return_val_if_fail (msg, NULL); + g_return_val_if_fail (pattern, NULL); + + if (!mu_msg_load_msg_file (msg, NULL)) + return NULL; + + mdata._lst = NULL; + mdata._rx = pattern; + mdata._idx = 0; + + mu_msg_part_foreach (msg, opts, + (MuMsgPartForeachFunc)match_filename_rx, + &mdata); + return mdata._lst; +} + + +gboolean +mu_msg_part_maybe_attachment (MuMsgPart *part) +{ + g_return_val_if_fail (part, FALSE); + + /* attachments must be leaf parts */ + if (!(part->part_type & MU_MSG_PART_TYPE_LEAF)) + return FALSE; + + /* parts other than text/plain, text/html are considered + * attachments as well */ + if (!(part->part_type & MU_MSG_PART_TYPE_TEXT_PLAIN) && + !(part->part_type & MU_MSG_PART_TYPE_TEXT_HTML)) + return TRUE; + + return part->part_type & MU_MSG_PART_TYPE_ATTACHMENT ? TRUE : FALSE; +} diff --git a/lib/mu-msg-part.h b/lib/mu-msg-part.h new file mode 100644 index 0000000..4f26ddf --- /dev/null +++ b/lib/mu-msg-part.h @@ -0,0 +1,268 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_MSG_PART_H__ +#define __MU_MSG_PART_H__ + +#include <glib.h> +#include <unistd.h> /* for ssize_t */ + +#define SIG_STATUS_REPORT "sig-status-report" + +G_BEGIN_DECLS + +enum _MuMsgPartType { + MU_MSG_PART_TYPE_NONE = 0, + + /* MIME part without children */ + MU_MSG_PART_TYPE_LEAF = 1 << 1, + /* an RFC822 message part? */ + MU_MSG_PART_TYPE_MESSAGE = 1 << 2, + /* disposition inline? */ + MU_MSG_PART_TYPE_INLINE = 1 << 3, + /* disposition attachment? */ + MU_MSG_PART_TYPE_ATTACHMENT = 1 << 4, + /* a signed part? */ + MU_MSG_PART_TYPE_SIGNED = 1 << 5, + /* an encrypted part? */ + MU_MSG_PART_TYPE_ENCRYPTED = 1 << 6, + /* a decrypted part? */ + MU_MSG_PART_TYPE_DECRYPTED = 1 << 7, + /* a text/plain part? */ + MU_MSG_PART_TYPE_TEXT_PLAIN = 1 << 8, + /* a text/html part? */ + MU_MSG_PART_TYPE_TEXT_HTML = 1 << 9 +}; +typedef enum _MuMsgPartType MuMsgPartType; + + +/* the signature status */ +enum _MuMsgPartSigStatus { + MU_MSG_PART_SIG_STATUS_UNSIGNED = 0, + + MU_MSG_PART_SIG_STATUS_GOOD, + MU_MSG_PART_SIG_STATUS_BAD, + MU_MSG_PART_SIG_STATUS_ERROR, + MU_MSG_PART_SIG_STATUS_FAIL +}; +typedef enum _MuMsgPartSigStatus MuMsgPartSigStatus; + +typedef struct { + MuMsgPartSigStatus verdict; + const char *report; + const char *signers; +} MuMsgPartSigStatusReport; + +/** + * destroy a MuMsgPartSignatureStatusReport object + * + * @param report a MuMsgPartSignatureStatusReport object + */ +void mu_msg_part_sig_status_report_destroy (MuMsgPartSigStatusReport *report); + + +struct _MuMsgPart { + + /* index of this message part */ + unsigned index; + + /* cid */ + /* const char *content_id; */ + + /* content-type: type/subtype, ie. text/plain */ + const char *type; + const char *subtype; + + /* size of the part; or < 0 if unknown */ + ssize_t size; + + gpointer data; /* opaque data */ + + MuMsgPartType part_type; + MuMsgPartSigStatusReport *sig_status_report; + }; +typedef struct _MuMsgPart MuMsgPart; + +/** + * get some appropriate file name for the mime-part + * + * @param mpart a MuMsgPart + * @param construct_if_needed if there is no + * real filename, construct one. + * + * @return the file name (free with g_free) + */ +char *mu_msg_part_get_filename (MuMsgPart *mpart, gboolean construct_if_needed) + G_GNUC_WARN_UNUSED_RESULT; + + +/** + * get appropriate content id for the mime-part + * + * @param mpart a MuMsgPart + * + * @return const content id + */ +const gchar* +mu_msg_part_get_content_id (MuMsgPart *mpart) + G_GNUC_WARN_UNUSED_RESULT; + +/** + * get the text in the MuMsgPart (ie. in its GMimePart) + * + * @param msg a MuMsg + * @param part a MuMsgPart + * @param opts MuMsgOptions + * + * @return utf8 string for this MIME part, to be freed by caller + */ +char* mu_msg_part_get_text (MuMsg *msg, MuMsgPart *part, MuMsgOptions opts) + G_GNUC_WARN_UNUSED_RESULT; + + +/** + * does this msg part look like an attachment? + * + * @param part a message part + * + * @return TRUE if it looks like an attachment, FALSE otherwise + */ +gboolean mu_msg_part_maybe_attachment (MuMsgPart *part); + + +/** + * save a specific attachment to some targetdir + * + * @param msg a valid MuMsg instance + * @param opts mu-message options (OVERWRITE/USE_EXISTING) + * @gchar filepath the filepath to save + * @param partidx index of the attachment you want to save + * @param err receives error information (when function returns NULL) + * + * @return full path to the message part saved or NULL in case or + * error; free with g_free + */ +gboolean mu_msg_part_save (MuMsg *msg, MuMsgOptions opts, + const char *filepath, guint partidx, + GError **err); + + +/** + * save a message part to a temporary file and return the full path to + * this file + * + * @param msg a MuMsg message + * @param opts mu-message options (OVERWRITE/USE_EXISTING) + * @param partidx index of the part to save + * @param err receives error information if any + * + * @return the full path to the temp file, or NULL in case of error + */ +gchar* mu_msg_part_save_temp (MuMsg *msg, MuMsgOptions opts, + guint partidx, GError **err) + G_GNUC_WARN_UNUSED_RESULT; + + + +/** + * get a filename for the saving the message part; try the filename + * specified for the message part if any, otherwise determine a unique + * name based on the partidx and the message path + * + * @param msg a msg + * @param opts mu-message options + * @param targetdir where to store the part + * @param partidx the part for which to determine a filename + * @param err receives error information (when function returns NULL) + * + * @return a filepath (g_free when done with it) or NULL in case of error + */ +gchar* mu_msg_part_get_path (MuMsg *msg, MuMsgOptions opts, + const char* targetdir, + guint partidx, GError **err) + G_GNUC_WARN_UNUSED_RESULT; + + +/** + * get a full path name for a file for saving the message part INDEX; + * this path is unique (1:1) for this particular message and part for + * this user. Thus, it can be used as a cache. + * + * Will create the directory if needed. + * + * @param msg a msg + * @param opts mu-message options + * @param partidx the part for which to determine a filename + * @param err receives error information (when function returns NULL) + * + * @return a filepath (g_free when done with it) or NULL in case of error + */ +gchar* mu_msg_part_get_cache_path (MuMsg *msg, MuMsgOptions opts, + guint partidx, GError **err) + G_GNUC_WARN_UNUSED_RESULT; + + +/** + * get the part index for the message part with a certain content-id + * + * @param msg a message + * @param content_id a content-id to search + * + * @return the part index number of the found part, or -1 if it was not found + */ +int mu_msg_find_index_for_cid (MuMsg *msg, MuMsgOptions opts, const char* content_id); + + + +/** + * retrieve a list of indices for mime-parts with filenames matching a regex + * + * @param msg a message + * @param opts + * @param a regular expression to match the filename with + * + * @return a list with indices for the files matching the pattern; the + * indices are the GPOINTER_TO_UINT(lst->data) of the list. They must + * be freed with g_slist_free + */ +GSList* mu_msg_find_files (MuMsg *msg, MuMsgOptions opts, const GRegex *pattern); + + +typedef void (*MuMsgPartForeachFunc) (MuMsg *msg, MuMsgPart*, gpointer); + + +/** + * call a function for each of the mime part in a message + * + * @param msg a valid MuMsg* instance + * @param func a callback function to call for each contact; when + * the callback does not return TRUE, it won't be called again + * @param user_data a user-provide pointer that will be passed to the callback + * @param options, bit-wise OR'ed + * + * @return FALSE in case of error, TRUE otherwise + */ +gboolean mu_msg_part_foreach (MuMsg *msg, MuMsgOptions opts, + MuMsgPartForeachFunc func, gpointer user_data); + +G_END_DECLS + +#endif /*__MU_MSG_PART_H__*/ diff --git a/lib/mu-msg-prio.c b/lib/mu-msg-prio.c new file mode 100644 index 0000000..96a959a --- /dev/null +++ b/lib/mu-msg-prio.c @@ -0,0 +1,65 @@ +/* +** Copyright (C) 2012-2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include "mu-msg-prio.h" + + +const char* +mu_msg_prio_name (MuMsgPrio prio) +{ + switch (prio) { + case MU_MSG_PRIO_LOW : return "low"; + case MU_MSG_PRIO_NORMAL : return "normal"; + case MU_MSG_PRIO_HIGH : return "high"; + default : g_return_val_if_reached (NULL); + } +} + +MuMsgPrio +mu_msg_prio_from_char (char k) +{ + g_return_val_if_fail (k == 'l' || k == 'n' || k == 'h', + MU_MSG_PRIO_NONE); + return (MuMsgPrio)k; +} + +char +mu_msg_prio_char (MuMsgPrio prio) +{ + if (!(prio == 'l' || prio == 'n' || prio == 'h')) { + g_warning ("prio: %c", (char)prio); + } + + + g_return_val_if_fail (prio == 'l' || prio == 'n' || prio == 'h', + 0); + + return (char)prio; +} + + +void +mu_msg_prio_foreach (MuMsgPrioForeachFunc func, gpointer user_data) +{ + g_return_if_fail (func); + + func (MU_MSG_PRIO_LOW, user_data); + func (MU_MSG_PRIO_NORMAL, user_data); + func (MU_MSG_PRIO_HIGH, user_data); +} diff --git a/lib/mu-msg-prio.h b/lib/mu-msg-prio.h new file mode 100644 index 0000000..df3e8c3 --- /dev/null +++ b/lib/mu-msg-prio.h @@ -0,0 +1,84 @@ +/* +** Copyright (C) 2008-2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_MSG_PRIO_H__ +#define __MU_MSG_PRIO_H__ + +#include <glib.h> + +G_BEGIN_DECLS + +enum _MuMsgPrio { + MU_MSG_PRIO_LOW = 'l', + MU_MSG_PRIO_NORMAL = 'n', + MU_MSG_PRIO_HIGH = 'h' +}; +typedef enum _MuMsgPrio MuMsgPrio; + +static const MuMsgPrio MU_MSG_PRIO_NONE = (MuMsgPrio)0; + + +/** + * get a printable name for the message priority + * (ie., MU_MSG_PRIO_LOW=>"low" etc.) + * + * @param prio a message priority + * + * @return a printable name for this priority + */ +const char* mu_msg_prio_name (MuMsgPrio prio) G_GNUC_CONST; + + +/** + * get the MuMsgPriority corresponding to a one-character shortcut + * ('l'=>MU_MSG_PRIO_, 'n'=>MU_MSG_PRIO_NORMAL or + * 'h'=>MU_MSG_PRIO_HIGH) + * + * @param k a character + * + * @return a message priority + */ +MuMsgPrio mu_msg_prio_from_char (char k) G_GNUC_CONST; + + +/** + * get the one-character shortcut corresponding to a message priority + * ('l'=>MU_MSG_PRIO_, 'n'=>MU_MSG_PRIO_NORMAL or + * 'h'=>MU_MSG_PRIO_HIGH) + * + * @param prio a message priority + * + * @return a shortcut character or 0 in case of error + */ +char mu_msg_prio_char (MuMsgPrio prio) G_GNUC_CONST; + +typedef void (*MuMsgPrioForeachFunc) (MuMsgPrio prio, gpointer user_data); +/** + * call a function for each message priority + * + * @param func a callback function + * @param user_data a user pointer to pass to the callback + */ +void mu_msg_prio_foreach (MuMsgPrioForeachFunc func, gpointer user_data); + + + +G_END_DECLS + +#endif /*__MU_MSG_PRIO_H__*/ diff --git a/lib/mu-msg-priv.h b/lib/mu-msg-priv.h new file mode 100644 index 0000000..8f61719 --- /dev/null +++ b/lib/mu-msg-priv.h @@ -0,0 +1,140 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_MSG_PRIV_H__ +#define __MU_MSG_PRIV_H__ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include <gmime/gmime.h> +#include <stdlib.h> + +#include <mu-msg.h> +#include <mu-msg-file.h> +#include <mu-msg-doc.h> +#include "mu-msg-part.h" + +G_BEGIN_DECLS + +struct _MuMsgFile { + GMimeMessage *_mime_msg; + time_t _timestamp; + size_t _size; + char _path [PATH_MAX + 1]; + char _maildir [PATH_MAX + 1]; +}; + + +/* we put the the MuMsg definition in this separate -priv file, so we + * can split the mu_msg implementations over separate files */ +struct _MuMsg { + + guint _refcount; + + /* our two backend */ + MuMsgFile *_file; /* based on GMime, ie. a file on disc */ + MuMsgDoc *_doc; /* based on Xapian::Document */ + + /* lists where we push allocated strings / GSLists of string + * so we can free them when the struct gets destroyed (and we + * can return them as 'const to callers) + */ + GSList *_free_later_str; + GSList *_free_later_lst; +}; + + +/** + * convert a GMimePart to a string + * + * @param part a GMimePart + * @param err will receive TRUE if there was an error, FALSE + * otherwise. Must NOT be NULL. + * + * @return utf8 string for this MIME part, to be freed by caller + */ +gchar* mu_msg_mime_part_to_string (GMimePart *part, gboolean *err) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + + +/** + * Like g_mime_message_foreach, but will recurse into encrypted parts + * if @param decrypt is TRUE and mu was built with crypto support + * + * @param msg a GMimeMessage + * @param decrypt whether to try to automatically decrypt + * @param func user callback function for each part + * @param user_data user point passed to callback function + * @param err receives error information + * + */ +void mu_mime_message_foreach (GMimeMessage *msg, gboolean decrypt, + GMimeObjectForeachFunc func, + gpointer user_data); + +/** + * callback function to retrieve a password from the user + * + * @param user_id the user name / id to get the password for + * @param prompt_ctx a string containing some helpful context for the prompt + * @param reprompt whether this is a reprompt after an earlier, incorrect password + * @param user_data the user_data pointer passed to mu_msg_part_decrypt_foreach + * + * @return a newly allocated (g_free'able) string + */ +typedef char* (*MuMsgPartPasswordFunc) (const char *user_id, const char *prompt_ctx, + gboolean reprompt, gpointer user_data); + + +/** + * verify the signature of a signed message part + * + * @param sig a signed message part + * @param opts message options + * @param err receive error information + * + * @return a status report object, free with mu_msg_part_sig_status_report_destroy + */ +void mu_msg_crypto_verify_part (GMimeMultipartSigned *sig, + MuMsgOptions opts, + GError **err); + +/** + * decrypt the given encrypted mime multipart + * + * @param enc encrypted part + * @param opts options + * @param password_func callback function to retrieve as password (or NULL) + * @param user_data pointer passed to the password func + * @param err receives error data + * + * @return the decrypted part, or NULL in case of error + */ +GMimeObject* mu_msg_crypto_decrypt_part (GMimeMultipartEncrypted *enc, MuMsgOptions opts, + MuMsgPartPasswordFunc func, gpointer user_data, + GError **err) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +G_END_DECLS + +#endif /*__MU_MSG_PRIV_H__*/ diff --git a/lib/mu-msg-sexp.c b/lib/mu-msg-sexp.c new file mode 100644 index 0000000..359ae22 --- /dev/null +++ b/lib/mu-msg-sexp.c @@ -0,0 +1,635 @@ +/* +** Copyright (C) 2011-2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ +#include <string.h> +#include <ctype.h> + +#include "utils/mu-str.h" +#include "mu-msg.h" +#include "mu-msg-iter.h" +#include "mu-msg-part.h" +#include "mu-maildir.h" + +static void +append_sexp_attr_list (GString *gstr, const char* elm, const GSList *lst) +{ + const GSList *cur; + + if (!lst) + return; /* empty list, don't include */ + + g_string_append_printf (gstr, "\t:%s ( ", elm); + + for (cur = lst; cur; cur = g_slist_next(cur)) { + char *str; + str = mu_str_escape_c_literal + ((const gchar*)cur->data, TRUE); + g_string_append_printf (gstr, "%s ", str); + g_free (str); + } + + g_string_append (gstr, ")\n"); +} + +static void +append_sexp_attr (GString *gstr, const char* elm, const char *str) +{ + gchar *esc, *utf8, *cur; + + if (!str || strlen(str) == 0) + return; /* empty: don't include */ + + + utf8 = mu_str_utf8ify (str); + + for (cur = utf8; *cur; ++cur) + if (iscntrl(*cur)) + *cur = ' '; + + esc = mu_str_escape_c_literal (utf8, TRUE); + g_free (utf8); + + g_string_append_printf (gstr, "\t:%s %s\n", elm, esc); + g_free (esc); +} + +static void +append_sexp_body_attr (GString *gstr, const char* elm, const char *str) +{ + gchar *esc; + + if (!str || strlen(str) == 0) + return; /* empty: don't include */ + + esc = mu_str_escape_c_literal (str, TRUE); + + g_string_append_printf (gstr, "\t:%s %s\n", elm, esc); + g_free (esc); +} + +struct _ContactData { + gboolean from, to, cc, bcc, reply_to; + GString *gstr; + MuMsgContactType prev_ctype; +}; +typedef struct _ContactData ContactData; + +static gchar* +get_name_email_pair (MuMsgContact *c) +{ + gchar *name, *email, *pair; + + name = (char*)mu_msg_contact_name(c); + email = (char*)mu_msg_contact_email(c); + + name = name ? mu_str_escape_c_literal (name, TRUE) : NULL; + email = email ? mu_str_escape_c_literal (email, TRUE) : NULL; + + pair = g_strdup_printf ("(%s . %s)", + name ? name : "nil", + email ? email : "nil"); + g_free (name); + g_free (email); + + return pair; +} + + +static void +add_prefix_maybe (GString *gstr, gboolean *field, const char *prefix) +{ + /* if there's nothing in the field yet, add the prefix */ + if (!*field) + g_string_append (gstr, prefix); + + *field = TRUE; +} + +static gboolean +each_contact (MuMsgContact *c, ContactData *cdata) +{ + char *pair; + MuMsgContactType ctype; + + ctype = mu_msg_contact_type (c); + + /* if the current type is not the previous type, close the + * previous first */ + if (cdata->prev_ctype != ctype && cdata->prev_ctype != (unsigned)-1) + g_string_append (cdata->gstr, ")\n"); + + switch (ctype) { + + case MU_MSG_CONTACT_TYPE_FROM: + add_prefix_maybe (cdata->gstr, &cdata->from, "\t:from ("); + break; + case MU_MSG_CONTACT_TYPE_TO: + add_prefix_maybe (cdata->gstr, &cdata->to, "\t:to ("); + break; + case MU_MSG_CONTACT_TYPE_CC: + add_prefix_maybe (cdata->gstr, &cdata->cc, "\t:cc ("); + break; + case MU_MSG_CONTACT_TYPE_BCC: + add_prefix_maybe (cdata->gstr, &cdata->bcc, "\t:bcc ("); + break; + case MU_MSG_CONTACT_TYPE_REPLY_TO: + add_prefix_maybe (cdata->gstr, &cdata->reply_to, + "\t:reply-to ("); + break; + default: g_return_val_if_reached (FALSE); + } + + cdata->prev_ctype = ctype; + + pair = get_name_email_pair (c); + g_string_append (cdata->gstr, pair); + g_free (pair); + + return TRUE; +} + +static void +maybe_append_list_post (GString *gstr, MuMsg *msg) +{ + /* some mailing lists do not set the reply-to; see pull #1278. So for + * those cases, check the List-Post address and use that instead */ + + GMatchInfo *minfo; + GRegex *rx; + const char* list_post; + + list_post = mu_msg_get_header (msg, "List-Post"); + if (!list_post) + return; + + rx = g_regex_new ("<?mailto:([a-z0-9!@#$%&'*+-/=?^_`{|}~]+)>?", + G_REGEX_CASELESS, (GRegexMatchFlags)0, NULL); + g_return_if_fail(rx); + + if (g_regex_match (rx, list_post, 0, &minfo)) { + char *addr; + addr = g_match_info_fetch (minfo, 1); + g_string_append_printf (gstr,"\t:list-post ((nil . \"%s\"))\n", addr); + g_free(addr); + } + + g_match_info_free (minfo); + g_regex_unref (rx); +} + + + +static void +append_sexp_contacts (GString *gstr, MuMsg *msg) +{ + ContactData cdata; + + cdata.from = cdata.to = cdata.cc = cdata.bcc + = cdata.reply_to = FALSE; + cdata.gstr = gstr; + cdata.prev_ctype = (unsigned)-1; + + mu_msg_contact_foreach (msg, (MuMsgContactForeachFunc)each_contact, + &cdata); + if (cdata.from || cdata.to || cdata.cc || cdata.bcc || cdata.reply_to) + gstr = g_string_append (gstr, ")\n"); + + maybe_append_list_post (gstr, msg); +} + +struct _FlagData { + char *flagstr; + MuFlags msgflags; +}; +typedef struct _FlagData FlagData; + +static void +each_flag (MuFlags flag, FlagData *fdata) +{ + if (!(flag & fdata->msgflags)) + return; + + if (!fdata->flagstr) + fdata->flagstr = g_strdup (mu_flag_name(flag)); + else { + gchar *tmp; + tmp = g_strconcat (fdata->flagstr, " ", + mu_flag_name(flag), NULL); + g_free (fdata->flagstr); + fdata->flagstr = tmp; + } +} + +static void +append_sexp_flags (GString *gstr, MuMsg *msg) +{ + FlagData fdata; + + fdata.msgflags = mu_msg_get_flags (msg); + fdata.flagstr = NULL; + + mu_flags_foreach ((MuFlagsForeachFunc)each_flag, &fdata); + if (fdata.flagstr) + g_string_append_printf (gstr, "\t:flags (%s)\n", + fdata.flagstr); + g_free (fdata.flagstr); +} + +static char* +get_temp_file (MuMsg *msg, MuMsgOptions opts, unsigned index) +{ + char *path; + GError *err; + + err = NULL; + path = mu_msg_part_get_cache_path (msg, opts, index, &err); + if (!path) + goto errexit; + + if (!mu_msg_part_save (msg, opts, path, index, &err)) + goto errexit; + + return path; + +errexit: + g_warning ("failed to save mime part: %s", + err->message ? err->message : "something went wrong"); + g_clear_error (&err); + g_free (path); + return NULL; +} + + +static gchar* +get_temp_file_maybe (MuMsg *msg, MuMsgPart *part, MuMsgOptions opts) +{ + char *tmp, *tmpfile; + + opts |= MU_MSG_OPTION_USE_EXISTING; + + if (!(opts & MU_MSG_OPTION_EXTRACT_IMAGES) || + g_ascii_strcasecmp (part->type, "image") != 0) + return NULL; + + tmp = get_temp_file (msg, opts, part->index); + if (!tmp) + return NULL; + + tmpfile = mu_str_escape_c_literal (tmp, TRUE); + g_free (tmp); + return tmpfile; +} + + +struct _PartInfo { + char *parts; + MuMsgOptions opts; +}; +typedef struct _PartInfo PartInfo; + +static char* +sig_verdict (MuMsgPart *mpart) +{ + char *signers, *s; + const char *verdict; + MuMsgPartSigStatusReport *report; + + report = mpart->sig_status_report; + if (!report) + return g_strdup (""); + + switch (report->verdict) { + case MU_MSG_PART_SIG_STATUS_GOOD: + verdict = ":signature verified"; + break; + case MU_MSG_PART_SIG_STATUS_BAD: + verdict = ":signature bad"; + break; + case MU_MSG_PART_SIG_STATUS_ERROR: + verdict = ":signature unverified"; + break; + default: + verdict = ""; + break; + } + + if (!report->signers) + return g_strdup (verdict); + + signers = mu_str_escape_c_literal (report->signers, TRUE); + s = g_strdup_printf ("%s :signers %s", verdict, signers); + g_free (signers); + + return s; +} + +static const char* +dec_verdict (MuMsgPart *mpart) +{ + MuMsgPartType ptype; + + ptype = mpart->part_type; + + if (ptype & MU_MSG_PART_TYPE_DECRYPTED) + return ":decryption succeeded"; + else if (ptype & MU_MSG_PART_TYPE_ENCRYPTED) + return ":decryption failed"; + else + return ""; +} + + +static gchar * +get_part_type_string (MuMsgPartType ptype) +{ + GString *gstr; + unsigned u; + struct PartTypes { + MuMsgPartType ptype; + const char* name; + } ptypes[] = { + { MU_MSG_PART_TYPE_LEAF, "leaf" }, + { MU_MSG_PART_TYPE_MESSAGE, "message" }, + { MU_MSG_PART_TYPE_INLINE, "inline" }, + { MU_MSG_PART_TYPE_ATTACHMENT, "attachment" }, + { MU_MSG_PART_TYPE_SIGNED, "signed" }, + { MU_MSG_PART_TYPE_ENCRYPTED, "encrypted" } + }; + + gstr = g_string_sized_new (100); /* more than enough */ + gstr = g_string_append_c (gstr, '('); + + for (u = 0; u!= G_N_ELEMENTS(ptypes); ++u) { + if (ptype & ptypes[u].ptype) { + if (gstr->len > 1) + gstr = g_string_append_c (gstr, ' '); + gstr = g_string_append (gstr, ptypes[u].name); + } + } + + gstr = g_string_append_c (gstr, ')'); + + return g_string_free (gstr, FALSE); +} + + +static void +each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo) +{ + char *name, *encname, *tmp, *parttype; + char *tmpfile, *cidesc, *verdict; + const char *cid; + + name = mu_msg_part_get_filename (part, TRUE); + encname = name ? + mu_str_escape_c_literal(name, TRUE) : + g_strdup("\"noname\""); + g_free (name); + + tmpfile = get_temp_file_maybe (msg, part, pinfo->opts); + parttype = get_part_type_string (part->part_type); + verdict = sig_verdict (part); + + cid = mu_msg_part_get_content_id(part); + cidesc = cid ? mu_str_escape_c_literal(cid, TRUE) : NULL; + + tmp = g_strdup_printf + ("%s(:index %d :name %s :mime-type \"%s/%s\"%s%s " + ":type %s " + ":attachment %s %s%s :size %i %s %s)", + pinfo->parts ? pinfo->parts: "", + part->index, + encname, + part->type ? part->type : "application", + part->subtype ? part->subtype : "octet-stream", + tmpfile ? " :temp" : "", tmpfile ? tmpfile : "", + parttype, + mu_msg_part_maybe_attachment (part) ? "t" : "nil", + cidesc ? " :cid" : "", cidesc ? cidesc : "", + (int)part->size, + verdict, + dec_verdict (part)); + + g_free (encname); + g_free (tmpfile); + g_free (parttype); + g_free (verdict); + g_free (cidesc); + + g_free (pinfo->parts); + pinfo->parts = tmp; +} + + +static void +append_sexp_parts (GString *gstr, MuMsg *msg, MuMsgOptions opts) +{ + PartInfo pinfo; + + pinfo.parts = NULL; + pinfo.opts = opts; + + if (!mu_msg_part_foreach (msg, opts, (MuMsgPartForeachFunc)each_part, + &pinfo)) { + /* do nothing */ + } else if (pinfo.parts) { + g_string_append_printf (gstr, "\t:parts (%s)\n", pinfo.parts); + g_free (pinfo.parts); + } +} + +static void +append_sexp_thread_info (GString *gstr, const MuMsgIterThreadInfo *ti) +{ + g_string_append_printf + (gstr, "\t:thread (:path \"%s\" :level %u%s%s%s%s%s)\n", + ti->threadpath, + ti->level, + ti->prop & MU_MSG_ITER_THREAD_PROP_FIRST_CHILD ? + " :first-child t" : "", + ti->prop & MU_MSG_ITER_THREAD_PROP_LAST_CHILD ? + " :last-child t" : "", + ti->prop & MU_MSG_ITER_THREAD_PROP_EMPTY_PARENT ? + " :empty-parent t" : "", + ti->prop & MU_MSG_ITER_THREAD_PROP_DUP ? + " :duplicate t" : "", + ti->prop & MU_MSG_ITER_THREAD_PROP_HAS_CHILD ? + " :has-child t" : ""); +} + +static void +append_sexp_param (GString *gstr, const GSList *param) +{ + for (;param; param = g_slist_next (param)) { + const char *str; + char *key, *value; + + str = param->data; + key = str ? mu_str_escape_c_literal (str, FALSE) : g_strdup (""); + + param = g_slist_next (param); + str = param->data; + value = str ? mu_str_escape_c_literal (str, FALSE) : g_strdup (""); + + g_string_append_printf (gstr, "(\"%s\" . \"%s\")", key, value); + g_free (key); + g_free (value); + + if (param->next) + g_string_append_c (gstr, ' '); + } +} + +static void +append_message_file_parts (GString *gstr, MuMsg *msg, MuMsgOptions opts) +{ + const char *str; + GError *err; + const GSList *params; + + err = NULL; + + if (!mu_msg_load_msg_file (msg, &err)) { + g_warning ("failed to load message file: %s", + err ? err->message : "some error occurred"); + g_clear_error (&err); + return; + } + + append_sexp_parts (gstr, msg, opts); + append_sexp_contacts (gstr, msg); + + /* add the user-agent / x-mailer */ + str = mu_msg_get_header (msg, "User-Agent"); + if (str || (str = mu_msg_get_header (msg, "X-Mailer"))) + append_sexp_attr (gstr, "user-agent", str); + + params = mu_msg_get_body_text_content_type_parameters (msg, opts); + if (params) { + g_string_append_printf (gstr, "\t:body-txt-params ("); + append_sexp_param (gstr, params); + g_string_append_printf (gstr, ")\n"); + } + + append_sexp_body_attr (gstr, "body-txt", + mu_msg_get_body_text(msg, opts)); + append_sexp_body_attr (gstr, "body-html", + mu_msg_get_body_html(msg, opts)); +} + +static void +append_sexp_date_and_size (GString *gstr, MuMsg *msg) +{ + time_t t; + size_t s; + + t = mu_msg_get_date (msg); + if (t == (time_t)-1) /* invalid date? */ + t = 0; + + s = mu_msg_get_size (msg); + if (s == (size_t)-1) /* invalid size? */ + s = 0; + + g_string_append_printf + (gstr, + "\t:date (%d %u 0)\n\t:size %u\n", + (unsigned)(t >> 16), + (unsigned)(t & 0xffff), + (unsigned)s); +} + + +static void +append_sexp_tags (GString *gstr, MuMsg *msg) +{ + const GSList *tags, *t; + gchar *tagesc; + GString *tagstr = g_string_new(""); + + tags = mu_msg_get_tags (msg); + + for(t = tags; t; t = t->next) { + if (t != tags) + g_string_append(tagstr, " "); + + tagesc = mu_str_escape_c_literal((const gchar *)t->data, TRUE); + g_string_append(tagstr, tagesc); + + g_free(tagesc); + } + + if (tagstr->len > 0) + g_string_append_printf (gstr, "\t:tags (%s)\n", + tagstr->str); + g_string_free (tagstr, TRUE); +} + +char* +mu_msg_to_sexp (MuMsg *msg, unsigned docid, const MuMsgIterThreadInfo *ti, + MuMsgOptions opts) +{ + GString *gstr; + + g_return_val_if_fail (msg, NULL); + g_return_val_if_fail (!((opts & MU_MSG_OPTION_HEADERS_ONLY) && + (opts & MU_MSG_OPTION_EXTRACT_IMAGES)),NULL); + gstr = g_string_sized_new + ((opts & MU_MSG_OPTION_HEADERS_ONLY) ? 1024 : 8192); + + if (docid == 0) + g_string_append (gstr, "(\n"); + else + g_string_append_printf (gstr, "(\n\t:docid %u\n", docid); + + if (ti) + append_sexp_thread_info (gstr, ti); + + append_sexp_attr (gstr, "subject", mu_msg_get_subject (msg)); + + /* in the no-headers-only case (see below) we get a more complete list + * of contacts, so no need to get them here if that's the case */ + if (opts & MU_MSG_OPTION_HEADERS_ONLY) + append_sexp_contacts (gstr, msg); + + append_sexp_date_and_size (gstr, msg); + + append_sexp_attr (gstr, "message-id", mu_msg_get_msgid (msg)); + append_sexp_attr (gstr, "mailing-list", + mu_msg_get_mailing_list (msg)); + append_sexp_attr (gstr, "path", mu_msg_get_path (msg)); + append_sexp_attr (gstr, "maildir", mu_msg_get_maildir (msg)); + g_string_append_printf (gstr, "\t:priority %s\n", + mu_msg_prio_name(mu_msg_get_prio(msg))); + append_sexp_flags (gstr, msg); + append_sexp_tags (gstr, msg); + + append_sexp_attr_list (gstr, "references", + mu_msg_get_references (msg)); + append_sexp_attr (gstr, "in-reply-to", + mu_msg_get_header (msg, "In-Reply-To")); + + /* headers are retrieved from the database, views from the + * message file file attr things can only be gotten from the + * file (ie., mu view), not from the database (mu find). */ + if (!(opts & MU_MSG_OPTION_HEADERS_ONLY)) + append_message_file_parts (gstr, msg, opts); + + g_string_append (gstr, ")\n"); + return g_string_free (gstr, FALSE); +} diff --git a/lib/mu-msg.c b/lib/mu-msg.c new file mode 100644 index 0000000..976f3c9 --- /dev/null +++ b/lib/mu-msg.c @@ -0,0 +1,1013 @@ +/* -*- mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +** +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#include <stdlib.h> +#include <ctype.h> + +#include <gmime/gmime.h> + +#include "mu-msg-priv.h" /* include before mu-msg.h */ +#include "mu-msg.h" +#include "utils/mu-str.h" + +#include "mu-maildir.h" + +/* note, we do the gmime initialization here rather than in + * mu-runtime, because this way we don't need mu-runtime for simple + * cases -- such as our unit tests. Also note that we need gmime init + * even for the doc backend, as we use the address parsing functions + * also there. */ +static gboolean _gmime_initialized = FALSE; + +static void +gmime_init (void) +{ + g_return_if_fail (!_gmime_initialized); + + g_mime_init(); + _gmime_initialized = TRUE; +} + +static void +gmime_uninit (void) +{ + g_return_if_fail (_gmime_initialized); + + g_mime_shutdown(); + _gmime_initialized = FALSE; +} + +static MuMsg* +msg_new (void) +{ + MuMsg *self; + + self = g_slice_new0 (MuMsg); + self->_refcount = 1; + + return self; +} + +MuMsg* +mu_msg_new_from_file (const char *path, const char *mdir, + GError **err) +{ + MuMsg *self; + MuMsgFile *msgfile; + + g_return_val_if_fail (path, NULL); + + if (G_UNLIKELY(!_gmime_initialized)) { + gmime_init (); + atexit (gmime_uninit); + } + + msgfile = mu_msg_file_new (path, mdir, err); + if (!msgfile) + return NULL; + + self = msg_new (); + self->_file = msgfile; + + return self; +} + +MuMsg* +mu_msg_new_from_doc (XapianDocument *doc, GError **err) +{ + MuMsg *self; + MuMsgDoc *msgdoc; + + g_return_val_if_fail (doc, NULL); + + if (G_UNLIKELY(!_gmime_initialized)) { + gmime_init (); + atexit (gmime_uninit); + } + + msgdoc = mu_msg_doc_new (doc, err); + if (!msgdoc) + return NULL; + + self = msg_new (); + self->_doc = msgdoc; + + return self; +} + +static void +mu_msg_destroy (MuMsg *self) +{ + if (!self) + return; + + mu_msg_file_destroy (self->_file); + mu_msg_doc_destroy (self->_doc); + + { /* cleanup the strings / lists we stored */ + mu_str_free_list (self->_free_later_str); + g_slist_foreach (self->_free_later_lst, + (GFunc)mu_str_free_list, NULL); + g_slist_free (self->_free_later_lst); + } + + g_slice_free (MuMsg, self); +} + +MuMsg* +mu_msg_ref (MuMsg *self) +{ + g_return_val_if_fail (self, NULL); + + ++self->_refcount; + + return self; +} + +void +mu_msg_unref (MuMsg *self) +{ + g_return_if_fail (self); + g_return_if_fail (self->_refcount >= 1); + + if (--self->_refcount == 0) + mu_msg_destroy (self); +} + +static const gchar* +free_later_str (MuMsg *self, gchar *str) +{ + if (str) + self->_free_later_str = + g_slist_prepend (self->_free_later_str, str); + return str; +} + +static const GSList* +free_later_lst (MuMsg *self, GSList *lst) +{ + if (lst) + self->_free_later_lst = + g_slist_prepend (self->_free_later_lst, lst); + return lst; +} + +/* use this instead of mu_msg_get_path so we don't get into infinite + * regress...*/ +static const char* +get_path (MuMsg *self) +{ + char *val; + gboolean do_free; + + do_free = TRUE; + val = NULL; + + if (self->_doc) + val = mu_msg_doc_get_str_field + (self->_doc, MU_MSG_FIELD_ID_PATH); + + /* not in the cache yet? try to get it from the file backend, + * in case we are using that */ + if (!val && self->_file) + val = mu_msg_file_get_str_field + (self->_file, MU_MSG_FIELD_ID_PATH, &do_free); + + /* shouldn't happen */ + if (!val) + g_warning ("%s: cannot find path", __func__); + + return free_later_str (self, val); +} + +/* for some data, we need to read the message file from disk */ +gboolean +mu_msg_load_msg_file (MuMsg *self, GError **err) +{ + const char *path; + + g_return_val_if_fail (self, FALSE); + + if (self->_file) + return TRUE; /* nothing to do */ + + if (!(path = get_path (self))) { + mu_util_g_set_error (err, MU_ERROR_INTERNAL, + "cannot get path for message"); + return FALSE; + } + + self->_file = mu_msg_file_new (path, NULL, err); + + return (self->_file != NULL); +} + +void +mu_msg_unload_msg_file (MuMsg *msg) +{ + g_return_if_fail (msg); + + mu_msg_file_destroy (msg->_file); + msg->_file = NULL; +} + +static const GSList* +get_str_list_field (MuMsg *self, MuMsgFieldId mfid) +{ + GSList *val; + + val = NULL; + + if (self->_doc && mu_msg_field_xapian_value (mfid)) + val = mu_msg_doc_get_str_list_field (self->_doc, mfid); + else if (mu_msg_field_gmime (mfid)) { + /* if we don't have a file object yet, we need to + * create it from the file on disk */ + if (!mu_msg_load_msg_file (self, NULL)) + return NULL; + val = mu_msg_file_get_str_list_field (self->_file, mfid); + } + + return free_later_lst (self, val); +} + +static const char* +get_str_field (MuMsg *self, MuMsgFieldId mfid) +{ + char *val; + gboolean do_free; + + do_free = TRUE; + val = NULL; + + if (self->_doc && mu_msg_field_xapian_value (mfid)) + val = mu_msg_doc_get_str_field (self->_doc, mfid); + + else if (mu_msg_field_gmime (mfid)) { + /* if we don't have a file object yet, we need to + * create it from the file on disk */ + if (!mu_msg_load_msg_file (self, NULL)) + return NULL; + val = mu_msg_file_get_str_field (self->_file, mfid, &do_free); + } else + val = NULL; + + return do_free ? free_later_str (self, val) : val; +} + +static gint64 +get_num_field (MuMsg *self, MuMsgFieldId mfid) +{ + guint64 val; + + val = -1; + if (self->_doc && mu_msg_field_xapian_value (mfid)) + val = mu_msg_doc_get_num_field (self->_doc, mfid); + else { + /* if we don't have a file object yet, we need to + * create it from the file on disk */ + if (!mu_msg_load_msg_file (self, NULL)) + return -1; + val = mu_msg_file_get_num_field (self->_file, mfid); + } + + return val; +} + +const char* +mu_msg_get_header (MuMsg *self, const char *header) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (header, NULL); + + /* if we don't have a file object yet, we need to + * create it from the file on disk */ + if (!mu_msg_load_msg_file (self, NULL)) + return NULL; + + return free_later_str + (self, mu_msg_file_get_header (self->_file, header)); +} + +time_t +mu_msg_get_timestamp (MuMsg *self) +{ + const char *path; + struct stat statbuf; + + g_return_val_if_fail (self, 0); + + if (self->_file) + return self->_file->_timestamp; + + path = mu_msg_get_path (self); + if (!path || stat (path, &statbuf) < 0) + return 0; + + return statbuf.st_mtime; +} + +const char* +mu_msg_get_path (MuMsg *self) +{ + g_return_val_if_fail (self, NULL); + return get_str_field (self, MU_MSG_FIELD_ID_PATH); +} + +const char* +mu_msg_get_subject (MuMsg *self) +{ + g_return_val_if_fail (self, NULL); + return get_str_field (self, MU_MSG_FIELD_ID_SUBJECT); +} + +const char* +mu_msg_get_msgid (MuMsg *self) +{ + g_return_val_if_fail (self, NULL); + return get_str_field (self, MU_MSG_FIELD_ID_MSGID); +} + +const char* +mu_msg_get_mailing_list (MuMsg *self) +{ + const char *ml; + char *decml; + + g_return_val_if_fail (self, NULL); + + ml = get_str_field (self, MU_MSG_FIELD_ID_MAILING_LIST); + if (!ml) + return NULL; + + decml = g_mime_utils_header_decode_text (NULL, ml); + if (!decml) + return NULL; + + return free_later_str (self, decml); +} + +const char* +mu_msg_get_maildir (MuMsg *self) +{ + g_return_val_if_fail (self, NULL); + return get_str_field (self, MU_MSG_FIELD_ID_MAILDIR); +} + +const char* +mu_msg_get_from (MuMsg *self) +{ + g_return_val_if_fail (self, NULL); + return get_str_field (self, MU_MSG_FIELD_ID_FROM); +} + +const char* +mu_msg_get_to (MuMsg *self) +{ + g_return_val_if_fail (self, NULL); + return get_str_field (self, MU_MSG_FIELD_ID_TO); +} + +const char* +mu_msg_get_cc (MuMsg *self) +{ + g_return_val_if_fail (self, NULL); + return get_str_field (self, MU_MSG_FIELD_ID_CC); +} + +const char* +mu_msg_get_bcc (MuMsg *self) +{ + g_return_val_if_fail (self, NULL); + return get_str_field (self, MU_MSG_FIELD_ID_BCC); +} + +time_t +mu_msg_get_date (MuMsg *self) +{ + g_return_val_if_fail (self, (time_t)-1); + return (time_t)get_num_field (self, MU_MSG_FIELD_ID_DATE); +} + +MuFlags +mu_msg_get_flags (MuMsg *self) +{ + g_return_val_if_fail (self, MU_FLAG_NONE); + return (MuFlags)get_num_field (self, MU_MSG_FIELD_ID_FLAGS); +} + +size_t +mu_msg_get_size (MuMsg *self) +{ + g_return_val_if_fail (self, (size_t)-1); + return (size_t)get_num_field (self, MU_MSG_FIELD_ID_SIZE); +} + +MuMsgPrio +mu_msg_get_prio (MuMsg *self) +{ + g_return_val_if_fail (self, MU_MSG_PRIO_NORMAL); + return (MuMsgPrio)get_num_field (self, MU_MSG_FIELD_ID_PRIO); +} + +struct _BodyData { + GString *gstr; + gboolean want_html; +}; +typedef struct _BodyData BodyData; + +static void +accumulate_body (MuMsg *msg, MuMsgPart *mpart, BodyData *bdata) +{ + char *txt; + GMimePart *mimepart; + gboolean has_err, is_plain, is_html; + + if (!GMIME_IS_PART(mpart->data)) + return; + if (mpart->part_type & MU_MSG_PART_TYPE_ATTACHMENT) + return; + + mimepart = (GMimePart*)mpart->data; + is_html = mpart->part_type & MU_MSG_PART_TYPE_TEXT_HTML; + is_plain = mpart->part_type & MU_MSG_PART_TYPE_TEXT_PLAIN; + + txt = NULL; + has_err = TRUE; + if ((bdata->want_html && is_html) || (!bdata->want_html && is_plain)) + txt = mu_msg_mime_part_to_string (mimepart, &has_err); + + if (!has_err && txt) + bdata->gstr = g_string_append (bdata->gstr, txt); + + g_free (txt); +} + +static char* +get_body (MuMsg *self, MuMsgOptions opts, gboolean want_html) +{ + BodyData bdata; + + bdata.want_html = want_html; + bdata.gstr = g_string_sized_new (4096); + + /* wipe out some irrelevant options */ + opts &= ~MU_MSG_OPTION_VERIFY; + opts &= ~MU_MSG_OPTION_EXTRACT_IMAGES; + + mu_msg_part_foreach (self, opts, + (MuMsgPartForeachFunc)accumulate_body, + &bdata); + + if (bdata.gstr->len == 0) { + g_string_free (bdata.gstr, TRUE); + return NULL; + } else + return g_string_free (bdata.gstr, FALSE); +} + +typedef struct { + GMimeContentType *ctype; + gboolean want_html; +} ContentTypeData; + +static void +find_content_type (MuMsg *msg, MuMsgPart *mpart, ContentTypeData *cdata) +{ + GMimePart *wanted; + + if (!GMIME_IS_PART(mpart->data)) + return; + + /* text-like attachments are included when in text-mode */ + + if (!cdata->want_html && + (mpart->part_type & MU_MSG_PART_TYPE_TEXT_PLAIN)) + wanted = mpart->data; + else if (!(mpart->part_type & MU_MSG_PART_TYPE_ATTACHMENT) && + cdata->want_html && + (mpart->part_type & MU_MSG_PART_TYPE_TEXT_HTML)) + wanted = mpart->data; + else + wanted = NULL; + + if (wanted) + cdata->ctype = g_mime_object_get_content_type ( + GMIME_OBJECT(wanted)); +} + +static const GSList* +get_content_type_parameters (MuMsg *self, MuMsgOptions opts, gboolean want_html) +{ + ContentTypeData cdata; + + cdata.want_html = want_html; + cdata.ctype = NULL; + + /* wipe out some irrelevant options */ + opts &= ~MU_MSG_OPTION_VERIFY; + opts &= ~MU_MSG_OPTION_EXTRACT_IMAGES; + + mu_msg_part_foreach (self, opts, + (MuMsgPartForeachFunc)find_content_type, + &cdata); + + if (cdata.ctype) { + + GSList *gslist; + GMimeParamList *paramlist; + const GMimeParam *param; + int i, len; + + gslist = NULL; + paramlist = g_mime_content_type_get_parameters (cdata.ctype); + len = g_mime_param_list_length (paramlist); + + for (i = 0; i < len; ++i) { + param = g_mime_param_list_get_parameter_at (paramlist, i); + gslist = g_slist_prepend (gslist, g_strdup (param->name)); + gslist = g_slist_prepend (gslist, g_strdup (param->value)); + } + + return free_later_lst (self, g_slist_reverse (gslist)); + } + return NULL; +} + +const GSList* +mu_msg_get_body_text_content_type_parameters (MuMsg *self, MuMsgOptions opts) +{ + g_return_val_if_fail (self, NULL); + return get_content_type_parameters(self, opts, FALSE); +} + +const char* +mu_msg_get_body_html (MuMsg *self, MuMsgOptions opts) +{ + g_return_val_if_fail (self, NULL); + return free_later_str (self, get_body (self, opts, TRUE)); +} + +const char* +mu_msg_get_body_text (MuMsg *self, MuMsgOptions opts) +{ + g_return_val_if_fail (self, NULL); + return free_later_str (self, get_body (self, opts, FALSE)); +} + +const GSList* +mu_msg_get_references (MuMsg *self) +{ + g_return_val_if_fail (self, NULL); + return get_str_list_field (self, MU_MSG_FIELD_ID_REFS); +} + +const GSList* +mu_msg_get_tags (MuMsg *self) +{ + g_return_val_if_fail (self, NULL); + return get_str_list_field (self, MU_MSG_FIELD_ID_TAGS); +} + +const char* +mu_msg_get_field_string (MuMsg *self, MuMsgFieldId mfid) +{ + g_return_val_if_fail (self, NULL); + return get_str_field (self, mfid); +} + +const GSList* +mu_msg_get_field_string_list (MuMsg *self, MuMsgFieldId mfid) +{ + g_return_val_if_fail (self, NULL); + return get_str_list_field (self, mfid); +} + +gint64 +mu_msg_get_field_numeric (MuMsg *self, MuMsgFieldId mfid) +{ + g_return_val_if_fail (self, -1); + return get_num_field (self, mfid); +} + +static gboolean +fill_contact (MuMsgContact *self, InternetAddress *addr, + MuMsgContactType ctype) +{ + if (!addr) + return FALSE; + + self->full_address = internet_address_to_string ( + addr, NULL, FALSE); + + self->name = internet_address_get_name (addr); + if (mu_str_is_empty (self->name)) { + self->name = NULL; + } + + self->type = ctype; + + /* we only support internet mailbox addresses; if we don't + * check, g_mime hits an assert + */ + if (INTERNET_ADDRESS_IS_MAILBOX(addr)) + self->email= internet_address_mailbox_get_addr + (INTERNET_ADDRESS_MAILBOX(addr)); + else + self->email = NULL; + + /* if there's no address, just a name, it's probably a local + * address (without @) */ + if (self->name && !self->email) + self->email = self->name; + + /* note, the address could be NULL e.g. when the recipient is something + * like 'Undisclosed recipients' + */ + return self->email != NULL; +} + +static void +address_list_foreach (InternetAddressList *addrlist, MuMsgContactType ctype, + MuMsgContactForeachFunc func, gpointer user_data) +{ + int i, len; + + if (!addrlist) + return; + + len = internet_address_list_length(addrlist); + + for (i = 0; i != len; ++i) { + MuMsgContact contact; + gboolean keep_going; + + if (!fill_contact(&contact, + internet_address_list_get_address (addrlist, i), + ctype)) + continue; + + keep_going = func(&contact, user_data); + g_free ((char*)contact.full_address); + + if (!keep_going) + break; + } +} + +static void +addresses_foreach (const char* addrs, MuMsgContactType ctype, + MuMsgContactForeachFunc func, gpointer user_data) +{ + InternetAddressList *addrlist; + + if (!addrs) + return; + + addrlist = internet_address_list_parse (NULL, addrs); + if (addrlist) { + address_list_foreach (addrlist, ctype, func, user_data); + g_object_unref (addrlist); + } +} + +static void +msg_contact_foreach_file (MuMsg *msg, MuMsgContactForeachFunc func, + gpointer user_data) +{ + int i; + struct { + GMimeAddressType _gmime_type; + MuMsgContactType _type; + } ctypes[] = { + {GMIME_ADDRESS_TYPE_FROM, MU_MSG_CONTACT_TYPE_FROM}, + {GMIME_ADDRESS_TYPE_REPLY_TO, MU_MSG_CONTACT_TYPE_REPLY_TO}, + {GMIME_ADDRESS_TYPE_TO, MU_MSG_CONTACT_TYPE_TO}, + {GMIME_ADDRESS_TYPE_CC, MU_MSG_CONTACT_TYPE_CC}, + {GMIME_ADDRESS_TYPE_BCC, MU_MSG_CONTACT_TYPE_BCC}, + }; + + for (i = 0; i != G_N_ELEMENTS(ctypes); ++i) { + InternetAddressList *addrlist; + addrlist = g_mime_message_get_addresses (msg->_file->_mime_msg, + ctypes[i]._gmime_type); + address_list_foreach (addrlist, ctypes[i]._type, func, user_data); + } +} + +static void +msg_contact_foreach_doc (MuMsg *msg, MuMsgContactForeachFunc func, + gpointer user_data) +{ + addresses_foreach (mu_msg_get_from (msg), + MU_MSG_CONTACT_TYPE_FROM, func, user_data); + addresses_foreach (mu_msg_get_to (msg), + MU_MSG_CONTACT_TYPE_TO, func, user_data); + addresses_foreach (mu_msg_get_cc (msg), + MU_MSG_CONTACT_TYPE_CC, func, user_data); + addresses_foreach (mu_msg_get_bcc (msg), + MU_MSG_CONTACT_TYPE_BCC, func, user_data); +} + +void +mu_msg_contact_foreach (MuMsg *msg, MuMsgContactForeachFunc func, + gpointer user_data) +{ + g_return_if_fail (msg); + g_return_if_fail (func); + + if (msg->_file) + msg_contact_foreach_file (msg, func, user_data); + else if (msg->_doc) + msg_contact_foreach_doc (msg, func, user_data); + else + g_return_if_reached (); +} + +static int +cmp_str (const char *s1, const char *s2) +{ + if (s1 == s2) + return 0; + else if (!s1) + return -1; + else if (!s2) + return 1; + + /* optimization 1: ascii */ + if (isascii(s1[0]) && isascii(s2[0])) { + int diff; + diff = tolower(s1[0]) - tolower(s2[0]); + if (diff != 0) + return diff; + } + + /* utf 8 */ + { + char *u1, *u2; + int diff; + + u1 = g_utf8_strdown (s1, -1); + u2 = g_utf8_strdown (s2, -1); + + diff = g_utf8_collate (u1, u2); + + g_free (u1); + g_free (u2); + + return diff; + } +} + +static int +cmp_subject (const char* s1, const char *s2) +{ + if (s1 == s2) + return 0; + else if (!s1) + return -1; + else if (!s2) + return 1; + + return cmp_str ( + mu_str_subject_normalize (s1), + mu_str_subject_normalize (s2)); +} + +int +mu_msg_cmp (MuMsg *m1, MuMsg *m2, MuMsgFieldId mfid) +{ + g_return_val_if_fail (m1, 0); + g_return_val_if_fail (m2, 0); + g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), 0); + + /* even though date is a numeric field, we can sort it by its + * string repr. in the database, which is much faster */ + if (mfid == MU_MSG_FIELD_ID_DATE || + mu_msg_field_is_string (mfid)) + return cmp_str (get_str_field (m1, mfid), + get_str_field (m2, mfid)); + + if (mfid == MU_MSG_FIELD_ID_SUBJECT) + return cmp_subject (get_str_field (m1, mfid), + get_str_field (m2, mfid)); + + /* TODO: note, we cast (potentially > MAXINT to int) */ + if (mu_msg_field_is_numeric (mfid)) + return get_num_field(m1, mfid) - get_num_field(m2, mfid); + + return 0; /* TODO: handle lists */ +} + +gboolean +mu_msg_is_readable (MuMsg *self) +{ + g_return_val_if_fail (self, FALSE); + + return access (mu_msg_get_path (self), R_OK) == 0 ? TRUE : FALSE; +} + +/* we need do to determine the + * /home/foo/Maildir/bar + * from the /bar + * that we got + */ +static char* +get_target_mdir (MuMsg *msg, const char *target_maildir, GError **err) +{ + char *rootmaildir, *rv; + const char *maildir; + gboolean not_top_level; + + /* maildir is the maildir stored in the message, e.g. '/foo' */ + maildir = mu_msg_get_maildir(msg); + if (!maildir) { + mu_util_g_set_error (err, MU_ERROR_GMIME, + "message without maildir"); + return NULL; + } + + /* the 'rootmaildir' is the filesystem path from root to + * maildir, ie. /home/user/Maildir/foo */ + rootmaildir = mu_maildir_get_maildir_from_path (mu_msg_get_path(msg)); + if (!rootmaildir) { + mu_util_g_set_error (err, MU_ERROR_GMIME, + "cannot determine maildir"); + return NULL; + } + + /* we do a sanity check: verify that that maildir is a suffix of + * rootmaildir;*/ + not_top_level = TRUE; + if (!g_str_has_suffix (rootmaildir, maildir) && + /* special case for the top-level '/' maildir, and + * remember not_top_level */ + (not_top_level = (g_strcmp0 (maildir, "/") != 0))) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, + "path is '%s', but maildir is '%s' ('%s')", + rootmaildir, mu_msg_get_maildir(msg), + mu_msg_get_path (msg)); + g_free (rootmaildir); + return NULL; + } + + /* if we're not at the top-level, remove the final '/' from + * the rootmaildir */ + if (not_top_level) + rootmaildir[strlen(rootmaildir) - + strlen (mu_msg_get_maildir(msg))] = '\0'; + + rv = g_strconcat (rootmaildir, target_maildir, NULL); + g_free (rootmaildir); + + return rv; +} + +/* + * move a msg to another maildir, trying to maintain 'integrity', + * ie. msg in 'new/' will go to new/, one in cur/ goes to cur/. be + * super-paranoid here... + */ +gboolean +mu_msg_move_to_maildir (MuMsg *self, const char *maildir, + MuFlags flags, gboolean ignore_dups, + gboolean new_name, GError **err) +{ + char *newfullpath; + char *targetmdir; + + g_return_val_if_fail (self, FALSE); + g_return_val_if_fail (maildir, FALSE); /* i.e. "/inbox" */ + + /* targetmdir is the full path to maildir, i.e., + * /home/foo/Maildir/inbox */ + targetmdir = get_target_mdir (self, maildir, err); + if (!targetmdir) + return FALSE; + + newfullpath = mu_maildir_move_message (mu_msg_get_path (self), + targetmdir, flags, + ignore_dups, new_name, + err); + if (!newfullpath) { + g_free (targetmdir); + return FALSE; + } + + /* clear the old backends */ + mu_msg_doc_destroy (self->_doc); + self->_doc = NULL; + + mu_msg_file_destroy (self->_file); + + /* and create a new one */ + self->_file = mu_msg_file_new (newfullpath, maildir, err); + g_free (targetmdir); + g_free (newfullpath); + + return self->_file ? TRUE : FALSE; +} + +/* + * Rename a message-file, keeping the same flags. This is useful for tricking + * some 3rd party progs such as mbsync + */ +gboolean +mu_msg_tickle (MuMsg *self, GError **err) +{ + g_return_val_if_fail (self, FALSE); + + return mu_msg_move_to_maildir (self, + mu_msg_get_maildir (self), + mu_msg_get_flags (self), + FALSE, TRUE, err); +} + +const char* +mu_str_flags_s (MuFlags flags) +{ + return mu_flags_to_str_s (flags, MU_FLAG_TYPE_ANY); +} + +char* +mu_str_flags (MuFlags flags) +{ + return g_strdup (mu_str_flags_s(flags)); +} + +static void +cleanup_contact (char *contact) +{ + char *c, *c2; + + /* replace "'<> with space */ + for (c2 = contact; *c2; ++c2) + if (*c2 == '"' || *c2 == '\'' || *c2 == '<' || *c2 == '>') + *c2 = ' '; + + /* remove everything between '()' if it's after the 5th pos; + * good to cleanup corporate contact address spam... */ + c = g_strstr_len (contact, -1, "("); + if (c && c - contact > 5) + *c = '\0'; + + g_strstrip (contact); +} + + +/* this is still somewhat simplistic... */ +const char* +mu_str_display_contact_s (const char *str) +{ + static gchar contact[255]; + gchar *c, *c2; + + str = str ? str : ""; + g_strlcpy (contact, str, sizeof(contact)); + + /* we check for '<', so we can strip out the address stuff in + * e.g. 'Hello World <hello@world.xx>, but only if there is + * something alphanumeric before the < + */ + c = g_strstr_len (contact, -1, "<"); + if (c != NULL) { + for (c2 = contact; c2 < c && !(isalnum(*c2)); ++c2); + if (c2 != c) /* apparently, there was something, + * so we can remove the <... part*/ + *c = '\0'; + } + + cleanup_contact (contact); + + return contact; +} + +char* +mu_str_display_contact (const char *str) +{ + g_return_val_if_fail (str, NULL); + + return g_strdup (mu_str_display_contact_s (str)); +} diff --git a/lib/mu-msg.h b/lib/mu-msg.h new file mode 100644 index 0000000..e4842aa --- /dev/null +++ b/lib/mu-msg.h @@ -0,0 +1,654 @@ +/* -*- mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +** +** Copyright (C) 2010-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_MSG_H__ +#define __MU_MSG_H__ + +#include <mu-flags.h> +#include <mu-msg-fields.h> +#include <mu-msg-prio.h> +#include <utils/mu-util.h> + +G_BEGIN_DECLS + +struct _MuMsg; +typedef struct _MuMsg MuMsg; + +/* options for various functions */ +enum _MuMsgOptions { + MU_MSG_OPTION_NONE = 0, +/* 1 << 0 is still free! */ + + /* for -> sexp conversion */ + MU_MSG_OPTION_HEADERS_ONLY = 1 << 1, + MU_MSG_OPTION_EXTRACT_IMAGES = 1 << 2, + + /* below options are for checking signatures; only effective + * if mu was built with crypto support */ + MU_MSG_OPTION_VERIFY = 1 << 4, + MU_MSG_OPTION_AUTO_RETRIEVE = 1 << 5, + MU_MSG_OPTION_USE_AGENT = 1 << 6, + /* MU_MSG_OPTION_USE_PKCS7 = 1 << 7, /\* gpg is the default *\/ */ + + /* get password from console if needed */ + MU_MSG_OPTION_CONSOLE_PASSWORD = 1 << 7, + + MU_MSG_OPTION_DECRYPT = 1 << 8, + + /* misc */ + MU_MSG_OPTION_OVERWRITE = 1 << 9, + MU_MSG_OPTION_USE_EXISTING = 1 << 10, + + /* recurse into submessages */ + MU_MSG_OPTION_RECURSE_RFC822 = 1 << 11 + +}; +typedef enum _MuMsgOptions MuMsgOptions; + + + +/** + * create a new MuMsg* instance which parses a message and provides + * read access to its properties; call mu_msg_unref when done with it. + * + * @param path full path to an email message file + * @param mdir the maildir for this message; ie, if the path is + * ~/Maildir/foo/bar/cur/msg, the maildir would be foo/bar; you can + * pass NULL for this parameter, in which case some maildir-specific + * information is not available. + * @param err receive error information (MU_ERROR_FILE or + * MU_ERROR_GMIME), or NULL. There will only be err info if the + * function returns NULL + * + * @return a new MuMsg instance or NULL in case of error; call + * mu_msg_unref when done with this message + */ +MuMsg *mu_msg_new_from_file (const char* filepath, const char *maildir, + GError **err) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + + +/** + * create a new MuMsg* instance based on a Xapian::Document + * + * @param store a MuStore ptr + * @param doc a ptr to a Xapian::Document (but cast to XapianDocument, + * because this is C not C++). MuMsg takes _ownership_ of this pointer; + * don't touch it afterwards + * @param err receive error information, or NULL. There + * will only be err info if the function returns NULL + * + * @return a new MuMsg instance or NULL in case of error; call + * mu_msg_unref when done with this message + */ +MuMsg *mu_msg_new_from_doc (XapianDocument* doc, GError **err) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + + +/** + * if we don't have a message file yet (because this message is + * database-backed), load it. + * + * @param msg a MuMsg + * @param err receives error information + * + * @return TRUE if this succeeded, FALSE in case of error + */ +gboolean mu_msg_load_msg_file (MuMsg *msg, GError **err); + + +/** + * close the file-backend, if any; this function is for the use case + * where you have a large amount of messages where you need some + * file-backed field (body or attachments). If you don't close the + * file-backend after retrieving the desired field, you'd quickly run + * out of file descriptors. If this message does not have a + * file-backend, do nothing. + * + * @param msg a message object + */ +void mu_msg_unload_msg_file (MuMsg *msg); + +/** + * increase the reference count for this message + * + * @param msg a message + * + * @return the message with its reference count increased, or NULL in + * case of error. + */ +MuMsg *mu_msg_ref (MuMsg *msg); + +/** + * decrease the reference count for this message. if the reference + * count reaches 0, the message will be destroyed. + * + * @param msg a message + */ +void mu_msg_unref (MuMsg *msg); + +/** + * cache the values from the backend (file or db), so we don't the + * backend anymore + * + * @param self a message + */ +void mu_msg_cache_values (MuMsg *self); + + +/** + * get the plain text body of this message + * + * @param msg a valid MuMsg* instance + * @param opts options for getting the body + * + * @return the plain text body or NULL in case of error or if there is no + * such body. the returned string should *not* be modified or freed. + * The returned data is in UTF8 or NULL. + */ +const char* mu_msg_get_body_text (MuMsg *msg, MuMsgOptions opts); + + +/** + * get the content type parameters for the text body part + * + * @param msg a valid MuMsg* instance + * @param opts options for getting the body + * + * @return the value of the requested body part content type parameter, or + * NULL in case of error or if there is no such body. the returned string + * should *not* be modified or freed. The returned data is in UTF8 or NULL. + */ +const GSList* mu_msg_get_body_text_content_type_parameters (MuMsg *self, MuMsgOptions opts); + + +/** + * get the html body of this message + * + * @param msg a valid MuMsg* instance + * @param opts options for getting the body + * + * @return the html body or NULL in case of error or if there is no + * such body. the returned string should *not* be modified or freed. + */ +const char* mu_msg_get_body_html (MuMsg *msgMu, MuMsgOptions opts); + +/** + * get the sender (From:) of this message + * + * @param msg a valid MuMsg* instance + * + * @return the sender of this Message or NULL in case of error or if there + * is no sender. the returned string should *not* be modified or freed. + */ +const char* mu_msg_get_from (MuMsg *msg); + + +/** + * get the recipients (To:) of this message + * + * @param msg a valid MuMsg* instance + * + * @return the sender of this Message or NULL in case of error or if there + * are no recipients. the returned string should *not* be modified or freed. + */ +const char* mu_msg_get_to (MuMsg *msg); + + +/** + * get the carbon-copy recipients (Cc:) of this message + * + * @param msg a valid MuMsg* instance + * + * @return the Cc: recipients of this Message or NULL in case of error or if + * there are no such recipients. the returned string should *not* be modified + * or freed. + */ +const char* mu_msg_get_cc (MuMsg *msg); + +/** + * get the blind carbon-copy recipients (Bcc:) of this message; this + * field usually only appears in outgoing messages + * + * @param msg a valid MuMsg* instance + * + * @return the Bcc: recipients of this Message or NULL in case of + * error or if there are no such recipients. the returned string + * should *not* be modified or freed. + */ +const char* mu_msg_get_bcc (MuMsg *msg); + +/** + * get the file system path of this message + * + * @param msg a valid MuMsg* instance + * + * @return the path of this Message or NULL in case of error. + * the returned string should *not* be modified or freed. + */ +const char* mu_msg_get_path (MuMsg *msg); + + +/** + * get the maildir this message lives in; ie, if the path is + * ~/Maildir/foo/bar/cur/msg, the maildir would be foo/bar + * + * @param msg a valid MuMsg* instance + * + * @return the maildir requested or NULL in case of error. The returned + * string should *not* be modified or freed. + */ +const char* mu_msg_get_maildir (MuMsg *msg); + + +/** + * get the subject of this message + * + * @param msg a valid MuMsg* instance + * + * @return the subject of this Message or NULL in case of error or if there + * is no subject. the returned string should *not* be modified or freed. + */ +const char* mu_msg_get_subject (MuMsg *msg); + +/** + * get the Message-Id of this message + * + * @param msg a valid MuMsg* instance + * + * @return the Message-Id of this message (without the enclosing <>), + * or a fake message-id for messages that don't have them, or NULL in + * case of error. + */ +const char* mu_msg_get_msgid (MuMsg *msg); + + +/** + * get the mailing list for a message, i.e. the mailing-list + * identifier in the List-Id header. + * + * @param msg a valid MuMsg* instance + * + * @return the mailing list id for this message (without the enclosing <>) + * or NULL in case of error or if there is none. the returned string + * should *not* be modified or freed. + */ +const char* mu_msg_get_mailing_list (MuMsg *msg); + + +/** + * get the message date/time (the Date: field) as time_t, using UTC + * + * @param msg a valid MuMsg* instance + * + * @return message date/time or 0 in case of error or if there + * is no such header. + */ +time_t mu_msg_get_date (MuMsg *msg); + +/** + * get the flags for this message + * + * @param msg valid MuMsg* instance + * + * @return the file/content flags as logically OR'd #MuMsgFlags or 0 + * if there are none. Non-standard flags are ignored. + */ +MuFlags mu_msg_get_flags (MuMsg *msg); + + +/** + * get the file size in bytes of this message + * + * @param msg a valid MuMsg* instance + * + * @return the filesize + */ +size_t mu_msg_get_size (MuMsg *msg); + + +/** + * get some field value as string + * + * @param msg a valid MuMsg instance + * @param field the field to retrieve; it must be a string-typed field + * + * @return a string that should not be freed + */ +const char* mu_msg_get_field_string (MuMsg *msg, MuMsgFieldId mfid); + + +/** + * get some field value as string-list + * + * @param msg a valid MuMsg instance + * @param field the field to retrieve; it must be a string-list-typed field + * + * @return a list that should not be freed + */ +const GSList* mu_msg_get_field_string_list (MuMsg *self, MuMsgFieldId mfid); + +/** + * get some field value as string + * + * @param msg a valid MuMsg instance + * @param field the field to retrieve; it must be a numeric field + * + * @return a string that should not be freed + */ +gint64 mu_msg_get_field_numeric (MuMsg *msg, MuMsgFieldId mfid); + +/** + * get the message priority for this message (MU_MSG_PRIO_LOW, + * MU_MSG_PRIO_NORMAL or MU_MSG_PRIO_HIGH) the X-Priority, + * X-MSMailPriority, Importance and Precedence header are checked, in + * that order. if no known or explicit priority is set, + * MU_MSG_PRIO_NORMAL is assumed + * + * @param msg a valid MuMsg* instance + * + * @return the message priority (!= 0) or 0 in case of error + */ +MuMsgPrio mu_msg_get_prio (MuMsg *msg); + +/** + * get the timestamp (mtime) for the file containing this message + * + * @param msg a valid MuMsg* instance + * + * @return the timestamp or 0 in case of error + */ +time_t mu_msg_get_timestamp (MuMsg *msg); + + +/** + * get a specific header from the message. This value will _not_ be + * cached + * + * @param self a MuMsg instance + * @param header a specific header (like 'X-Mailer' or 'Organization') + * + * @return a header string which is valid as long as this MuMsg is + */ +const char* mu_msg_get_header (MuMsg *self, const char *header); + + +/** + * get the list of references (consisting of both the References and + * In-Reply-To fields), with the oldest first and the direct parent as + * the last one. Note, any reference (message-id) will appear at most + * once, duplicates are filtered out. + * + * @param msg a valid MuMsg + * + * @return a list with the references for this msg. Don't modify/free + */ +const GSList* mu_msg_get_references (MuMsg *msg); + +/** + * get the list of tags (ie., X-Label) + * + * @param msg a valid MuMsg + * + * @return a list with the tags for this msg. Don't modify/free + */ +const GSList* mu_msg_get_tags (MuMsg *self); + + +/** + * compare two messages for sorting + * + * @param m1 a message + * @param m2 another message + * @param mfid the message to use for the comparison + * + * @return negative if m1 is smaller, positive if m1 is smaller, 0 if + * they are equal + */ +int mu_msg_cmp (MuMsg *m1, MuMsg *m2, MuMsgFieldId mfid); + + +/** + * check whether there there's a readable file behind this message + * + * @param self a MuMsg* + * + * @return TRUE if the message file is readable, FALSE otherwise + */ +gboolean mu_msg_is_readable (MuMsg *self); + + +struct _MuMsgIterThreadInfo; + + +/** + * convert the msg to a Lisp symbolic expression (for further processing in + * e.g. emacs) + * + * @param msg a valid message + * @param docid the docid for this message, or 0 + * @param ti thread info for the current message, or NULL + * @param opts, bitwise OR'ed; + * - MU_MSG_OPTION_HEADERS_ONLY: only include message fields which can be + * obtained from the database (this is much faster if the MuMsg is + * database-backed, so no file needs to be opened) + * - MU_MSG_OPTION_EXTRACT_IMAGES: extract image attachments as temporary + * files and include links to those in the sexp + * and for message parts: + * MU_MSG_OPTION_CHECK_SIGNATURES: check signatures + * MU_MSG_OPTION_AUTO_RETRIEVE_KEY: attempt to retrieve keys online + * MU_MSG_OPTION_USE_AGENT: attempt to use GPG-agent + * MU_MSG_OPTION_USE_PKCS7: attempt to use PKCS (instead of gpg) + * + * @return a string with the sexp (free with g_free) or NULL in case of error + */ +char* mu_msg_to_sexp (MuMsg *msg, unsigned docid, + const struct _MuMsgIterThreadInfo *ti, + MuMsgOptions ops) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +#ifdef HAVE_JSON_GLIB + +struct _JsonNode; /* forward declaration */ + +/** + * convert the msg to json + * + * @param msg a valid message + * @param docid the docid for this message, or 0 + * @param ti thread info for the current message, or NULL + * @param opts, bitwise OR'ed; + * - MU_MSG_OPTION_HEADERS_ONLY: only include message fields which can be + * obtained from the database (this is much faster if the MuMsg is + * database-backed, so no file needs to be opened) + * - MU_MSG_OPTION_EXTRACT_IMAGES: extract image attachments as temporary + * files and include links to those in the sexp + * + * @return a string with the sexp (free with g_free) or NULL in case of error + */ +struct _JsonNode* mu_msg_to_json (MuMsg *msg, unsigned docid, + const struct _MuMsgIterThreadInfo *ti, + MuMsgOptions ops) G_GNUC_WARN_UNUSED_RESULT; +#endif /*HAVE_JSON_GLIB*/ + +/** + * move a message to another maildir; note that this does _not_ update + * the database + * + * @param msg a message with an existing file system path in an actual + * maildir + * @param maildir the subdir where the message should go, relative to + * rootmaildir. e.g. "/archive" + * @param flags to set for the target (influences the filename, path) + * @param silently ignore the src=target case (return TRUE) + * @param new_name whether to create a new unique name, or keep the + * old one + * @param err (may be NULL) may contain error information; note if the + * function return FALSE, err is not set for all error condition + * (ie. not for parameter error + * + * @return TRUE if it worked, FALSE otherwise + */ +gboolean mu_msg_move_to_maildir (MuMsg *msg, const char *maildir, + MuFlags flags, gboolean ignore_dups, + gboolean new_name, + GError **err); + +/** + * Tickle a message -- ie., rename a message to some new semi-random name,while + * maintaining the maildir and flags. This can be useful when dealing with + * third-party tools such as mbsync that depend on changed filenames. + * + * @param msg a message with an existing file system path in an actual + * maildir + * @param err (may be NULL) may contain error information; note if the + * function return FALSE, err is not set for all error condition + * (ie. not for parameter error + * + * @return TRUE if it worked, FALSE otherwise + */ +gboolean mu_msg_tickle (MuMsg *msg, GError **err); + + +enum _MuMsgContactType { /* Reply-To:? */ + MU_MSG_CONTACT_TYPE_TO = 0, + MU_MSG_CONTACT_TYPE_FROM, + MU_MSG_CONTACT_TYPE_CC, + MU_MSG_CONTACT_TYPE_BCC, + MU_MSG_CONTACT_TYPE_REPLY_TO, + + MU_MSG_CONTACT_TYPE_NUM +}; +typedef guint MuMsgContactType; + +/* not a 'real' contact type */ +#define MU_MSG_CONTACT_TYPE_ALL (MU_MSG_CONTACT_TYPE_NUM + 1) + +#define mu_msg_contact_type_is_valid(MCT)\ + ((MCT) < MU_MSG_CONTACT_TYPE_NUM) + +struct _MuMsgContact { + const char *name; /**< Foo Bar */ + const char *email; /**< foo@bar.cuux */ + const char *full_address; /**< Foo Bar <foo@bar.cuux> */ + MuMsgContactType type; /**< MU_MSG_CONTACT_TYPE_{ TO, + CC, BCC, FROM, REPLY_TO} */ +}; +typedef struct _MuMsgContact MuMsgContact; + + +/** + * macro to get the name of a contact + * + * @param ct a MuMsgContact + * + * @return the name + */ +#define mu_msg_contact_name(ct) ((ct)->name) + +/** + * macro to get the email address of a contact + * + * @param ct a MuMsgContact + * + * @return the address + */ +#define mu_msg_contact_email(ct) ((ct)->email) + +/** + * macro to get the contact type + * + * @param ct a MuMsgContact + * + * @return the contact type + */ +#define mu_msg_contact_type(ct) ((ct)->type) + + +/** + * callback function + * + * @param contact + * @param user_data a user provided data pointer + * + * @return TRUE if we should continue the foreach, FALSE otherwise + */ +typedef gboolean (*MuMsgContactForeachFunc) (MuMsgContact* contact, + gpointer user_data); + +/** + * call a function for each of the contacts in a message; the order is: + * from to cc bcc (of each there are zero or more) + * + * @param msg a valid MuMsgGMime* instance + * @param func a callback function to call for each contact; when + * the callback does not return TRUE, it won't be called again + * @param user_data a user-provide pointer that will be passed to the callback + * + */ +void mu_msg_contact_foreach (MuMsg *msg, MuMsgContactForeachFunc func, + gpointer user_data); + + + +/** + * create a 'display contact' from an email header To/Cc/Bcc/From-type address + * ie., turn + * "Foo Bar" <foo@bar.com> + * into + * Foo Bar + * Note that this is based on some simple heuristics. Max length is 255 bytes. + * + * mu_str_display_contact_s returns a statically allocated + * buffer (ie, non-reentrant), while mu_str_display_contact + * returns a newly allocated string that you must free with g_free + * when done with it. + * + * @param str a 'contact str' (ie., what is in the To/Cc/Bcc/From + * fields), or NULL + * + * @return a newly allocated string with a display contact + */ +const char* mu_str_display_contact_s (const char *str) G_GNUC_CONST; +char *mu_str_display_contact (const char *str) G_GNUC_WARN_UNUSED_RESULT; + +/** + * get a display string for a given set of flags, OR'ed in + * @param flags; one character per flag: + * D=draft,F=flagged,N=new,P=passed,R=replied,S=seen,T=trashed + * a=has-attachment,s=signed, x=encrypted + * + * mu_str_file_flags_s returns a ptr to a static buffer, + * while mu_str_file_flags returns dynamically allocated + * memory that must be freed after use. + * + * @param flags file flags + * + * @return a string representation of the flags; see above + * for what to do with it + */ +const char* mu_str_flags_s (MuFlags flags) G_GNUC_CONST; +char* mu_str_flags (MuFlags flags) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + + +G_END_DECLS + +#endif /*__MU_MSG_H__*/ diff --git a/lib/mu-query.cc b/lib/mu-query.cc new file mode 100644 index 0000000..cafb3eb --- /dev/null +++ b/lib/mu-query.cc @@ -0,0 +1,524 @@ +/* +** Copyright (C) 2008-2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include <stdexcept> +#include <string> +#include <cctype> +#include <cstring> +#include <sstream> + +#include <stdlib.h> +#include <xapian.h> +#include <glib/gstdio.h> + +#include "mu-query.h" +#include "mu-msg-fields.h" + +#include "mu-msg-iter.h" + +#include "utils/mu-str.h" +#include "utils/mu-date.h" +#include <utils/mu-utils.hh> + +#include <query/mu-proc-iface.hh> +#include <query/mu-xapian.hh> + +using namespace Mu; + +struct MuProc: public Mu::ProcIface { + + MuProc (const Xapian::Database& db): db_{db} {} + + static MuMsgFieldId field_id (const std::string& field) { + + if (field.empty()) + return MU_MSG_FIELD_ID_NONE; + + MuMsgFieldId id = mu_msg_field_id_from_name (field.c_str(), FALSE); + if (id != MU_MSG_FIELD_ID_NONE) + return id; + else if (field.length() == 1) + return mu_msg_field_id_from_shortcut (field[0], FALSE); + else + return MU_MSG_FIELD_ID_NONE; + } + + std::string + process_value (const std::string& field, + const std::string& value) const override { + const auto id = field_id (field); + if (id == MU_MSG_FIELD_ID_NONE) + return value; + switch(id) { + case MU_MSG_FIELD_ID_PRIO: { + if (!value.empty()) + return std::string(1, value[0]); + } break; + + case MU_MSG_FIELD_ID_FLAGS: { + const auto flag = mu_flag_char_from_name (value.c_str()); + if (flag) + return std::string(1, tolower(flag)); + } break; + + default: + break; + } + + return value; // XXX prio/flags, etc. alias + } + + void add_field (std::vector<FieldInfo>& fields, MuMsgFieldId id) const { + + const auto shortcut = mu_msg_field_shortcut(id); + if (!shortcut) + return; // can't be searched + + const auto name = mu_msg_field_name (id); + const auto pfx = mu_msg_field_xapian_prefix (id); + + if (!name || !pfx) + return; + + fields.push_back ({{name}, {pfx}, + (bool)mu_msg_field_xapian_index(id), + id}); + } + + std::vector<FieldInfo> + process_field (const std::string& field) const override { + + std::vector<FieldInfo> fields; + + if (field == "contact" || field == "recip") { // multi fields + add_field (fields, MU_MSG_FIELD_ID_TO); + add_field (fields, MU_MSG_FIELD_ID_CC); + add_field (fields, MU_MSG_FIELD_ID_BCC); + if (field == "contact") + add_field (fields, MU_MSG_FIELD_ID_FROM); + } else if (field == "") { + add_field (fields, MU_MSG_FIELD_ID_TO); + add_field (fields, MU_MSG_FIELD_ID_CC); + add_field (fields, MU_MSG_FIELD_ID_BCC); + add_field (fields, MU_MSG_FIELD_ID_FROM); + add_field (fields, MU_MSG_FIELD_ID_SUBJECT); + add_field (fields, MU_MSG_FIELD_ID_BODY_TEXT); + } else { + const auto id = field_id (field.c_str()); + if (id != MU_MSG_FIELD_ID_NONE) + add_field (fields, id); + } + + return fields; + } + + bool is_range_field (const std::string& field) const override { + const auto id = field_id (field.c_str()); + if (id == MU_MSG_FIELD_ID_NONE) + return false; + else + return mu_msg_field_is_range_field (id); + } + + Range process_range (const std::string& field, const std::string& lower, + const std::string& upper) const override { + + const auto id = field_id (field.c_str()); + if (id == MU_MSG_FIELD_ID_NONE) + return { lower, upper }; + + std::string l2 = lower; + std::string u2 = upper; + + if (id == MU_MSG_FIELD_ID_DATE) { + l2 = Mu::date_to_time_t_string (lower, true); + u2 = Mu::date_to_time_t_string (upper, false); + } else if (id == MU_MSG_FIELD_ID_SIZE) { + l2 = Mu::size_to_string (lower, true); + u2 = Mu::size_to_string (upper, false); + } + + return { l2, u2 }; + } + + std::vector<std::string> + process_regex (const std::string& field, const std::regex& rx) const override { + + const auto id = field_id (field.c_str()); + if (id == MU_MSG_FIELD_ID_NONE) + return {}; + + char pfx[] = { mu_msg_field_xapian_prefix(id), '\0' }; + + std::vector<std::string> terms; + for (auto it = db_.allterms_begin(pfx); it != db_.allterms_end(pfx); ++it) { + if (std::regex_search((*it).c_str() + 1, rx)) // avoid copy + terms.push_back(*it); + } + + return terms; + } + + const Xapian::Database& db_; +}; + +struct _MuQuery { +public: + _MuQuery (MuStore *store): _store(mu_store_ref(store)) {} + ~_MuQuery () { mu_store_unref (_store); } + + Xapian::Database& db() const { + const auto db = reinterpret_cast<Xapian::Database*> + (mu_store_get_read_only_database (_store)); + if (!db) + throw Mu::Error(Error::Code::NotFound, "no database"); + return *db; + } +private: + MuStore *_store; +}; + +static const Xapian::Query +get_query (MuQuery *mqx, const char* searchexpr, bool raw, GError **err) try { + + Mu::WarningVec warns; + const auto tree = Mu::parse (searchexpr, warns, + std::make_unique<MuProc>(mqx->db())); + for (const auto w: warns) + std::cerr << w << std::endl; + + return Mu::xapian_query (tree); + +} catch (...) { + mu_util_g_set_error (err,MU_ERROR_XAPIAN_QUERY, + "parse error in query"); + throw; +} + +MuQuery* +mu_query_new (MuStore *store, GError **err) +{ + g_return_val_if_fail (store, NULL); + + try { + return new MuQuery (store); + } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN (err, MU_ERROR_XAPIAN, 0); + + return 0; +} + +void +mu_query_destroy (MuQuery *self) +{ + try { delete self; } MU_XAPIAN_CATCH_BLOCK; +} + + +/* this function is for handling the case where a DatabaseModified + * exception is raised. We try to reopen the database, and run the + * query again. */ +static MuMsgIter * +try_requery (MuQuery *self, const char* searchexpr, MuMsgFieldId sortfieldid, + int maxnum, MuQueryFlags flags, GError **err) +{ + try { + /* let's assume that infinite regression is + * impossible */ + self->db().reopen(); + MU_WRITE_LOG ("reopening db after modification"); + return mu_query_run (self, searchexpr, sortfieldid, + maxnum, flags, err); + + } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN (err, MU_ERROR_XAPIAN, 0); +} + + +static MuMsgIterFlags +msg_iter_flags (MuQueryFlags flags) +{ + MuMsgIterFlags iflags; + + iflags = MU_MSG_ITER_FLAG_NONE; + + if (flags & MU_QUERY_FLAG_DESCENDING) + iflags |= MU_MSG_ITER_FLAG_DESCENDING; + if (flags & MU_QUERY_FLAG_SKIP_UNREADABLE) + iflags |= MU_MSG_ITER_FLAG_SKIP_UNREADABLE; + if (flags & MU_QUERY_FLAG_SKIP_DUPS) + iflags |= MU_MSG_ITER_FLAG_SKIP_DUPS; + if (flags & MU_QUERY_FLAG_THREADS) + iflags |= MU_MSG_ITER_FLAG_THREADS; + + return iflags; +} + + + +static Xapian::Enquire +get_enquire (MuQuery *self, const char *searchexpr, MuMsgFieldId sortfieldid, + bool descending, bool raw, GError **err) +{ + Xapian::Enquire enq (self->db()); + + try { + if (raw) + enq.set_query(Xapian::Query(Xapian::Query(searchexpr))); + else if (!mu_str_is_empty(searchexpr) && + g_strcmp0 (searchexpr, "\"\"") != 0) /* NULL or "" or """" */ + enq.set_query(get_query (self, searchexpr, raw, err)); + else/* empty or "" means "matchall" */ + enq.set_query(Xapian::Query::MatchAll); + } catch (...) { + mu_util_g_set_error (err, MU_ERROR_XAPIAN_QUERY, + "parse error in query"); + throw; + } + + enq.set_cutoff(0,0); + return enq; +} + +/* + * record all threadids for the messages; also 'orig_set' receives all + * original matches (a map msgid-->docid), so we can make sure the + * originals are not seen as 'duplicates' later (when skipping + * duplicates). We want to favor the originals over the related + * messages, when skipping duplicates. + */ +static GHashTable* +get_thread_ids (MuMsgIter *iter, GHashTable **orig_set) +{ + GHashTable *ids; + + ids = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify)g_free, NULL); + *orig_set = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify)g_free, NULL); + + while (!mu_msg_iter_is_done (iter)) { + char *thread_id, *msgid; + unsigned docid; + /* record the thread id for the message */ + if ((thread_id = mu_msg_iter_get_thread_id (iter))) + g_hash_table_insert (ids, thread_id, + GSIZE_TO_POINTER(TRUE)); + /* record the original set */ + docid = mu_msg_iter_get_docid(iter); + if (docid != 0 && (msgid = mu_msg_iter_get_msgid (iter))) + g_hash_table_insert (*orig_set, msgid, + GSIZE_TO_POINTER(docid)); + + if (!mu_msg_iter_next (iter)) + break; + } + + return ids; +} + + +static Xapian::Query +get_related_query (MuMsgIter *iter, GHashTable **orig_set) +{ + GHashTable *hash; + GList *id_list, *cur; + std::vector<Xapian::Query> qvec; + static std::string pfx (1, mu_msg_field_xapian_prefix + (MU_MSG_FIELD_ID_THREAD_ID)); + + /* orig_set receives the hash msgid->docid of the set of + * original matches */ + hash = get_thread_ids (iter, orig_set); + /* id_list now gets a list of all thread-ids seen in the query + * results; either in the Message-Id field or in + * References. */ + id_list = g_hash_table_get_keys (hash); + + // now, we create a vector with queries for each of the + // thread-ids, which we combine below. This is /much/ faster + // than creating the query as 'query = Query (OR, query)'... + for (cur = id_list; cur; cur = g_list_next(cur)) + qvec.push_back (Xapian::Query((std::string + (pfx + (char*)cur->data)))); + + g_hash_table_destroy (hash); + g_list_free (id_list); + + return Xapian::Query (Xapian::Query::OP_OR, qvec.begin(), qvec.end()); +} + + +static void +get_related_messages (MuQuery *self, MuMsgIter **iter, int maxnum, + MuMsgFieldId sortfieldid, MuQueryFlags flags, + Xapian::Query orig_query) +{ + GHashTable *orig_set; + Xapian::Enquire enq (self->db()); + MuMsgIter *rel_iter; + const bool inc_related = flags & MU_QUERY_FLAG_INCLUDE_RELATED; + + orig_set = NULL; + Xapian::Query new_query = get_related_query (*iter, &orig_set); + /* If related message are not desired, filter out messages which would not + have matched the original query. + */ + if (!inc_related) + new_query = Xapian::Query (Xapian::Query::OP_AND, orig_query, new_query); + enq.set_query(new_query); + enq.set_cutoff(0,0); + + rel_iter= mu_msg_iter_new ( + reinterpret_cast<XapianEnquire*>(&enq), + maxnum, + sortfieldid, + msg_iter_flags (flags), + NULL); + + mu_msg_iter_destroy (*iter); + + // set the preferred set for the iterator (ie., the set of + // messages not considered to be duplicates) to be the + // original matches -- the matches without considering + // 'related' + mu_msg_iter_set_preferred (rel_iter, orig_set); + g_hash_table_destroy (orig_set); + + *iter = rel_iter; +} + + +MuMsgIter* +mu_query_run (MuQuery *self, const char *searchexpr, MuMsgFieldId sortfieldid, + int maxnum, MuQueryFlags flags, GError **err) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (searchexpr, NULL); + g_return_val_if_fail (mu_msg_field_id_is_valid (sortfieldid) || + sortfieldid == MU_MSG_FIELD_ID_NONE, + NULL); + try { + MuMsgIter *iter; + MuQueryFlags first_flags; + const bool threads = flags & MU_QUERY_FLAG_THREADS; + const bool inc_related = flags & MU_QUERY_FLAG_INCLUDE_RELATED; + const bool descending = flags & MU_QUERY_FLAG_DESCENDING; + const bool raw = flags & MU_QUERY_FLAG_RAW; + Xapian::Enquire enq (get_enquire(self, searchexpr, sortfieldid, + descending, raw, err)); + + /* when we're doing a 'include-related query', wea're actually + * doing /two/ queries; one to get the initial matches, and + * based on that one to get all messages in threads in those + * matches. + */ + + /* get the 'real' maxnum if it was specified as < 0 */ + maxnum = maxnum < 0 ? self->db().get_doccount() : maxnum; + /* Calculating threads involves two queries, so do the calculation only in + * the second query instead of in both. + */ + if (threads) + first_flags = (MuQueryFlags)(flags & ~MU_QUERY_FLAG_THREADS); + else + first_flags = flags; + /* Perform the initial query, returning up to max num results. + */ + iter = mu_msg_iter_new ( + reinterpret_cast<XapianEnquire*>(&enq), + maxnum, + sortfieldid, + msg_iter_flags (first_flags), + err); + /* If we want threads or related messages, find related messages using a + * second query based on the message ids / refs of the first query's result. + * Do this even if we don't want to include related messages in the final + * result so we can apply the threading algorithm to the related message set + * of a maxnum-sized result instead of the unbounded result of the first + * query. If threads are desired but related message are not, we will remove + * the undesired related messages later. + */ + if(threads||inc_related) + get_related_messages (self, &iter, maxnum, sortfieldid, flags, + enq.get_query()); + + if (err && *err && (*err)->code == MU_ERROR_XAPIAN_MODIFIED) { + g_clear_error (err); + return try_requery (self, searchexpr, sortfieldid, + maxnum, flags, err); + } else + return iter; + + } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN (err, MU_ERROR_XAPIAN, 0); +} + + +size_t +mu_query_count_run (MuQuery *self, const char *searchexpr) try +{ + g_return_val_if_fail (self, 0); + g_return_val_if_fail (searchexpr, 0); + + const auto enq{get_enquire(self, searchexpr,MU_MSG_FIELD_ID_NONE, false, false, NULL)}; + auto mset(enq.get_mset(0, self->db().get_doccount())); + mset.fetch(); + + return mset.size(); + +} MU_XAPIAN_CATCH_BLOCK_RETURN (0); + + + + +char* +mu_query_internal_xapian (MuQuery *self, const char *searchexpr, GError **err) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (searchexpr, NULL); + + try { + Xapian::Query query (get_query(self, searchexpr, false, err)); + return g_strdup(query.get_description().c_str()); + + } MU_XAPIAN_CATCH_BLOCK_RETURN(NULL); +} + + +char* +mu_query_internal (MuQuery *self, const char *searchexpr, + gboolean warn, GError **err) +{ + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (searchexpr, NULL); + + try { + Mu::WarningVec warns; + const auto tree = Mu::parse (searchexpr, warns, + std::make_unique<MuProc>(self->db())); + std::stringstream ss; + ss << tree; + + if (warn) { + for (const auto w: warns) + std::cerr << w << std::endl; + } + + return g_strdup(ss.str().c_str()); + + } MU_XAPIAN_CATCH_BLOCK_RETURN(NULL); +} diff --git a/lib/mu-query.h b/lib/mu-query.h new file mode 100644 index 0000000..26cdb0f --- /dev/null +++ b/lib/mu-query.h @@ -0,0 +1,136 @@ +/* +** Copyright (C) 2008-2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_QUERY_H__ +#define __MU_QUERY_H__ + +#include <glib.h> +#include <mu-store.hh> +#include <mu-msg-iter.h> +#include <utils/mu-util.h> + +G_BEGIN_DECLS + +struct _MuQuery; +typedef struct _MuQuery MuQuery; + +/** + * create a new MuQuery instance. + * + * @param store a MuStore object + * @param err receives error information (if there is any); if + * function returns non-NULL, err will _not_be set. err can be NULL + * possible errors (err->code) are MU_ERROR_XAPIAN_DIR and + * MU_ERROR_XAPIAN_NOT_UPTODATE + * + * @return a new MuQuery instance, or NULL in case of error. + * when the instance is no longer needed, use mu_query_destroy + * to free it + */ +MuQuery* mu_query_new (MuStore *store, GError **err) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +/** + * destroy the MuQuery instance + * + * @param self a MuQuery instance, or NULL + */ +void mu_query_destroy (MuQuery *self); + + +typedef enum { + MU_QUERY_FLAG_NONE = 0 << 0, /**< no flags */ + MU_QUERY_FLAG_DESCENDING = 1 << 0, /**< sort z->a */ + MU_QUERY_FLAG_SKIP_UNREADABLE = 1 << 1, /**< skip unreadable msgs */ + MU_QUERY_FLAG_SKIP_DUPS = 1 << 2, /**< skip duplicate msgs */ + MU_QUERY_FLAG_INCLUDE_RELATED = 1 << 3, /**< include related msgs */ + MU_QUERY_FLAG_THREADS = 1 << 4, /**< calculate threading info */ + MU_QUERY_FLAG_RAW = 1 << 5 /**< don't parse the query */ +} MuQueryFlags; + +/** + * run a Xapian query; for the syntax, please refer to the mu-query + * manpage + * + * @param self a valid MuQuery instance + * @param expr the search expression; use "" to match all messages + * @param sortfield the field id to sort by or MU_MSG_FIELD_ID_NONE if + * sorting is not desired + * @param maxnum maximum number of search results to return, or <= 0 for + * unlimited + * @param flags bitwise OR'd flags to influence the query (see MuQueryFlags) + * @param err receives error information (if there is any); if + * function returns non-NULL, err will _not_be set. err can be NULL + * possible error (err->code) is MU_ERROR_QUERY, + * + * @return a MuMsgIter instance you can iterate over, or NULL in + * case of error + */ +MuMsgIter* mu_query_run (MuQuery *self, const char* expr, + MuMsgFieldId sortfieldid, int maxnum, + MuQueryFlags flags, GError **err) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + + +/** + * run a Xapian query to count the number of matches; for the syntax, please + * refer to the mu-query manpage + * + * @param self a valid MuQuery instance + * @param expr the search expression; use "" to match all messages + * + * @return the number of matches + */ +size_t mu_query_count_run (MuQuery *self, const char *searchexpr); + +/** + * get Xapian's internal string representation of the query + * + * @param self a MuQuery instance + * @param searchexpr a xapian search expression + * @param warn print warnings to stderr + * @param err receives error information (if there is any); if + * function returns non-NULL, err will _not_be set. err can be NULL + * + * @return the string representation of the xapian query, or NULL in case of + * error; free the returned value with g_free + */ +char* mu_query_internal (MuQuery *self, const char *searchexpr, + gboolean warn, GError **err) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +/** + * get Xapian's internal string representation of the query + * + * @param self a MuQuery instance + * @param searchexpr a xapian search expression + * @param err receives error information (if there is any); if + * function returns non-NULL, err will _not_be set. err can be NULL + * + * @return the string representation of the xapian query, or NULL in case of + * error; free the returned value with g_free + */ +char* mu_query_internal_xapian (MuQuery *self, const char* searchexpr, + GError **err) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + + +G_END_DECLS + +#endif /*__MU_QUERY_H__*/ diff --git a/lib/mu-runtime.cc b/lib/mu-runtime.cc new file mode 100644 index 0000000..b8fb606 --- /dev/null +++ b/lib/mu-runtime.cc @@ -0,0 +1,118 @@ +/* +** Copyright (C) 2019 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include "mu-runtime.h" +#include "utils/mu-util.h" + +#include <locale.h> /* for setlocale() */ + +#include <string> +#include <unordered_map> +static std::unordered_map<MuRuntimePath, std::string> RuntimePaths; + +constexpr auto PartsDir = "parts"; +constexpr auto LogDir = "log"; +constexpr auto XapianDir = "xapian"; +constexpr auto Mu = "mu"; +constexpr auto Bookmarks = "bookmarks"; + +static const std::string Sepa{G_DIR_SEPARATOR_S}; + +static void +init_paths_xdg () +{ + RuntimePaths.emplace(MU_RUNTIME_PATH_XAPIANDB, g_get_user_cache_dir() + + Sepa + Mu + Sepa + XapianDir); + RuntimePaths.emplace(MU_RUNTIME_PATH_CACHE, g_get_user_cache_dir() + + Sepa + Mu); + RuntimePaths.emplace(MU_RUNTIME_PATH_MIMECACHE, g_get_user_cache_dir() + + Sepa + Mu + Sepa + PartsDir); + RuntimePaths.emplace(MU_RUNTIME_PATH_LOGDIR, g_get_user_cache_dir() + + Sepa + Mu); + RuntimePaths.emplace(MU_RUNTIME_PATH_BOOKMARKS, g_get_user_config_dir() + + Sepa + Mu); +} + +static void +init_paths_muhome (const char *muhome) +{ + RuntimePaths.emplace(MU_RUNTIME_PATH_XAPIANDB, muhome + Sepa + XapianDir); + RuntimePaths.emplace(MU_RUNTIME_PATH_CACHE, muhome); + RuntimePaths.emplace(MU_RUNTIME_PATH_MIMECACHE, muhome + Sepa + PartsDir); + RuntimePaths.emplace(MU_RUNTIME_PATH_LOGDIR, muhome + Sepa + LogDir); + RuntimePaths.emplace(MU_RUNTIME_PATH_BOOKMARKS, muhome + Sepa + Bookmarks); +} + +gboolean +mu_runtime_init (const char* muhome, const char *name) +{ + g_return_val_if_fail (RuntimePaths.empty(), FALSE); + g_return_val_if_fail (name, FALSE); + + setlocale (LC_ALL, ""); + + if (muhome) + init_paths_muhome (muhome); + else + init_paths_xdg(); + + for (const auto& d: RuntimePaths ) { + char* dir; + if (d.first == MU_RUNTIME_PATH_BOOKMARKS) // special case + dir = g_path_get_dirname (d.second.c_str()); + else + dir = g_strdup (d.second.c_str()); + + auto ok = mu_util_create_dir_maybe (dir, 0700, TRUE); + if (!ok) { + g_critical ("failed to create %s", dir); + g_free (dir); + mu_runtime_uninit(); + return FALSE; + } + g_free (dir); + } + + const auto log_path = RuntimePaths[MU_RUNTIME_PATH_LOGDIR] + + Sepa + name + ".log"; + + if (!mu_log_init (log_path.c_str(), MU_LOG_OPTIONS_BACKUP)) { + mu_runtime_uninit(); + return FALSE; + } + + return TRUE; +} + +void +mu_runtime_uninit (void) +{ + RuntimePaths.clear(); + mu_log_uninit(); +} + +const char* +mu_runtime_path (MuRuntimePath path) +{ + const auto it = RuntimePaths.find (path); + if (it == RuntimePaths.end()) + return NULL; + else + return it->second.c_str(); +} diff --git a/lib/mu-runtime.h b/lib/mu-runtime.h new file mode 100644 index 0000000..f300815 --- /dev/null +++ b/lib/mu-runtime.h @@ -0,0 +1,67 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- +** +** Copyright (C) 2012-2019 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ +#ifndef __MU_RUNTIME_H__ +#define __MU_RUNTIME_H__ + +#include <glib.h> +#include <utils/mu-log.h> + +G_BEGIN_DECLS + +/** + * initialize the mu runtime system; initializes logging and other + * systems. To uninitialize, use mu_runtime_uninit + * + * @param muhome path where to find the mu home directory (typically, ~/.cache/mu) + * @param name of the main program, ie. 'mu', 'mug' or + * 'procmule'. this influences the name of the e.g. the logfile + * + * @return TRUE if succeeded, FALSE in case of error + */ +gboolean mu_runtime_init (const char *muhome, const char *name); + +/** + * free all resources + * + */ +void mu_runtime_uninit (void); + + +typedef enum { + MU_RUNTIME_PATH_XAPIANDB, /* mu xapian db path */ + MU_RUNTIME_PATH_BOOKMARKS, /* mu bookmarks file path */ + MU_RUNTIME_PATH_CACHE, /* mu cache path for attachments etc. */ + MU_RUNTIME_PATH_MIMECACHE, /* mu cache path for attachments etc. */ + MU_RUNTIME_PATH_LOGDIR, /* mu path for log files */ + + MU_RUNTIME_PATH_NUM +} MuRuntimePath; + +/** + * get a file system path to some 'special' file or directory + * + * @return ma string which should be not be modified/freed, or NULL in + * case of error. + */ +const char* mu_runtime_path (MuRuntimePath path); + +G_END_DECLS + +#endif /*__MU_RUNTIME_H__*/ diff --git a/lib/mu-script.c b/lib/mu-script.c new file mode 100644 index 0000000..c5b167f --- /dev/null +++ b/lib/mu-script.c @@ -0,0 +1,360 @@ +/* +** Copyright (C) 2012-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#ifdef BUILD_GUILE + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#include <libguile.h> +#pragma GCC diagnostic pop +#endif /*BUILD_GUILE*/ + +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <dirent.h> +#include <errno.h> +#include <unistd.h> + +#include "utils/mu-str.h" +#include "mu-script.h" +#include "utils/mu-util.h" + +/** + * Structure with information about a certain script. + * the values will be *freed* when MuScriptInfo is freed + */ +struct _MuScriptInfo { + char *_name; /* filename-sans-extension */ + char *_path; /* full path to script */ + char *_oneline; /* one-line description */ + char *_descr; /* longer description */ +}; + + +/* create a new MuScriptInfo* object*/ +static MuScriptInfo* +script_info_new (void) +{ + return g_slice_new0 (MuScriptInfo); +} + +/* destroy a MuScriptInfo* object */ +static void +script_info_destroy (MuScriptInfo *msi) +{ + if (!msi) + return; + + g_free (msi->_name); + g_free (msi->_path); + g_free (msi->_oneline); + g_free (msi->_descr); + + g_slice_free (MuScriptInfo, msi); +} + +/* compare two MuScripInfo* objects (for sorting) */ +static int +script_info_cmp (MuScriptInfo *msi1, MuScriptInfo *msi2) +{ + return strcmp (msi1->_name, msi2->_name); + +} + +const char* +mu_script_info_name (MuScriptInfo *msi) +{ + g_return_val_if_fail (msi, NULL); + return msi->_name; +} + +const char* +mu_script_info_path (MuScriptInfo *msi) +{ + g_return_val_if_fail (msi, NULL); + return msi->_path; +} + +const char* +mu_script_info_one_line (MuScriptInfo *msi) +{ + g_return_val_if_fail (msi, NULL); + return msi->_oneline; +} + +const char* +mu_script_info_description (MuScriptInfo *msi) +{ + g_return_val_if_fail (msi, NULL); + return msi->_descr; +} + + +gboolean +mu_script_info_matches_regex (MuScriptInfo *msi, const char *rxstr, + GError **err) +{ + GRegex *rx; + gboolean match; + + g_return_val_if_fail (msi, FALSE); + g_return_val_if_fail (rxstr, FALSE); + + rx = g_regex_new (rxstr, G_REGEX_CASELESS|G_REGEX_OPTIMIZE, 0, err); + if (!rx) + return FALSE; + + match = FALSE; + if (msi->_name) + match = g_regex_match (rx, msi->_name, 0, NULL); + if (!match && msi->_oneline) + match = g_regex_match (rx, msi->_oneline, 0, NULL); + + return match; +} + +void +mu_script_info_list_destroy (GSList *lst) +{ + g_slist_foreach (lst, (GFunc)script_info_destroy, NULL); + g_slist_free (lst); +} + + +static GIOChannel * +open_channel (const char *path) +{ + GError *err; + GIOChannel *io_chan; + + err = NULL; + + io_chan = g_io_channel_new_file (path, "r", &err); + if (!io_chan) { + g_warning ("failed to open '%s': %s", path, + err ? err->message : "something went wrong"); + g_clear_error (&err); + return NULL; + } + + return io_chan; +} + +static void +end_channel (GIOChannel *io_chan) +{ + GIOStatus status; + GError *err; + + err = NULL; + status = g_io_channel_shutdown (io_chan, FALSE, + &err); + if (status != G_IO_STATUS_NORMAL) { + g_warning ("failed to shutdown io-channel: %s", + err ? err->message : "something went wrong"); + g_clear_error (&err); + } + + g_io_channel_unref (io_chan); +} + + + +static gboolean +get_descriptions (MuScriptInfo *msi, const char *prefix) +{ + GIOStatus io_status; + GIOChannel *script_io; + GError *err; + + char *line, *descr, *oneline; + + if (!prefix) + return TRUE; /* not an error */ + + if (!(script_io = open_channel (msi->_path))) + return FALSE; + + err = NULL; + line = descr = oneline = NULL; + + do { + g_free (line); + io_status = g_io_channel_read_line (script_io, &line, + NULL, NULL, &err); + if (io_status != G_IO_STATUS_NORMAL) + break; + + if (!g_str_has_prefix (line, prefix)) + continue; + + if (!oneline) + oneline = g_strdup (line + strlen (prefix)); + else { + char *tmp; + tmp = descr; + descr = g_strdup_printf + ("%s%s", descr ? descr : "", + line + strlen(prefix)); + g_free (tmp); + } + + } while (TRUE); + + if (io_status != G_IO_STATUS_EOF) { + g_warning ("error reading %s: %s", msi->_path, + err ? err->message : "something went wrong"); + g_clear_error (&err); + } + + end_channel (script_io); + msi->_oneline = oneline; + msi->_descr = descr; + + return TRUE; +} + + + +GSList* +mu_script_get_script_info_list (const char *path, const char *ext, + const char *descprefix, GError **err) +{ + DIR *dir; + GSList *lst; + struct dirent *dentry; + + g_return_val_if_fail (path, NULL); + + dir = opendir (path); + if (!dir) { + mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_OPEN, + "failed to open '%s': %s", + path, strerror(errno)); + return NULL; + } + + /* create a list of names, paths */ + lst = NULL; + while ((dentry = readdir (dir))) { + MuScriptInfo *msi; + /* only consider files with certain extensions, + * if ext != NULL */ + if (ext && !g_str_has_suffix (dentry->d_name, ext)) + continue; + msi = script_info_new (); + msi->_name = g_strdup (dentry->d_name); + if (ext) /* strip the extension */ + msi->_name[strlen(msi->_name) - strlen(ext)] = '\0'; + msi->_path = g_strdup_printf ("%s%c%s", path, G_DIR_SEPARATOR, + dentry->d_name); + /* set the one-line and long description */ + get_descriptions (msi, descprefix); + lst = g_slist_prepend (lst, msi); + } + + closedir (dir); /* ignore error checking... */ + + return g_slist_sort (lst, (GCompareFunc)script_info_cmp); +} + + +MuScriptInfo* +mu_script_find_script_with_name (GSList *lst, const char *name) +{ + GSList *cur; + + g_return_val_if_fail (name, NULL); + + for (cur = lst; cur; cur = g_slist_next (cur)) { + + MuScriptInfo *msi; + msi = (MuScriptInfo*)cur->data; + + if (g_strcmp0 (name, mu_script_info_name (msi)) == 0) + return msi; + } + + return NULL; +} + +#ifdef BUILD_GUILE +static void +guile_shell (void *closure, int argc, char **argv) +{ + scm_shell (argc, argv); +} + +gboolean +mu_script_guile_run (MuScriptInfo *msi, const char *muhome, + const char **args, GError **err) +{ + const char *s; + char *mainargs, *expr; + char **argv; + + g_return_val_if_fail (msi, FALSE); + g_return_val_if_fail (muhome, FALSE); + + argv = g_new0 (char*, 6); + argv[0] = g_strdup("guile2.2"); + argv[1] = g_strdup("-l"); + + if (access (mu_script_info_path (msi), R_OK) != 0) { + mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_READ, + "failed to read script: %s", + strerror(errno)); + return FALSE; + } + + s = mu_script_info_path (msi); + argv[2] = g_strdup (s ? s : ""); + + mainargs = mu_str_quoted_from_strv (args); + expr = g_strdup_printf ( + "(main '(\"%s\" \"--muhome=%s\" %s))", + mu_script_info_name (msi), + muhome, + mainargs ? mainargs : ""); + + g_free (mainargs); + argv[3] = g_strdup("-c"); + argv[4] = expr; + + scm_boot_guile (5, argv, guile_shell, NULL); + + /* never reached but let's be correct(TM)*/ + g_strfreev (argv); + return TRUE; +} +#else /*!BUILD_GUILE*/ +gboolean +mu_script_guile_run (MuScriptInfo *msi, const char *muhome, + const char **args, GError **err) +{ + mu_util_g_set_error (err, MU_ERROR_INTERNAL, + "this mu does not have guile support"); + return FALSE; +} +#endif /*!BUILD_GUILE*/ diff --git a/lib/mu-script.h b/lib/mu-script.h new file mode 100644 index 0000000..586b6f0 --- /dev/null +++ b/lib/mu-script.h @@ -0,0 +1,132 @@ +/* +** Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_SCRIPT_H__ +#define __MU_SCRIPT_H__ + +#include <glib.h> + +G_BEGIN_DECLS + +/* Opaque structure with information about a script */ +struct _MuScriptInfo; +typedef struct _MuScriptInfo MuScriptInfo; + +/** + * get the name of the script (sans-extension, if some extension was + * provided to mu_script_get_scripts) + * + * @param msi a MuScriptInfo structure + * + * @return the name + */ +const char* mu_script_info_name (MuScriptInfo *msi); + + +/** + * get the full filesystem path of the script + * + * @param msi a MuScriptInfo structure + * + * @return the path + */ +const char* mu_script_info_path (MuScriptInfo *msi); + +/** + * get a one-line description for the script + * + * @param msi a MuScriptInfo structure + * + * @return the description, or NULL if there was none + */ +const char* mu_script_info_one_line (MuScriptInfo *msi); + +/** + * get a full description for the script + * + * @param msi a MuScriptInfo structure + * + * @return the description, or NULL if there was none + */ +const char* mu_script_info_description (MuScriptInfo *msi); + +/** + * check whether either the name or one-line description of a + * MuScriptInfo matches regular expression rxstr + * + * @param msi a MuScriptInfo + * @param rxstr a regular expression string + * @param err receives error information + * + * @return TRUE if it matches, FALSE if not or in case of error + */ +gboolean mu_script_info_matches_regex (MuScriptInfo *msi, const char *rxstr, + GError **err); + +/** + * Get the list of all scripts in path with extension ext + * + * @param path a file system path + * @param ext an extension (e.g., ".scm"), or NULL + * @param prefix for the one-line description + * (e.g., ";; DESCRIPTION: "), or NULL + * @param err receives error information, if any + * + * @return a list of Mu + */ +GSList *mu_script_get_script_info_list (const char *path, const char *ext, + const char *descprefix, GError **err); + +/** + * destroy a list of MuScriptInfo* objects + * + * @param scriptslst a list of MuScriptInfo* objects + */ +void mu_script_info_list_destroy (GSList *lst); + + +/** + * find the MuScriptInfo object for the first script with a certain + * name, or return NULL if not found. + * + * @param lst a list of MuScriptInfo* objects + * @param name the name to search for + * + * @return a MuScriptInfo* object, or NULL if not found. + */ +MuScriptInfo* mu_script_find_script_with_name (GSList *lst, const char *name); + + +/** + * run the guile script at path + * + * @param msi MuScriptInfo object for the script + * @param muhome path to the mu home dir + * @param args NULL-terminated array of strings (argv for the script) + * @param err receives error information + * + * @return FALSE in case of error -- otherwise, this function will + * _not return_ + */ +gboolean mu_script_guile_run (MuScriptInfo *msi, const char *muhome, + const char **args, GError **err); + +G_END_DECLS + +#endif /*__MU_SCRIPT_H__*/ diff --git a/lib/mu-store.cc b/lib/mu-store.cc new file mode 100644 index 0000000..d9141e9 --- /dev/null +++ b/lib/mu-store.cc @@ -0,0 +1,1433 @@ +/* +** Copyright (C) 2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include "config.h" + +#include <mutex> +#include <array> +#include <cstdlib> +#include <xapian.h> +#include <unordered_map> +#include <atomic> +#include <iostream> +#include <cstring> +#include "mu-store.hh" +#include "utils/mu-str.h" +#include "utils/mu-error.hh" + +#include "mu-msg-part.h" +#include "utils/mu-utils.hh" + +using namespace Mu; + +constexpr auto SchemaVersionKey = "schema-version"; +constexpr auto RootMaildirKey = "maildir"; // XXX: make this 'root-maildir' +constexpr auto ContactsKey = "contacts"; +constexpr auto PersonalAddressesKey = "personal-addresses"; +constexpr auto CreatedKey = "created"; +constexpr auto BatchSize = 150'000; + +constexpr auto ExpectedSchemaVersion = MU_STORE_SCHEMA_VERSION; + + + +extern "C" { +static unsigned add_or_update_msg (MuStore *store, unsigned docid, MuMsg *msg, GError **err); +} + +/* we cache these prefix strings, so we don't have to allocate them all + * the time; this should save 10-20 string allocs per message */ +G_GNUC_CONST static const std::string& +prefix (MuMsgFieldId mfid) +{ + static std::string fields[MU_MSG_FIELD_ID_NUM]; + static bool initialized = false; + + if (G_UNLIKELY(!initialized)) { + for (int i = 0; i != MU_MSG_FIELD_ID_NUM; ++i) + fields[i] = std::string (1, mu_msg_field_xapian_prefix + ((MuMsgFieldId)i)); + initialized = true; + } + + return fields[mfid]; +} + +static void +add_synonym_for_flag (MuFlags flag, Xapian::WritableDatabase *db) +{ + static const std::string pfx(prefix(MU_MSG_FIELD_ID_FLAGS)); + + db->clear_synonyms (pfx + mu_flag_name (flag)); + db->add_synonym (pfx + mu_flag_name (flag), pfx + + (std::string(1, (char)(tolower(mu_flag_char(flag)))))); +} + + +static void +add_synonym_for_prio (MuMsgPrio prio, Xapian::WritableDatabase *db) +{ + static const std::string pfx (prefix(MU_MSG_FIELD_ID_PRIO)); + + std::string s1 (pfx + mu_msg_prio_name (prio)); + std::string s2 (pfx + (std::string(1, mu_msg_prio_char (prio)))); + + db->clear_synonyms (s1); + db->clear_synonyms (s2); + + db->add_synonym (s1, s2); +} + +struct Store::Private { + +#define LOCKED std::lock_guard<std::mutex> l(lock_); + + Private (const std::string& path, bool readonly): + db_path_{path}, + db_{readonly? + std::make_shared<Xapian::Database>(db_path_) : + std::make_shared<Xapian::WritableDatabase>(db_path_, Xapian::DB_OPEN)}, + root_maildir_{db()->get_metadata(RootMaildirKey)}, + created_{atoll(db()->get_metadata(CreatedKey).c_str())}, + schema_version_{db()->get_metadata(SchemaVersionKey)}, + personal_addresses_{Mu::split(db()->get_metadata(PersonalAddressesKey),",")}, + contacts_{db()->get_metadata(ContactsKey)} { + } + + Private (const std::string& path, const std::string& root_maildir, + const StringVec& personal_addresses): + db_path_{path}, + db_{std::make_shared<Xapian::WritableDatabase>( + db_path_, Xapian::DB_CREATE_OR_OVERWRITE)}, + root_maildir_{root_maildir}, + created_{time({})}, + schema_version_{MU_STORE_SCHEMA_VERSION}, + personal_addresses_{personal_addresses} { + + writable_db()->set_metadata(SchemaVersionKey, schema_version_); + writable_db()->set_metadata(RootMaildirKey, root_maildir_); + writable_db()->set_metadata(CreatedKey, Mu::format("%" PRId64, (int64_t)created_)); + + std::string addrs; + for (const auto& addr : personal_addresses_) { // _very_ minimal check. + if (addr.find(",") != std::string::npos) + throw Mu::Error(Error::Code::InvalidArgument, + "e-mail address '%s' contains comma", addr.c_str()); + addrs += (addrs.empty() ? "": ",") + addr; + } + writable_db()->set_metadata (PersonalAddressesKey, addrs); + + } + + ~Private() try { + LOCKED; + if (wdb()) { + wdb()->set_metadata (ContactsKey, contacts_.serialize()); + if (in_transaction_) // auto-commit. + wdb()->commit_transaction(); + } + } MU_XAPIAN_CATCH_BLOCK; + + std::shared_ptr<Xapian::Database> db() const { + if (!db_) + throw Mu::Error(Error::Code::NotFound, "no database found"); + return db_; + } + + std::shared_ptr<Xapian::WritableDatabase> wdb() const { + return std::dynamic_pointer_cast<Xapian::WritableDatabase>(db_); + } + + std::shared_ptr<Xapian::WritableDatabase> writable_db() const { + auto w_db{wdb()}; + if (!w_db) + throw Mu::Error(Error::Code::AccessDenied, "database is read-only"); + else + return w_db; + } + + void begin_transaction () try { + wdb()->begin_transaction(); + in_transaction_ = true; + dirtiness_ = 0; + } MU_XAPIAN_CATCH_BLOCK; + + void commit_transaction () try { + in_transaction_ = false; + dirtiness_ = 0; + wdb()->commit_transaction(); + } MU_XAPIAN_CATCH_BLOCK; + + void add_synonyms () { + mu_flags_foreach ((MuFlagsForeachFunc)add_synonym_for_flag, + writable_db().get()); + mu_msg_prio_foreach ((MuMsgPrioForeachFunc)add_synonym_for_prio, + writable_db().get()); + } + + time_t metadata_time_t (const std::string& key) const { + const auto ts = db()->get_metadata(key); + return (time_t)atoll(db()->get_metadata(key).c_str()); + } + + + + const std::string db_path_; + std::shared_ptr<Xapian::Database> db_; + const std::string root_maildir_; + const time_t created_{}; + const std::string schema_version_; + const StringVec personal_addresses_; + Contacts contacts_; + + std::atomic<bool> in_transaction_{}; + std::mutex lock_; + + size_t dirtiness_{}; + + mutable std::atomic<std::size_t> ref_count_{1}; +}; + + +static void +hash_str (char *buf, size_t buf_size, const char *data) +{ + g_snprintf(buf, buf_size, "016%" PRIx64, mu_util_get_hash(data)); +} + + +static std::string +get_uid_term (const char* path) +{ + char uid_term[1 + 16 + 1] = {'\0'}; + uid_term[0] = mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_UID); + hash_str(uid_term + 1, sizeof(uid_term)-1, path); + + return std::string{uid_term, sizeof(uid_term)}; +} + + +#undef LOCKED +#define LOCKED std::lock_guard<std::mutex> l(priv_->lock_); + +Store::Store (const std::string& path, bool readonly): + priv_{std::make_unique<Private>(path, readonly)} +{ + if (ExpectedSchemaVersion != schema_version()) + throw Mu::Error(Error::Code::SchemaMismatch, + "expected schema-version %s, but got %s", + ExpectedSchemaVersion, schema_version().c_str()); +} + +Store::Store (const std::string& path, const std::string& maildir, + const StringVec& personal_addresses): + priv_{std::make_unique<Private>(path, maildir, personal_addresses)} +{} + +Store::~Store() = default; + +bool +Store::read_only() const +{ + return !priv_->wdb(); +} + +const std::string& +Store::root_maildir () const +{ + return priv_->root_maildir_; +} + +const StringVec& +Store::personal_addresses(void) const +{ + return priv_->personal_addresses_; +} + +const std::string& +Store::database_path() const +{ + return priv_->db_path_; +} + +const Contacts& +Store::contacts() const +{ + LOCKED; + return priv_->contacts_; +} + +std::size_t +Store::size() const +{ + return priv_->db()->get_doccount(); +} + +bool +Store::empty() const +{ + return size() == 0; +} + + +const std::string& +Store::schema_version() const +{ + return priv_->schema_version_; +} + +time_t +Store::created() const +{ + return priv_->created_; +} + +static std::string +maildir_from_path (const std::string& root, const std::string& path) +{ + if (G_UNLIKELY(root.empty()) || root.length() >= path.length() || + path.find(root) != 0) + throw Mu::Error{Error::Code::InvalidArgument, + "root '%s' is not a proper suffix of path '%s'", + root.c_str(), path.c_str()}; + + auto mdir{path.substr(root.length())}; + auto slash{mdir.rfind('/')}; + + if (G_UNLIKELY(slash == std::string::npos) || slash < 4) + throw Mu::Error{Error::Code::InvalidArgument, + "invalid path: %s", path.c_str()}; + mdir.erase(slash); + auto subdir=mdir.data()+slash-4; + if (G_UNLIKELY(strncmp(subdir, "/cur", 4) != 0 && + strncmp(subdir, "/new", 4))) + throw Mu::Error{Error::Code::InvalidArgument, + "cannot find '/new' or '/cur' - invalid path: %s", path.c_str()}; + if (mdir.length() == 4) + return "/"; + + mdir.erase(mdir.length()-4); + return mdir; +} + + +unsigned +Store::add_message (const std::string& path) +{ + LOCKED; + + GError *gerr{}; + const auto maildir{maildir_from_path(root_maildir(), path)}; + auto msg{mu_msg_new_from_file (path.c_str(), maildir.c_str(), &gerr)}; + if (G_UNLIKELY(!msg)) + throw Error{Error::Code::Message, "failed to create message: %s", + gerr ? gerr->message : "something went wrong"}; + + auto store{reinterpret_cast<MuStore*>(this)}; // yuk. + const auto docid{add_or_update_msg (store, 0, msg, &gerr)}; + mu_msg_unref (msg); + if (G_UNLIKELY(docid == MU_STORE_INVALID_DOCID)) + throw Error{Error::Code::Message, "failed to store message: %s", + gerr ? gerr->message : "something went wrong"}; + + return docid; +} + +bool +Store::remove_message (const std::string& path) +{ + LOCKED; + + try { + const std::string term{(get_uid_term(path.c_str()))}; + auto wdb{priv()->wdb()}; + + wdb->delete_document (term); + + } MU_XAPIAN_CATCH_BLOCK_RETURN (false); + + return true; +} + + + +time_t +Store::dirstamp (const std::string& path) const +{ + LOCKED; + + const auto ts = priv_->db()->get_metadata(path); + if (ts.empty()) + return 0; + else + return (time_t)strtoll(ts.c_str(), NULL, 16); +} + +void +Store::set_dirstamp (const std::string& path, time_t tstamp) +{ + LOCKED; + + std::array<char, 2*sizeof(tstamp)+1> data{}; + const std::size_t len = g_snprintf (data.data(), data.size(), "%zx", tstamp); + + priv_->writable_db()->set_metadata(path, std::string{data.data(), len}); +} + + +MuMsg* +Store::find_message (unsigned docid) const +{ + LOCKED; + + try { + Xapian::Document *doc{new Xapian::Document{priv_->db()->get_document (docid)}}; + GError *gerr{}; + auto msg{mu_msg_new_from_doc (reinterpret_cast<XapianDocument*>(doc), &gerr)}; + if (!msg) { + g_warning ("could not create message: %s", gerr ? gerr->message : + "something went wrong"); + g_clear_error(&gerr); + } + + return msg; + + } MU_XAPIAN_CATCH_BLOCK_RETURN (nullptr); +} + + +bool +Store::contains_message (const std::string& path) const +{ + LOCKED; + + try { + const std::string term (get_uid_term(path.c_str())); + return priv_->db()->term_exists (term); + + } MU_XAPIAN_CATCH_BLOCK_RETURN(false); +} + +void +Store::begin_transaction () try +{ + LOCKED; + priv_->begin_transaction(); + +} MU_XAPIAN_CATCH_BLOCK; + +void +Store::commit_transaction () try +{ + LOCKED; + priv_->commit_transaction(); + +} MU_XAPIAN_CATCH_BLOCK; + +bool +Store::in_transaction () const +{ + return priv_->in_transaction_; +} + + +//////////////////////////////////////////////////////////////////////////////// +// C compat +extern "C" { + + +struct MuStore_ { Mu::Store* self; }; + + +static const Mu::Store* +self (const MuStore *store) +{ + if (!store) { + g_error ("invalid store"); // terminates + return {}; + } + + return reinterpret_cast<const Mu::Store*>(store); +} + +static Mu::Store* +mutable_self (MuStore *store) +{ + if (!store) { + g_error ("invalid store"); // terminates + return {}; + } + + auto s = reinterpret_cast<Mu::Store*>(store); + if (s->read_only()) { + g_error ("store is read-only"); // terminates + return {}; + } + + return s; +} + + +MuStore* +mu_store_new_readable (const char* xpath, GError **err) +{ + g_return_val_if_fail (xpath, NULL); + + g_debug ("opening database at %s (read-only)", xpath); + + try { + return reinterpret_cast<MuStore*>(new Store (xpath)); + + } catch (const Mu::Error& me) { + g_warning ("failed to open database: %s", me.what()); + } catch (const Xapian::Error& dbe) { + g_warning ("failed to open database @ %s: %s", xpath, + dbe.get_error_string() ? dbe.get_error_string() : "something went wrong"); + } + + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN_CANNOT_OPEN, + "failed to open database @ %s", xpath); + + return NULL; +} + +MuStore* +mu_store_new_writable (const char* xpath, GError **err) +{ + g_return_val_if_fail (xpath, NULL); + + g_debug ("opening database at %s (writable)", xpath); + + try { + return reinterpret_cast<MuStore*>(new Store (xpath, false/*!readonly*/)); + + } catch (const Mu::Error& me) { + if (me.code() == Mu::Error::Code::SchemaMismatch) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN_SCHEMA_MISMATCH, + "%s", me.what()); + return NULL; + } + } catch (const Xapian::DatabaseLockError& dle) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK, + "database @ %s is write-locked", xpath); + return NULL; + } catch (const Xapian::Error& dbe) { + g_warning ("failed to open database @ %s: %s", xpath, + dbe.get_error_string() ? dbe.get_error_string() : "something went wrong"); + } + + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN_CANNOT_OPEN, + "failed to open database @ %s", xpath); + + return NULL; +} + + +MuStore* +mu_store_new_create (const char* xpath, const char *root_maildir, + const char **personal_addresses, GError **err) +{ + g_return_val_if_fail (xpath, NULL); + g_return_val_if_fail (root_maildir, NULL); + + g_debug ("create database at %s (root-maildir=%s)", xpath, root_maildir); + + try { + StringVec addrs; + for (auto i = 0; personal_addresses && personal_addresses[i]; ++i) + addrs.emplace_back(personal_addresses[i]); + + return reinterpret_cast<MuStore*>( + new Store (xpath, std::string{root_maildir}, addrs)); + + } catch (const Xapian::DatabaseLockError& dle) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK, + "database @ %s is write-locked already", xpath); + } catch (...) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN, + "error opening database @ %s", xpath); + } + + return NULL; +} + + +MuStore* +mu_store_ref (MuStore* store) +{ + g_return_val_if_fail (store, NULL); + g_return_val_if_fail (self(store)->priv()->ref_count_ > 0, NULL); + + ++self(store)->priv()->ref_count_; + return store; +} + + +MuStore* +mu_store_unref (MuStore* store) +{ + g_return_val_if_fail (store, NULL); + g_return_val_if_fail (self(store)->priv()->ref_count_ > 0, NULL); + + auto me = reinterpret_cast<Mu::Store*>(store); + + if (--me->priv()->ref_count_ == 0) + delete me; + + return NULL; +} + +gboolean +mu_store_is_read_only (const MuStore *store) +{ + g_return_val_if_fail (store, FALSE); + + try { + return self(store)->read_only() ? TRUE : FALSE; + + } MU_XAPIAN_CATCH_BLOCK_RETURN(FALSE); + +} + + +const MuContacts* +mu_store_contacts (MuStore *store) +{ + g_return_val_if_fail (store, FALSE); + + try { + return self(store)->contacts().mu_contacts(); + + } MU_XAPIAN_CATCH_BLOCK_RETURN(FALSE); +} + +unsigned +mu_store_count (const MuStore *store, GError **err) +{ + g_return_val_if_fail (store, (unsigned)-1); + + try { + return self(store)->size(); + + } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(err, MU_ERROR_XAPIAN, + (unsigned)-1); +} + +const char* +mu_store_schema_version (const MuStore *store) +{ + g_return_val_if_fail (store, NULL); + + return self(store)->schema_version().c_str(); +} + +XapianDatabase* +mu_store_get_read_only_database (MuStore *store) +{ + g_return_val_if_fail (store, NULL); + return (XapianWritableDatabase*)self(store)->priv()->db().get(); +} + + + + +gboolean +mu_store_contains_message (const MuStore *store, const char* path) +{ + g_return_val_if_fail (store, FALSE); + g_return_val_if_fail (path, FALSE); + + try { + return self(store)->contains_message(path) ? TRUE : FALSE; + + } MU_XAPIAN_CATCH_BLOCK_RETURN(FALSE); +} + +unsigned +mu_store_get_docid_for_path (const MuStore *store, const char* path, GError **err) +{ + g_return_val_if_fail (store, FALSE); + g_return_val_if_fail (path, FALSE); + + try { + const std::string term (get_uid_term(path)); + Xapian::Query query (term); + Xapian::Enquire enq (*self(store)->priv()->db().get()); + + enq.set_query (query); + + Xapian::MSet mset (enq.get_mset (0,1)); + if (mset.empty()) + throw Mu::Error(Error::Code::NotFound, + "message @ %s not found in store", path); + + return *mset.begin(); + + } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(err, MU_ERROR_XAPIAN, + MU_STORE_INVALID_DOCID); +} + + +MuError +mu_store_foreach (MuStore *store, + MuStoreForeachFunc func, void *user_data, GError **err) +{ + g_return_val_if_fail (store, MU_ERROR); + g_return_val_if_fail (func, MU_ERROR); + + try { + Xapian::Enquire enq (*self(store)->priv()->db().get()); + + enq.set_query (Xapian::Query::MatchAll); + enq.set_cutoff (0,0); + + Xapian::MSet matches(enq.get_mset (0, self(store)->size())); + if (matches.empty()) + return MU_OK; /* database is empty */ + + for (Xapian::MSet::iterator iter = matches.begin(); + iter != matches.end(); ++iter) { + Xapian::Document doc (iter.get_document()); + const std::string path(doc.get_value(MU_MSG_FIELD_ID_PATH)); + MuError res = func (path.c_str(), user_data); + if (res != MU_OK) + return res; + } + + } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(err, MU_ERROR_XAPIAN, + MU_ERROR_XAPIAN); + + return MU_OK; +} + + +MuMsg* +mu_store_get_msg (const MuStore *store, unsigned docid, GError **err) +{ + g_return_val_if_fail (store, NULL); + g_return_val_if_fail (docid != 0, NULL); + + return self(store)->find_message(docid); +} + + +const char* +mu_store_database_path (const MuStore *store) +{ + g_return_val_if_fail (store, NULL); + + return self(store)->database_path().c_str(); +} + + +const char* +mu_store_root_maildir (const MuStore *store) +{ + g_return_val_if_fail (store, NULL); + + return self(store)->root_maildir().c_str(); +} + + +time_t +mu_store_created (const MuStore *store) +{ + g_return_val_if_fail (store, (time_t)0); + + return self(store)->created(); +} + +char** +mu_store_personal_addresses (const MuStore *store) +{ + g_return_val_if_fail (store, NULL); + + const auto size = self(store)->personal_addresses().size(); + auto addrs = g_new0 (char*, 1 + size); + for (size_t i = 0; i != size; ++i) + addrs[i] = g_strdup(self(store)->personal_addresses()[i].c_str()); + + return addrs; +} + +void +mu_store_flush (MuStore *store) try { + + g_return_if_fail (store); + + if (self(store)->priv()->in_transaction_) + mutable_self(store)->commit_transaction (); + + mutable_self(store)->priv()->wdb()->set_metadata( + ContactsKey, self(store)->priv()->contacts_.serialize()); + +} MU_XAPIAN_CATCH_BLOCK; + +static void +add_terms_values_date (Xapian::Document& doc, MuMsg *msg, MuMsgFieldId mfid) +{ + const auto dstr = Mu::date_to_time_t_string ( + (time_t)mu_msg_get_field_numeric (msg, mfid)); + + doc.add_value ((Xapian::valueno)mfid, dstr); +} + +static void +add_terms_values_size (Xapian::Document& doc, MuMsg *msg, MuMsgFieldId mfid) +{ + const auto szstr = + Mu::size_to_string (mu_msg_get_field_numeric (msg, mfid)); + doc.add_value ((Xapian::valueno)mfid, szstr); +} + +G_GNUC_CONST +static const std::string& +flag_val (char flagchar) +{ + static const std::string + pfx (prefix(MU_MSG_FIELD_ID_FLAGS)), + draftstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_DRAFT))), + flaggedstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_FLAGGED))), + passedstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_PASSED))), + repliedstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_REPLIED))), + seenstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_SEEN))), + trashedstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_TRASHED))), + newstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_NEW))), + signedstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_SIGNED))), + cryptstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_ENCRYPTED))), + attachstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_HAS_ATTACH))), + unreadstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_UNREAD))), + liststr (pfx + (char)tolower(mu_flag_char(MU_FLAG_LIST))); + + switch (flagchar) { + + case 'D': return draftstr; + case 'F': return flaggedstr; + case 'P': return passedstr; + case 'R': return repliedstr; + case 'S': return seenstr; + case 'T': return trashedstr; + + case 'N': return newstr; + + case 'z': return signedstr; + case 'x': return cryptstr; + case 'a': return attachstr; + case 'l': return liststr; + + case 'u': return unreadstr; + + default: + g_return_val_if_reached (flaggedstr); + return flaggedstr; + } +} + +/* pre-calculate; optimization */ +G_GNUC_CONST static const std::string& +prio_val (MuMsgPrio prio) +{ + static const std::string pfx (prefix(MU_MSG_FIELD_ID_PRIO)); + + static const std::string + low (pfx + std::string(1, mu_msg_prio_char(MU_MSG_PRIO_LOW))), + norm (pfx + std::string(1, mu_msg_prio_char(MU_MSG_PRIO_NORMAL))), + high (pfx + std::string(1, mu_msg_prio_char(MU_MSG_PRIO_HIGH))); + + switch (prio) { + case MU_MSG_PRIO_LOW: return low; + case MU_MSG_PRIO_NORMAL: return norm; + case MU_MSG_PRIO_HIGH: return high; + default: + g_return_val_if_reached (norm); + return norm; + } +} + + +static void // add term, truncate if needed. +add_term (Xapian::Document& doc, const std::string& term) +{ + if (term.length() < MU_STORE_MAX_TERM_LENGTH) + doc.add_term(term); + else + doc.add_term(term.substr(0, MU_STORE_MAX_TERM_LENGTH)); +} + + + +static void +add_terms_values_number (Xapian::Document& doc, MuMsg *msg, MuMsgFieldId mfid) +{ + gint64 num = mu_msg_get_field_numeric (msg, mfid); + + const std::string numstr (Xapian::sortable_serialise((double)num)); + doc.add_value ((Xapian::valueno)mfid, numstr); + + if (mfid == MU_MSG_FIELD_ID_FLAGS) { + const char *cur = mu_flags_to_str_s + ((MuFlags)num,(MuFlagType)MU_FLAG_TYPE_ANY); + g_return_if_fail (cur); + while (*cur) { + add_term (doc, flag_val(*cur)); + ++cur; + } + + } else if (mfid == MU_MSG_FIELD_ID_PRIO) + add_term (doc, prio_val((MuMsgPrio)num)); +} + + +/* for string and string-list */ +static void +add_terms_values_str (Xapian::Document& doc, const char *val, MuMsgFieldId mfid) +{ + const auto flat = Mu::utf8_flatten (val); + + if (mu_msg_field_xapian_index (mfid)) { + Xapian::TermGenerator termgen; + termgen.set_document (doc); + termgen.index_text (flat, 1, prefix(mfid)); + } + + if (mu_msg_field_xapian_term(mfid)) + add_term(doc, prefix(mfid) + flat); + +} + +static void +add_terms_values_string (Xapian::Document& doc, MuMsg *msg, MuMsgFieldId mfid) +{ + const char *orig; + + if (!(orig = mu_msg_get_field_string (msg, mfid))) + return; /* nothing to do */ + + /* the value is what we display in search results; the + * unchanged original */ + if (mu_msg_field_xapian_value(mfid)) + doc.add_value ((Xapian::valueno)mfid, orig); + + add_terms_values_str (doc, orig, mfid); +} + +static void +add_terms_values_string_list (Xapian::Document& doc, MuMsg *msg, + MuMsgFieldId mfid) +{ + const GSList *lst; + + lst = mu_msg_get_field_string_list (msg, mfid); + if (!lst) + return; + + if (mu_msg_field_xapian_value (mfid)) { + gchar *str; + str = mu_str_from_list (lst, ','); + if (str) + doc.add_value ((Xapian::valueno)mfid, str); + g_free (str); + } + + if (mu_msg_field_xapian_term (mfid)) { + for (; lst; lst = g_slist_next ((GSList*)lst)) + add_terms_values_str (doc, (const gchar*)lst->data, + mfid); + } +} + + +struct PartData { + PartData (Xapian::Document& doc, MuMsgFieldId mfid): + _doc (doc), _mfid(mfid) {} + Xapian::Document _doc; + MuMsgFieldId _mfid; +}; + +/* index non-body text parts */ +static void +maybe_index_text_part (MuMsg *msg, MuMsgPart *part, PartData *pdata) +{ + char *txt; + Xapian::TermGenerator termgen; + + /* only deal with attachments/messages; inlines are indexed as + * body parts */ + if (!(part->part_type & MU_MSG_PART_TYPE_ATTACHMENT) && + !(part->part_type & MU_MSG_PART_TYPE_MESSAGE)) + return; + + txt = mu_msg_part_get_text (msg, part, MU_MSG_OPTION_NONE); + if (!txt) + return; + + termgen.set_document(pdata->_doc); + const auto str = Mu::utf8_flatten (txt); + g_free (txt); + + termgen.index_text (str, 1, prefix(MU_MSG_FIELD_ID_EMBEDDED_TEXT)); +} + + +static void +each_part (MuMsg *msg, MuMsgPart *part, PartData *pdata) +{ + char *fname; + static const std::string + file (prefix(MU_MSG_FIELD_ID_FILE)), + mime (prefix(MU_MSG_FIELD_ID_MIME)); + + /* save the mime type of any part */ + if (part->type) { + char ctype[MU_STORE_MAX_TERM_LENGTH + 1]; + g_snprintf(ctype, sizeof(ctype), "%s/%s", part->type, part->subtype); + add_term(pdata->_doc, mime + ctype); + } + + if ((fname = mu_msg_part_get_filename (part, FALSE))) { + const auto flat = Mu::utf8_flatten (fname); + g_free (fname); + add_term(pdata->_doc, file + flat); + } + + maybe_index_text_part (msg, part, pdata); +} + + +static void +add_terms_values_attach (Xapian::Document& doc, MuMsg *msg, + MuMsgFieldId mfid) +{ + PartData pdata (doc, mfid); + mu_msg_part_foreach (msg, MU_MSG_OPTION_RECURSE_RFC822, + (MuMsgPartForeachFunc)each_part, &pdata); +} + + +static void +add_terms_values_body (Xapian::Document& doc, MuMsg *msg, + MuMsgFieldId mfid) +{ + if (mu_msg_get_flags(msg) & MU_FLAG_ENCRYPTED) + return; /* ignore encrypted bodies */ + + auto str = mu_msg_get_body_text (msg, MU_MSG_OPTION_NONE); + if (!str) /* FIXME: html->txt fallback needed */ + str = mu_msg_get_body_html (msg, MU_MSG_OPTION_NONE); + if (!str) + return; /* no body... */ + + Xapian::TermGenerator termgen; + termgen.set_document(doc); + + const auto flat = Mu::utf8_flatten(str); + termgen.index_text (flat, 1, prefix(mfid)); +} + +struct MsgDoc { + Xapian::Document *_doc; + MuMsg *_msg; + Store *_store; + /* callback data, to determine whether this message is 'personal' */ + gboolean _personal; + const StringVec *_my_addresses; +}; + + +static void +add_terms_values_default (MuMsgFieldId mfid, MsgDoc *msgdoc) +{ + if (mu_msg_field_is_numeric (mfid)) + add_terms_values_number + (*msgdoc->_doc, msgdoc->_msg, mfid); + else if (mu_msg_field_is_string (mfid)) + add_terms_values_string + (*msgdoc->_doc, msgdoc->_msg, mfid); + else if (mu_msg_field_is_string_list(mfid)) + add_terms_values_string_list + (*msgdoc->_doc, msgdoc->_msg, mfid); + else + g_return_if_reached (); +} + +static void +add_terms_values (MuMsgFieldId mfid, MsgDoc* msgdoc) +{ + /* note: contact-stuff (To/Cc/From) will handled in + * each_contact_info, not here */ + if (!mu_msg_field_xapian_index(mfid) && + !mu_msg_field_xapian_term(mfid) && + !mu_msg_field_xapian_value(mfid)) + return; + + switch (mfid) { + case MU_MSG_FIELD_ID_DATE: + add_terms_values_date (*msgdoc->_doc, msgdoc->_msg, mfid); + break; + case MU_MSG_FIELD_ID_SIZE: + add_terms_values_size (*msgdoc->_doc, msgdoc->_msg, mfid); + break; + case MU_MSG_FIELD_ID_BODY_TEXT: + add_terms_values_body (*msgdoc->_doc, msgdoc->_msg, mfid); + break; + /* note: add_terms_values_attach handles _FILE, _MIME and + * _ATTACH_TEXT msgfields */ + case MU_MSG_FIELD_ID_FILE: + add_terms_values_attach (*msgdoc->_doc, msgdoc->_msg, mfid); + break; + case MU_MSG_FIELD_ID_MIME: + case MU_MSG_FIELD_ID_EMBEDDED_TEXT: + break; + case MU_MSG_FIELD_ID_THREAD_ID: + case MU_MSG_FIELD_ID_UID: + break; /* already taken care of elsewhere */ + default: + return add_terms_values_default (mfid, msgdoc); + } +} + + +static const std::string& +xapian_pfx (MuMsgContact *contact) +{ + static const std::string empty; + + /* use ptr to string to prevent copy... */ + switch (contact->type) { + case MU_MSG_CONTACT_TYPE_TO: + return prefix(MU_MSG_FIELD_ID_TO); + case MU_MSG_CONTACT_TYPE_FROM: + return prefix(MU_MSG_FIELD_ID_FROM); + case MU_MSG_CONTACT_TYPE_CC: + return prefix(MU_MSG_FIELD_ID_CC); + case MU_MSG_CONTACT_TYPE_BCC: + return prefix(MU_MSG_FIELD_ID_BCC); + default: + g_warning ("unsupported contact type %u", + (unsigned)contact->type); + return empty; + } +} + + +static void +add_address_subfields (Xapian::Document& doc, const char *addr, + const std::string& pfx) +{ + const char *at, *domain_part; + char *name_part; + + /* add "foo" and "bar.com" as terms as well for + * "foo@bar.com" */ + if (G_UNLIKELY(!(at = (g_strstr_len (addr, -1, "@"))))) + return; + + name_part = g_strndup(addr, at - addr); // foo + domain_part = at + 1; + + add_term(doc, pfx + name_part); + add_term(doc, pfx + domain_part); + + g_free (name_part); +} + +static gboolean +each_contact_info (MuMsgContact *contact, MsgDoc *msgdoc) +{ + /* for now, don't store reply-to addresses */ + if (mu_msg_contact_type (contact) == MU_MSG_CONTACT_TYPE_REPLY_TO) + return TRUE; + + const std::string pfx (xapian_pfx(contact)); + if (pfx.empty()) + return TRUE; /* unsupported contact type */ + + if (!mu_str_is_empty(contact->name)) { + Xapian::TermGenerator termgen; + termgen.set_document (*msgdoc->_doc); + const auto flat = Mu::utf8_flatten(contact->name); + termgen.index_text (flat, 1, pfx); + } + + if (!mu_str_is_empty(contact->email)) { + const auto flat = Mu::utf8_flatten(contact->email); + add_term(*msgdoc->_doc, pfx + flat); + add_address_subfields (*msgdoc->_doc, contact->email, pfx); + /* store it also in our contacts cache */ + auto& contacts = msgdoc->_store->priv()->contacts_; + contacts.add(Mu::ContactInfo(contact->full_address, + contact->email, + contact->name ? contact->name : "", + msgdoc->_personal, + mu_msg_get_date(msgdoc->_msg))); + } + + return TRUE; +} + + +static gboolean +each_contact_check_if_personal (MuMsgContact *contact, MsgDoc *msgdoc) +{ + if (msgdoc->_personal || !contact->email) + return TRUE; + + for (const auto& cur : *msgdoc->_my_addresses) { + if (g_ascii_strcasecmp + (contact->email, + (const char*)cur.c_str()) == 0) { + msgdoc->_personal = TRUE; + break; + } + } + + return TRUE; +} + +static Xapian::Document +new_doc_from_message (MuStore *store, MuMsg *msg) +{ + Xapian::Document doc; + MsgDoc docinfo = {&doc, msg, mutable_self(store), 0, NULL}; + + mu_msg_field_foreach ((MuMsgFieldForeachFunc)add_terms_values, &docinfo); + + /* determine whether this is 'personal' email, ie. one of my + * e-mail addresses is explicitly mentioned -- it's not a + * mailing list message. Callback will update docinfo->_personal */ + const auto& personal_addresses = self(store)->personal_addresses(); + if (personal_addresses.size()) { + docinfo._my_addresses = &personal_addresses; + mu_msg_contact_foreach + (msg, + (MuMsgContactForeachFunc)each_contact_check_if_personal, + &docinfo); + } + + /* also store the contact-info as separate terms, and add it + * to the cache */ + mu_msg_contact_foreach (msg, (MuMsgContactForeachFunc)each_contact_info, + &docinfo); + + // g_printerr ("\n--%s\n--\n", doc.serialise().c_str()); + + return doc; +} + +static void +update_threading_info (Xapian::WritableDatabase* db, + MuMsg *msg, Xapian::Document& doc) +{ + const GSList *refs; + + // refs contains a list of parent messages, with the oldest + // one first until the last one, which is the direct parent of + // the current message. of course, it may be empty. + // + // NOTE: there may be cases where the list is truncated; we happily + // ignore that case. + refs = mu_msg_get_references (msg); + + char thread_id[16+1]; + hash_str(thread_id, sizeof(thread_id), + refs ? (const char*)refs->data : mu_msg_get_msgid (msg)); + + add_term (doc, prefix(MU_MSG_FIELD_ID_THREAD_ID) + thread_id); + doc.add_value((Xapian::valueno)MU_MSG_FIELD_ID_THREAD_ID, thread_id); +} + + +static unsigned +add_or_update_msg (MuStore *store, unsigned docid, MuMsg *msg, GError **err) +{ + g_return_val_if_fail (store, MU_STORE_INVALID_DOCID); + g_return_val_if_fail (msg, MU_STORE_INVALID_DOCID); + + try { + Xapian::docid id; + Xapian::Document doc (new_doc_from_message(store, msg)); + const std::string term (get_uid_term (mu_msg_get_path(msg))); + + auto self = mutable_self(store); + auto wdb = self->priv()->wdb(); + + if (!self->in_transaction()) + self->priv()->begin_transaction(); + + add_term (doc, term); + + // update the threading info if this message has a message id + if (mu_msg_get_msgid (msg)) + update_threading_info (wdb.get(), msg, doc); + + if (docid == 0) + id = wdb->replace_document (term, doc); + else { + wdb->replace_document (docid, doc); + id = docid; + } + + if (++self->priv()->dirtiness_ >= BatchSize) + self->priv()->commit_transaction(); + + return id; + + } MU_XAPIAN_CATCH_BLOCK_G_ERROR (err, MU_ERROR_XAPIAN_STORE_FAILED); + + return MU_STORE_INVALID_DOCID; +} + +unsigned +mu_store_add_msg (MuStore *store, MuMsg *msg, GError **err) +{ + g_return_val_if_fail (store, MU_STORE_INVALID_DOCID); + g_return_val_if_fail (msg, MU_STORE_INVALID_DOCID); + + return add_or_update_msg (store, 0, msg, err); +} + +unsigned +mu_store_update_msg (MuStore *store, unsigned docid, MuMsg *msg, GError **err) +{ + g_return_val_if_fail (store, MU_STORE_INVALID_DOCID); + g_return_val_if_fail (msg, MU_STORE_INVALID_DOCID); + g_return_val_if_fail (docid != 0, MU_STORE_INVALID_DOCID); + + return add_or_update_msg (store, docid, msg, err); +} + +unsigned +mu_store_add_path (MuStore *store, const char *path, GError **err) try { + + MuMsg *msg; + unsigned docid; + + g_return_val_if_fail (store, FALSE); + g_return_val_if_fail (path, FALSE); + + const auto maildir{maildir_from_path(self(store)->root_maildir(), path)}; + msg = mu_msg_new_from_file (path, maildir.c_str(), err); + if (!msg) + return MU_STORE_INVALID_DOCID; + + docid = add_or_update_msg (store, 0, msg, err); + mu_msg_unref (msg); + + return docid; + +} catch (const Mu::Error& me) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN, + "%s", me.what()); + return MU_STORE_INVALID_DOCID; +} catch (...) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_INTERNAL, + "caught exception"); + return MU_STORE_INVALID_DOCID; +} + +XapianWritableDatabase* +mu_store_get_writable_database (MuStore *store) +{ + g_return_val_if_fail (store, NULL); + + return (XapianWritableDatabase*)mutable_self(store)->priv()->wdb().get(); +} + + +gboolean +mu_store_remove_path (MuStore *store, const char *msgpath) +{ + g_return_val_if_fail (store, FALSE); + g_return_val_if_fail (msgpath, FALSE); + + try { + const std::string term{(get_uid_term(msgpath))}; + auto wdb = mutable_self(store)->priv()->wdb(); + + wdb->delete_document (term); + //store->inc_processed(); + + return TRUE; + + } MU_XAPIAN_CATCH_BLOCK_RETURN (FALSE); +} + + +gboolean +mu_store_set_dirstamp (MuStore *store, const char* dirpath, + time_t stamp, GError **err) +{ + g_return_val_if_fail (store, FALSE); + g_return_val_if_fail (dirpath, FALSE); + + mutable_self(store)->set_dirstamp(dirpath, stamp); + + return TRUE; +} + +time_t +mu_store_get_dirstamp (const MuStore *store, const char *dirpath, GError **err) +{ + g_return_val_if_fail (store, 0); + g_return_val_if_fail (dirpath, 0); + + return self(store)->dirstamp(dirpath); +} + +void +mu_store_print_info (const MuStore *store, gboolean nocolor) +{ + const auto green{nocolor ? "" : MU_COLOR_GREEN}; + const auto def{nocolor ? "" : MU_COLOR_DEFAULT}; + + std::cout << "database-path : " + << green << self(store)->database_path() << def << "\n" + << "messages in store : " + << green << self(store)->size() << def << "\n" + << "schema-version : " + << green << self(store)->schema_version() << def << "\n"; + + const auto created{mu_store_created (store)}; + const auto tstamp{localtime (&created)}; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-y2k" + char tbuf[64]; + strftime (tbuf, sizeof(tbuf), "%c", tstamp); +#pragma GCC diagnostic pop + + std::cout << "created : " << green << tbuf << def << "\n" + << "maildir : " + << green << self(store)->root_maildir() << def << "\n"; + + std::cout << ("personal-addresses : "); + + auto addrs{mu_store_personal_addresses (store)}; + if (!addrs || g_strv_length(addrs) == 0) + std::cout << green << "<none>" << def << "\n"; + else { + for (auto i = 0U; addrs[i]; ++i) { + std::cout << (i != 0 ? " " : "") + << green << addrs[i] << def << "\n"; + } + } + + g_strfreev(addrs); +} +} diff --git a/lib/mu-store.hh b/lib/mu-store.hh new file mode 100644 index 0000000..f34c70b --- /dev/null +++ b/lib/mu-store.hh @@ -0,0 +1,568 @@ +/* +** Copyright (C) 2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_STORE_HH__ +#define __MU_STORE_HH__ + +#include <mu-msg.h> + +#ifdef __cplusplus + +#include "mu-contacts.hh" + +#include <xapian.h> + +#include <string> +#include <vector> +#include <ctime> + +#include <utils/mu-utils.hh> + +namespace Mu { + +class Store { +public: + /** + * Construct a store for an existing document database + * + * @param path path to the database + * @param readonly whether to open the database in read-only mode + */ + Store (const std::string& path, bool readonly=true); + + /** + * Construct a store for a not-yet-existing document database + * + * @param path path to the database + * @param maildir maildir to use for this store + * @param personal_addressesaddresses that should be recognized as + * 'personal' for identifying personal messages. + */ + Store (const std::string& path, const std::string& maildir, + const StringVec& personal_addresses); + + /** + * DTOR + */ + ~Store(); + + /** + * Is the store read-only? + * + * @return true or false + */ + bool read_only() const; + + /** + * Path to the database; this is some subdirectory of the path + * passed to the constructor. + * + * @return the database path + */ + const std::string& database_path() const; + + /** + * Path to the top-level Maildir + * + * @return the maildir + */ + const std::string& root_maildir() const; + + /** + * Version of the database-schema + * + * @return the maildir + */ + const std::string& schema_version() const; + + + /** + * Time of creation of the store + * + * @return creation time + */ + std::time_t created() const; + + /** + * Get a vec with the personal addresses + * + * @return personal addresses + */ + const StringVec& personal_addresses() const; + + /** + * Get the Contacts object for this store + * + * @return the Contacts object + */ + const Contacts& contacts() const; + + /** + * Add a message to the store. + * + * @param path the message path. + * + * @return the doc id of the added message + */ + unsigned add_message (const std::string& path); + + /** + * Add a message to the store. + * + * @param path the message path. + * + * @return true if removing happened; false otherwise. + */ + bool remove_message (const std::string& path); + + /** + * Fina message in the store. + * + * @param docid doc id for the message to find + * + * @return a message (owned by caller), or nullptr + */ + MuMsg* find_message (unsigned docid) const; + + /** + * does a certain message exist in the store already? + * + * @param path the message path + * + * @return true if the message exists in the store, false otherwise + */ + bool contains_message (const std::string& path) const; + + /** + * Get the timestamp for some directory + * + * @param path the path + * + * @return the timestamp, or 0 if not found + */ + time_t dirstamp (const std::string& path) const; + + /** + * Set the timestamp for some directory + * + * @param path a filesystem path + * @param tstamp the timestamp for that path + */ + void set_dirstamp (const std::string& path, time_t tstamp); + + /** + * Get the number of documents in the document database + * + * @return the number + */ + std::size_t size() const; + + /** + * Is the database empty? + * + * @return true or false + */ + bool empty() const; + + /** + * Begin a database transaction + */ + void begin_transaction(); + + /** + * Commit a database transaction + * + */ + void commit_transaction(); + + /** + * Are we in a transaction? + * + * @return true or false + */ + bool in_transaction() const; + + + /** + * Get a reference to the private data. For internal use. + * + * @return private reference. + */ + struct Private; + std::unique_ptr<Private>& priv() { return priv_; } + const std::unique_ptr<Private>& priv() const { return priv_; } + +private: + std::unique_ptr<Private> priv_; +}; + +} // namespace Mu + + +#endif /*__cplusplus*/ + +#include <glib.h> +#include <inttypes.h> +#include <utils/mu-util.h> +#include <mu-contacts.hh> + +G_BEGIN_DECLS + +struct MuStore_; +typedef struct MuStore_ MuStore; + +/* http://article.gmane.org/gmane.comp.search.xapian.general/3656 */ +#define MU_STORE_MAX_TERM_LENGTH (240) + + +/** + * create a new read-only Xapian store, for querying documents + * + * @param path the path to the database + * @param err to receive error info or NULL. err->code is MuError value + * + * @return a new MuStore object with ref count == 1, or NULL in case of error; + * free with mu_store_unref + */ +MuStore* mu_store_new_readable (const char* xpath, GError **err) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +/** + * create a new writable Xapian store, a place to store documents + * + * @param path the path to the database + * @param err to receive error info or NULL. err->code is MuError value + * + * @return a new MuStore object with ref count == 1, or NULL in case + * of error; free with mu_store_unref + */ +MuStore* mu_store_new_writable (const char *xpath, GError **err) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +/** + * create a new writable Xapian store, a place to store documents, and + * create/overwrite the existing database. + * + * @param path the path to the database + * @param path to the maildir + * @param personal_addressesaddresses that should be recognized as + * 'personal' for identifying personal messages. + * @param err to receive error info or NULL. err->code is MuError value + * + * @return a new MuStore object with ref count == 1, or NULL in case + * of error; free with mu_store_unref + */ +MuStore* mu_store_new_create (const char *xpath, const char *maildir, + const char **personal_addresses, GError **err) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +/** + * increase the reference count for this store with 1 + * + * @param store a valid store object + * + * @return the same store with increased ref count, or NULL in case of + * error + */ +MuStore* mu_store_ref (MuStore *store); + +/** + * decrease the reference count for this store with 1 + * + * @param store a valid store object + * + * @return NULL + */ +MuStore* mu_store_unref (MuStore *store); + + +/** + * we need this when using Xapian::(Writable)Database* from C + */ +typedef gpointer XapianWritableDatabase; +typedef gpointer XapianDatabase; + + +/** + * get the underlying writable database object for this store; not + * that this pointer becomes in valid after mu_store_destroy + * + * @param store a valid store + * + * @return a Xapian::WritableDatabase (you'll need to cast in C++), or + * NULL in case of error. + */ +XapianWritableDatabase* mu_store_get_writable_database (MuStore *store); + + +/** + * get the underlying read-only database object for this store; not that this + * pointer becomes in valid after mu_store_destroy + * + * @param store a valid store + * + * @return a Xapian::Database (you'll need to cast in C++), or + * NULL in case of error. + */ +XapianDatabase* mu_store_get_read_only_database (MuStore *store); + +/** + * get the version of the xapian database (ie., the version of the + * 'schema' we are using). If this version != MU_STORE_SCHEMA_VERSION, + * it's means we need to a full reindex. + * + * @param store the store to inspect + * + * @return the version of the database as a newly allocated string + * (free with g_free); if there is no version yet, it will return NULL + */ +const char* mu_store_schema_version (const MuStore* store); + + +/** + * Get the database-path for this message store + * + * @param store the store to inspetc + * + * @return the database-path + */ +const char *mu_store_database_path (const MuStore *store); + + +/** + * Get the root-maildir for this message store. + * + * @param store the store + * + * @return the maildir. + */ +const char *mu_store_root_maildir(const MuStore *store); + + +/** + * Get the time this database was created + * + * @param store the store + * + * @return the maildir. + */ +time_t mu_store_created(const MuStore *store); + +/** + * Get the list of personal addresses from the store + * + * @param store the message store + * + * @return the list of personal addresses, or NULL in case of error. + * + * Free with g_strfreev(). + */ +char** mu_store_personal_addresses (const MuStore *store); + +/** + * Get the a MuContacts* ptr for this store. + * + * @param store a store + * + * @return the contacts ptr + */ +const MuContacts* mu_store_contacts (MuStore *store); + + +/** + * get the numbers of documents in the database + * + * @param index a valid MuStore instance + * @param err to receive error info or NULL. err->code is MuError value + * + * @return the number of documents in the database; (unsigned)-1 in + * case of error + */ +unsigned mu_store_count (const MuStore *store, GError **err); + + +/** + * try to flush/commit all outstanding work to the database and the contacts + * cache. + * + * @param store a valid xapian store + */ +void mu_store_flush (MuStore *store); + +#define MU_STORE_INVALID_DOCID 0 + +/** + * store an email message in the XapianStore + * + * @param store a valid store + * @param msg a valid message + * @param err receives error information, if any, or NULL + * + * @return the docid of the stored message, or 0 + * (MU_STORE_INVALID_DOCID) in case of error + */ +unsigned mu_store_add_msg (MuStore *store, MuMsg *msg, GError **err); + + +/** + * update an email message in the XapianStore + * + * @param store a valid store + * @param the docid for the message + * @param msg a valid message + * @param err receives error information, if any, or NULL + * + * @return the docid of the stored message, or 0 + * (MU_STORE_INVALID_DOCID) in case of error + */ +unsigned mu_store_update_msg (MuStore *store, unsigned docid, MuMsg *msg, + GError **err); + +/** + * store an email message in the XapianStore; similar to + * mu_store_store, but instead takes a path as parameter instead of a + * MuMsg* + * + * @param store a valid store + * @param path full filesystem path to a valid message + * @param err receives error information, if any, or NULL + * + * @return the docid of the stored message, or 0 + * (MU_STORE_INVALID_DOCID) in case of error + */ +unsigned mu_store_add_path (MuStore *store, const char *path, GError **err); + +/** + * remove a message from the database based on its path + * + * @param store a valid store + * @param msgpath path of the message (note, this is only used to + * *identify* the message; a common use of this function is to remove + * a message from the database, for which there is no message anymore + * in the filesystem. + * + * @return TRUE if it succeeded, FALSE otherwise + */ +gboolean mu_store_remove_path (MuStore *store, const char* msgpath); + +/** + * does a certain message exist in the database already? + * + * @param store a store + * @param path the message path + * + * @return TRUE if the message exists, FALSE otherwise + */ +gboolean mu_store_contains_message (const MuStore *store, const char* path); + +/** + * get the docid for message at path + * + * @param store a store + * @param path the message path + * @param err to receive error info or NULL. err->code is MuError value + * + * @return the docid if the message was found, MU_STORE_INVALID_DOCID (0) otherwise + * */ +unsigned mu_store_get_docid_for_path (const MuStore *store, const char* path, + GError **err); + +/** + * store a timestamp for a directory + * + * @param store a valid store + * @param dirpath path to some directory + * @param stamp a timestamp + * @param err to receive error info or NULL. err->code is MuError value + * + * @return TRUE if setting the timestamp succeeded, FALSE otherwise + */ +gboolean mu_store_set_dirstamp (MuStore *store, const char* dirpath, + time_t stamp, GError **err); + +/** + * get the timestamp for a directory + * + * @param store a valid store + * @param msgpath path to some directory + * @param err to receive error info or NULL. err->code is MuError value + * + * @return the timestamp, or 0 in case of error + */ +time_t mu_store_get_dirstamp (const MuStore *store, const char* dirpath, + GError **err); + +/** + * check whether this store is read-only + * + * @param store a store + * + * @return TRUE if the store is read-only, FALSE otherwise (and in + * case of error) + */ +gboolean mu_store_is_read_only (const MuStore *store); + +/** + * call a function for each document in the database + * + * @param self a valid store + * @param func a callback function to to call for each document + * @param user_data a user pointer passed to the callback function + * @param err to receive error info or NULL. err->code is MuError value + * + * @return MU_OK if all went well, MU_STOP if the foreach was interrupted, + * MU_ERROR in case of error + */ +typedef MuError (*MuStoreForeachFunc) (const char* path, gpointer user_data); +MuError mu_store_foreach (MuStore *self, MuStoreForeachFunc func, + void *user_data, GError **err); + +/** + * check if the database is locked for writing + * + * @param xpath path to a xapian database + * + * @return TRUE if it is locked, FALSE otherwise (or in case of error) + */ +gboolean mu_store_database_is_locked (const gchar *xpath); + +/** + * get a specific message, based on its Xapian docid + * + * @param self a valid MuQuery instance + * @param docid the Xapian docid for the wanted message + * @param err receives error information, or NULL + * + * @return a MuMsg instance (use mu_msg_unref when done with it), or + * NULL in case of error + */ +MuMsg* mu_store_get_msg (const MuStore *self, unsigned docid, GError **err) + G_GNUC_WARN_UNUSED_RESULT; + +/** + * Print some information about the store + * + * @param store a store + * @param nocolor whether to _not_ show color + */ +void mu_store_print_info (const MuStore *store, gboolean nocolor); + + +G_END_DECLS + +#endif /* __MU_STORE_HH__ */ diff --git a/lib/mu-threader.c b/lib/mu-threader.c new file mode 100644 index 0000000..80857ef --- /dev/null +++ b/lib/mu-threader.c @@ -0,0 +1,455 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ +/* +** Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ +#include <math.h> /* for log, ceil */ +#include <string.h> /* for memset */ + +#include "mu-threader.h" +#include "mu-container.h" +#include "utils/mu-str.h" + +/* msg threading implementation based on JWZ's algorithm, as described in: + * http://www.jwz.org/doc/threading.html + * + * the implementation follows the terminology from that doc, so should + * be understandable from that... I did change things a bit though + * + * the end result of the threading operation is a hashtable which maps + * docids (ie., Xapian documents == messages) to 'thread paths'; a + * thread path is a string denoting the 2-dimensional place of a + * message in a list of messages, + * + * Msg1 => 00000 + * Msg2 => 00001 + * Msg3 (child of Msg2) => 00001:00000 + * Msg4 (child of Msg2) => 00001:00001 + * Msg5 (child of Msg4) => 00001:00001:00000 + * Msg6 => 00002 + * + * the padding-0's are added to make them easy to sort using strcmp; + * the number hexadecimal numbers, and the length of the 'segments' + * (the parts separated by the ':') is equal to ceil(log_16(matchnum)) + * + */ + +/* step 1 */ static GHashTable* create_containers (MuMsgIter *iter); +/* step 2 */ static MuContainer *find_root_set (GHashTable *ids); +static MuContainer* prune_empty_containers (MuContainer *root); +/* static void group_root_set_by_subject (GSList *root_set); */ +GHashTable* create_doc_id_thread_path_hash (MuContainer *root, + size_t match_num); + +/* msg threading algorithm, based on JWZ's algorithm, + * http://www.jwz.org/doc/threading.html */ +GHashTable* +mu_threader_calculate (MuMsgIter *iter, size_t matchnum, + MuMsgFieldId sortfield, gboolean descending) +{ + GHashTable *id_table, *thread_ids; + MuContainer *root_set; + + g_return_val_if_fail (iter, FALSE); + g_return_val_if_fail (mu_msg_field_id_is_valid (sortfield) || + sortfield == MU_MSG_FIELD_ID_NONE, + FALSE); + + /* step 1 */ + id_table = create_containers (iter); + if (matchnum == 0) + return id_table; /* just return an empty table */ + + /* step 2 -- the root_set is the list of children without parent */ + root_set = find_root_set (id_table); + + /* step 3: skip until the end; we still need to containers */ + + /* step 4: prune empty containers */ + root_set = prune_empty_containers (root_set); + + /* sort root set */ + if (sortfield != MU_MSG_FIELD_ID_NONE) + root_set = mu_container_sort (root_set, sortfield, descending, + NULL); + + /* step 5: group root set by subject */ + /* group_root_set_by_subject (root_set); */ + + /* sort */ + mu_msg_iter_reset (iter); /* go all the way back */ + + /* finally, deliver the docid => thread-path hash */ + thread_ids = mu_container_thread_info_hash_new (root_set, + matchnum); + + g_hash_table_destroy (id_table); /* step 3*/ + + return thread_ids; +} + +G_GNUC_UNUSED static void +check_dup (const char *msgid, MuContainer *c, GHashTable *hash) +{ + if (g_hash_table_lookup (hash, c)) { + g_warning ("ALREADY!!"); + mu_container_dump (c, FALSE); + g_assert (0); + } else + g_hash_table_insert (hash, c, GUINT_TO_POINTER(TRUE)); +} + + +G_GNUC_UNUSED static void +assert_no_duplicates (GHashTable *ids) +{ + GHashTable *hash; + + hash = g_hash_table_new (g_direct_hash, g_direct_equal); + + g_hash_table_foreach (ids, (GHFunc)check_dup, hash); + + g_hash_table_destroy (hash); +} + + +/* a referred message is a message that is referred by some other + * message */ +static MuContainer* +find_or_create_referred (GHashTable *id_table, const char *msgid, + gboolean *created) +{ + MuContainer *c; + + g_return_val_if_fail (msgid, NULL); + + c = g_hash_table_lookup (id_table, msgid); + *created = !c; + if (!c) { + c = mu_container_new (NULL, 0, msgid); + g_hash_table_insert (id_table, (gpointer)msgid, c); + /* assert_no_duplicates (id_table); */ + } + + + return c; +} + +/* find a container for the given msgid; if it does not exist yet, + * create a new one, and register it */ +static MuContainer* +find_or_create (GHashTable *id_table, MuMsg *msg, guint docid) +{ + MuContainer *c; + const char* msgid; + char fake[32]; + + g_return_val_if_fail (msg, NULL); + g_return_val_if_fail (docid != 0, NULL); + + msgid = mu_msg_get_msgid (msg); + if (!msgid) + msgid = mu_msg_get_path (msg); /* fake it */ + if (!msgid) { /* no path either? seems to happen... */ + g_warning ("message without path"); + g_snprintf (fake, sizeof(fake), "fake:%p", (gpointer)msg); + msgid = fake; + } + + /* XXX the '<none>' works around a crash; find a better + * solution */ + c = g_hash_table_lookup (id_table, msgid); + + /* If id_table contains an empty MuContainer for this ID: * * + * Store this message in the MuContainer's message slot. */ + if (c) { + if (!c->msg) { + c->msg = mu_msg_ref (msg); + c->docid = docid; + return c; + } else { + /* special case, not in the JWZ algorithm: the + * container exists already and has a message; this + * means that we are seeing *another message* with a + * message-id we already saw... create this message, + * and mark it as a duplicate, and a child of the one + * we saw before; use its path as a fake message-id + * */ + MuContainer *c2; + const char* fake_msgid; + + fake_msgid = mu_msg_get_path (msg); + + c2 = mu_container_new (msg, docid, fake_msgid); + c2->flags = MU_CONTAINER_FLAG_DUP; + /*c = */ mu_container_append_children (c, c2); + + g_hash_table_insert (id_table, (gpointer)fake_msgid, c2); + + return NULL; /* don't process this message further */ + } + } else { /* Else: Create a new MuContainer object holding + this message; Index the MuContainer by + Message-ID in id_table. */ + c = mu_container_new (msg, docid, msgid); + g_hash_table_insert (id_table, (gpointer)msgid, c); + /* assert_no_duplicates (id_table); */ + + return c; + } +} + +static gboolean +child_elligible (MuContainer *parent, MuContainer *child, gboolean created) +{ + if (!parent || !child) + return FALSE; + if (child->parent) + return FALSE; + /* if (created) */ + /* return TRUE; */ + if (mu_container_reachable (parent, child)) + return FALSE; + if (mu_container_reachable (child, parent)) + return FALSE; + + return TRUE; +} + + + +static void /* 1B */ +handle_references (GHashTable *id_table, MuContainer *c) +{ + const GSList *refs, *cur; + MuContainer *parent; + gboolean created; + + refs = mu_msg_get_references (c->msg); + if (!refs) + return; /* nothing to do */ + + /* For each element in the message's References field: + + Find a MuContainer object for the given Message-ID: If + there's one in id_table use that; Otherwise, make (and + index) one with a null Message. */ + + /* go over over our list of refs, until 1 before the last... */ + created = FALSE; + for (parent = NULL, cur = refs; cur; cur = g_slist_next (cur)) { + + MuContainer *child; + child = find_or_create_referred (id_table, (gchar*)cur->data, + &created); + + /* if we find the current message in their own refs, break now + so that parent != c in next step */ + if (child == c) + break; + + /*Link the References field's MuContainers together in + * the order implied by the References header. + + If they are already linked, don't change the existing + links. Do not add a link if adding that link would + introduce a loop: that is, before asserting A->B, + search down the children of B to see if A is + reachable, and also search down the children of A to + see if B is reachable. If either is already reachable + as a child of the other, don't add the link. */ + + if (child_elligible (parent, child, created)) + /*parent =*/ + mu_container_append_children (parent, child); + + parent = child; + } + + /* 'parent' points to the last ref: our direct parent; + + Set the parent of this message to be the last element in + References. Note that this message may have a parent + already: this can happen because we saw this ID in a + References field, and presumed a parent based on the other + entries in that field. Now that we have the actual message, + we can be more definitive, so throw away the old parent and + use this new one. Find this MuContainer in the parent's + children list, and unlink it. + + Note that this could cause this message to now have no + parent, if it has no references field, but some message + referred to it as the non-first element of its + references. (Which would have been some kind of lie...) + + Note that at all times, the various ``parent'' and ``child'' fields + must be kept inter-consistent. */ + + /* optimization: if the the message was newly added, it's by + definition not reachable yet */ + + /* So, we move c and its descendants to become a child of parent if: + * both are not NULL + * parent is not a descendant of c. + * both are different from each other (guaranteed in last loop) */ + + if (parent && c && !(c->child && mu_container_reachable (c->child, parent))) { + + /* if c already has a parent, remove c from its parent children + and reparent it, as now we know who is c's parent reliably */ + if (c->parent) { + mu_container_remove_child(c->parent, c); + c->next = c->last = c->parent = NULL; + } + + /*parent = */mu_container_append_children (parent, c); + } +} + + + +/* step 1: create the containers, connect them, and fill the id_table */ +static GHashTable* +create_containers (MuMsgIter *iter) +{ + GHashTable *id_table; + id_table = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, + (GDestroyNotify)mu_container_destroy); + + for (mu_msg_iter_reset (iter); !mu_msg_iter_is_done (iter); + mu_msg_iter_next (iter)) { + + MuContainer *c; + MuMsg *msg; + unsigned docid; + + /* 1.A */ + msg = mu_msg_iter_get_msg_floating (iter); /* don't unref */ + docid = mu_msg_iter_get_docid (iter); + + c = find_or_create (id_table, msg, docid); + + /* 1.B and C */ + if (c) + handle_references (id_table, c); + } + + return id_table; +} + + + +static void +filter_root_set (const gchar *msgid, MuContainer *c, MuContainer **root_set) +{ + /* ignore children */ + if (c->parent) + return; + + /* ignore duplicates */ + if (c->flags & MU_CONTAINER_FLAG_DUP) + return; + + if (*root_set == NULL) { + *root_set = c; + return; + } else + *root_set = mu_container_append_siblings (*root_set, c); +} + + +/* 2. Walk over the elements of id_table, and gather a list of the + MuContainer objects that have no parents, but do have children */ +static MuContainer* +find_root_set (GHashTable *ids) +{ + MuContainer *root_set; + + root_set = NULL; + g_hash_table_foreach (ids, (GHFunc)filter_root_set, &root_set); + + return root_set; +} + + +static gboolean +prune_maybe (MuContainer *c) +{ + MuContainer *cur; + + for (cur = c->child; cur; cur = cur->next) { + if (cur->flags & MU_CONTAINER_FLAG_DELETE) { + c = mu_container_remove_child (c, cur); + } else if (cur->flags & MU_CONTAINER_FLAG_SPLICE) { + c = mu_container_splice_grandchildren (c, cur); + c = mu_container_remove_child (c, cur); + } + } + + g_return_val_if_fail (c, FALSE); + + /* don't touch containers with messages */ + if (c->msg) + return TRUE; + + /* A. If it is an msg-less container with no children, mark it for + * deletion. */ + if (!c->child) { + c->flags |= MU_CONTAINER_FLAG_DELETE; + return TRUE; + } + + /* B. If the MuContainer has no Message, but does have + * children, remove this container but promote its + * children to this level (that is, splice them in to + * the current child list.) + * + * Do not promote the children if doing so would + * promote them to the root set -- unless there is + * only one child, in which case, do. + */ + if (c->child->next) /* ie., > 1 child */ + return TRUE; + + c->flags |= MU_CONTAINER_FLAG_SPLICE; + + return TRUE; +} + + +static MuContainer* +prune_empty_containers (MuContainer *root_set) +{ + MuContainer *cur; + + mu_container_foreach (root_set, + (MuContainerForeachFunc)prune_maybe, + NULL); + + /* and prune the root_set itself... */ + for (cur = root_set; cur; cur = cur->next) { + if (cur->flags & MU_CONTAINER_FLAG_DELETE) { + root_set = mu_container_remove_sibling (root_set, cur); + } else if (cur->flags & MU_CONTAINER_FLAG_SPLICE) { + root_set = mu_container_splice_children (root_set, cur); + root_set = mu_container_remove_sibling (root_set, cur); + } + } + + return root_set; +} diff --git a/lib/mu-threader.h b/lib/mu-threader.h new file mode 100644 index 0000000..dc8d414 --- /dev/null +++ b/lib/mu-threader.h @@ -0,0 +1,56 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_THREADER_H__ +#define __MU_THREADER_H__ + +#include <glib.h> +#include <mu-msg-iter.h> + +G_BEGIN_DECLS + +/** + * takes an iter and the total number of matches, and from this + * generates a hash-table with information about the thread structure + * of these matches. + * + * the algorithm to find this structure is based on JWZ's + * message-threading algorithm, as descrbed in: + * http://www.jwz.org/doc/threading.html + * + * the returned hashtable maps the Xapian docid of iter (msg) to a ptr + * to a MuMsgIterThreadInfo structure (see mu-msg-iter.h) + * + * @param iter an iter; note this function will mu_msgi_iter_reset this iterator + * @param matches the number of matches in the set * + * @param sortfield the field to sort results by, or + * MU_MSG_FIELD_ID_NONE if no sorting should be performed + * @param revert if TRUE, if revert the sorting order + * + * @return a hashtable; free with g_hash_table_destroy when done with it + */ +GHashTable *mu_threader_calculate (MuMsgIter *iter, size_t matches, + MuMsgFieldId sortfield, gboolean revert); + + +G_END_DECLS + +#endif /*__MU_THREADER_H__*/ diff --git a/lib/query/Makefile.am b/lib/query/Makefile.am new file mode 100644 index 0000000..6923d2b --- /dev/null +++ b/lib/query/Makefile.am @@ -0,0 +1,99 @@ +## Copyright (C) 2017-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +@VALGRIND_CHECK_RULES@ + +AM_CXXFLAGS= \ + -I$(srcdir)/.. \ + -I$(top_srcdir)/lib \ + $(GLIB_CFLAGS) \ + $(XAPIAN_CXXFLAGS) \ + $(WARN_CXXFLAGS) \ + $(ASAN_CXXFLAGS) \ + $(CODE_COVERAGE_CFLAGS) \ + -Wno-inline \ + -Wno-switch-enum + +AM_CPPFLAGS= \ + $(CODE_COVERAGE_CPPFLAGS) + +AM_LDFLAGS= \ + $(ASAN_LDFLAGS) \ + $(WARN_LDFLAGS) + +noinst_PROGRAMS= \ + tokenize \ + parse + +noinst_LTLIBRARIES= \ + libmu-query.la + +libmu_query_la_SOURCES= \ + mu-data.hh \ + mu-parser.cc \ + mu-parser.hh \ + mu-proc-iface.hh \ + mu-tokenizer.cc \ + mu-tokenizer.hh \ + mu-tree.hh \ + mu-xapian.cc \ + mu-xapian.hh + +libmu_query_la_LIBADD= \ + $(WARN_LDFLAGS) \ + $(GLIB_LIBS) \ + $(XAPIAN_LIBS) \ + ../utils/libmu-utils.la \ + $(CODE_COVERAGE_LIBS) + +VALGRIND_SUPPRESSIONS_FILES= \ + ${top_srcdir}/mu.supp + +tokenize_SOURCES= \ + tokenize.cc + +tokenize_LDADD= \ + $(WARN_LDFLAGS) \ + libmu-query.la + +parse_SOURCES= \ + parse.cc + +parse_LDADD= \ + $(WARN_LDFLAGS) \ + libmu-query.la + +noinst_PROGRAMS+=$(TEST_PROGS) + +TEST_PROGS+= \ + test-tokenizer +test_tokenizer_SOURCES= \ + test-tokenizer.cc +test_tokenizer_LDADD= \ + libmu-query.la + +TEST_PROGS+= \ + test-parser +test_parser_SOURCES= \ + test-parser.cc +test_parser_LDADD= \ + libmu-query.la + +TESTS=$(TEST_PROGS) + +include $(top_srcdir)/aminclude_static.am diff --git a/lib/query/mu-data.hh b/lib/query/mu-data.hh new file mode 100644 index 0000000..25d3634 --- /dev/null +++ b/lib/query/mu-data.hh @@ -0,0 +1,155 @@ +/* +** Copyright (C) 2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + +#ifndef __DATA_HH__ +#define __DATA_HH__ + +#include <string> +#include <iostream> +#include <regex> + +#include <utils//mu-utils.hh> + +namespace Mu { + +// class representing some data item; either a Value or a Range a Value can still be a Regex (but +// that's not a separate type here) +struct Data { + enum class Type { Value, Range }; + virtual ~Data() = default; + + Type type; /**< type of data */ + std::string field; /**< full name of the field */ + std::string prefix; /**< Xapian prefix for thef field */ + unsigned id; /**< Xapian value no for the field */ + +protected: + Data (Type _type, const std::string& _field, const std::string& _prefix, + unsigned _id): type(_type), field(_field), prefix(_prefix), id(_id) {} +}; + + +/** + * operator<< + * + * @param os an output stream + * @param t a data type + * + * @return the updated output stream + */ +inline std::ostream& +operator<< (std::ostream& os, Data::Type t) +{ + switch (t) { + case Data::Type::Value: os << "value"; break; + case Data::Type::Range: os << "range"; break; + default: os << "bug"; break; + } + return os; +} + + +/** + * Range type -- [a..b] + */ +struct Range: public Data { + /** + * Construct a range + * + * @param _field the field + * @param _prefix the xapian prefix + * @param _id xapian value number + * @param _lower lower bound + * @param _upper upper bound + */ + Range (const std::string& _field, const std::string& _prefix, + unsigned _id, + const std::string& _lower,const std::string& _upper): + + Data(Data::Type::Range, _field, _prefix, _id), + lower(_lower), upper(_upper) {} + + std::string lower; /**< lower bound */ + std::string upper; /**< upper bound */ +}; + + +/** + * Basic value + * + */ +struct Value: public Data { + /** + * Construct a Value + * + * @param _field the field + * @param _prefix the xapian prefix + * @param _id xapian value number + * @param _value the value + */ + Value (const std::string& _field, const std::string& _prefix, + unsigned _id, const std::string& _value, bool _phrase = false): + Data(Value::Type::Value, _field, _prefix, _id), + value(_value), phrase(_phrase) {} + + std::string value; /**< the value */ + bool phrase; +}; + + +/** + * operator<< + * + * @param os an output stream + * @param v a data ptr + * + * @return the updated output stream + */ +inline std::ostream& +operator<< (std::ostream& os, const std::unique_ptr<Data>& v) +{ + switch (v->type) { + case Data::Type::Value: { + const auto bval = dynamic_cast<Value*> (v.get()); + os << ' ' << quote(v->field) << ' ' + << quote(utf8_flatten(bval->value)); + if (bval->phrase) + os << " (ph)"; + + break; + } + case Data::Type::Range: { + const auto rval = dynamic_cast<Range*> (v.get()); + os << ' ' << quote(v->field) << ' ' + << quote(rval->lower) << ' ' + << quote(rval->upper); + break; + } + default: + os << "unexpected type"; + break; + } + + return os; +} + +} // namespace Mu + + +#endif /* __DATA_HH__ */ diff --git a/lib/query/mu-parser.cc b/lib/query/mu-parser.cc new file mode 100644 index 0000000..8becb1d --- /dev/null +++ b/lib/query/mu-parser.cc @@ -0,0 +1,344 @@ +/* +** Copyright (C) 2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ +#include "mu-parser.hh" +#include "mu-tokenizer.hh" +#include "utils/mu-utils.hh" +#include "utils/mu-error.hh" + +using namespace Mu; + +// 3 precedence levels: units (NOT,()) > factors (OR) > terms (AND) + +// query -> <term-1> | ε +// <term-1> -> <factor-1> <term-2> | ε +// <term-2> -> OR|XOR <term-1> | ε +// <factor-1> -> <unit> <factor-2> | ε +// <factor-2> -> [AND]|AND NOT <factor-1> | ε +// <unit> -> [NOT] <term-1> | ( <term-1> ) | <data> +// <data> -> <value> | <range> | <regex> +// <value> -> [field:]value +// <range> -> [field:][lower]..[upper] +// <regex> -> [field:]/regex/ + + +#define BUG(...) Mu::Error (Error::Code::Internal, format("%u: BUG: ",__LINE__) \ + + format(__VA_ARGS__)) + +static Token +look_ahead (const Mu::Tokens& tokens) +{ + return tokens.front(); +} + +static Mu::Tree +empty() +{ + return {{Node::Type::Empty}}; +} + +static Mu::Tree term_1 (Mu::Tokens& tokens, ProcPtr proc, WarningVec& warnings); + + +static Mu::Tree +value (const ProcIface::FieldInfoVec& fields, const std::string& v, + size_t pos, ProcPtr proc, WarningVec& warnings) +{ + auto val = utf8_flatten(v); + + if (fields.empty()) + throw BUG("expected one or more fields"); + + if (fields.size() == 1) { + const auto item = fields.front(); + return Tree({Node::Type::Value, + std::make_unique<Value>( + item.field, item.prefix, item.id, + proc->process_value(item.field, val), + item.supports_phrase)}); + } + + // a 'multi-field' such as "recip:" + Tree tree(Node{Node::Type::OpOr}); + for (const auto& item: fields) + tree.add_child (Tree({Node::Type::Value, + std::make_unique<Value>( + item.field, item.prefix, item.id, + proc->process_value(item.field, val), + item.supports_phrase)})); + return tree; +} + +static Mu::Tree +regex (const ProcIface::FieldInfoVec& fields, const std::string& v, + size_t pos, ProcPtr proc, WarningVec& warnings) +{ + if (v.length() < 2) + throw BUG("expected regexp, got '%s'", v.c_str()); + + const auto rxstr = utf8_flatten(v.substr(1, v.length()-2)); + + try { + Tree tree(Node{Node::Type::OpOr}); + const auto rx = std::regex (rxstr); + for (const auto& field: fields) { + const auto terms = proc->process_regex (field.field, rx); + for (const auto& term: terms) { + tree.add_child (Tree( + {Node::Type::Value, + std::make_unique<Value>(field.field, "", + field.id, term)})); + } + } + + if (tree.children.empty()) + return empty(); + else + return tree; + + } catch (...) { + // fallback + warnings.push_back ({pos, "invalid regexp"}); + return value (fields, v, pos, proc, warnings); + } +} + + + +static Mu::Tree +range (const ProcIface::FieldInfoVec& fields, const std::string& lower, + const std::string& upper, size_t pos, ProcPtr proc, + WarningVec& warnings) +{ + if (fields.empty()) + throw BUG("expected field"); + + const auto& field = fields.front(); + if (!proc->is_range_field(field.field)) + return value (fields, lower + ".." + upper, pos, proc, warnings); + + auto prange = proc->process_range (field.field, lower, upper); + if (prange.lower > prange.upper) + prange = proc->process_range (field.field, upper, lower); + + return Tree({Node::Type::Range, + std::make_unique<Range>(field.field, field.prefix, field.id, + prange.lower, prange.upper)}); +} + + +static Mu::Tree +data (Mu::Tokens& tokens, ProcPtr proc, WarningVec& warnings) +{ + const auto token = look_ahead(tokens); + if (token.type != Token::Type::Data) + warnings.push_back ({token.pos, "expected: value"}); + + tokens.pop_front(); + + std::string field, val; + const auto col = token.str.find (":"); + if (col != 0 && col != std::string::npos && col != token.str.length()-1) { + field = token.str.substr(0, col); + val = token.str.substr(col + 1); + } else + val = token.str; + + auto fields = proc->process_field (field); + if (fields.empty()) {// not valid field... + warnings.push_back ({token.pos, format ("invalid field '%s'", field.c_str())}); + fields = proc->process_field (""); + // fallback, treat the whole of foo:bar as a value + return value (fields, field + ":" + val, token.pos, proc, warnings); + } + + // does it look like a regexp? + if (val.length() >=2 ) + if (val[0] == '/' && val[val.length()-1] == '/') + return regex (fields, val, token.pos, proc, warnings); + + // does it look like a range? + const auto dotdot = val.find(".."); + if (dotdot != std::string::npos) + return range(fields, val.substr(0, dotdot), val.substr(dotdot + 2), + token.pos, proc, warnings); + else if (proc->is_range_field(fields.front().field)) { + // range field without a range - treat as field:val..val + return range (fields, val, val, token.pos, proc, warnings); + } + + // if nothing else, it's a value. + return value (fields, val, token.pos, proc, warnings); +} + +static Mu::Tree +unit (Mu::Tokens& tokens, ProcPtr proc, WarningVec& warnings) +{ + if (tokens.empty()) { + warnings.push_back ({0, "expected: unit"}); + return empty(); + } + + const auto token = look_ahead (tokens); + + if (token.type == Token::Type::Not) { + tokens.pop_front(); + Tree tree{{Node::Type::OpNot}}; + tree.add_child(unit (tokens, proc, warnings)); + return tree; + } + + if (token.type == Token::Type::Open) { + tokens.pop_front(); + auto tree = term_1 (tokens, proc, warnings); + if (tokens.empty()) + warnings.push_back({token.pos, "expected: ')'"}); + else { + const auto token2 = look_ahead(tokens); + if (token2.type == Token::Type::Close) + tokens.pop_front(); + else { + warnings.push_back( + {token2.pos, + std::string("expected: ')' but got ") + + token2.str}); + } + + } + return tree; + } + + return data (tokens, proc, warnings); +} + +static Mu::Tree factor_1 (Mu::Tokens& tokens, ProcPtr proc, + WarningVec& warnings); + +static Mu::Tree +factor_2 (Mu::Tokens& tokens, Node::Type& op, ProcPtr proc, + WarningVec& warnings) +{ + if (tokens.empty()) + return empty(); + + const auto token = look_ahead(tokens); + + switch (token.type) { + case Token::Type::And: { + tokens.pop_front(); + op = Node::Type::OpAnd; + } break; + + case Token::Type::Open: + case Token::Type::Data: + case Token::Type::Not: + op = Node::Type::OpAnd; // implicit AND + break; + + default: + return empty(); + } + + return factor_1 (tokens, proc, warnings); +} + +static Mu::Tree +factor_1 (Mu::Tokens& tokens, ProcPtr proc, WarningVec& warnings) +{ + Node::Type op { Node::Type::Invalid }; + + auto t = unit (tokens, proc, warnings); + auto a2 = factor_2 (tokens, op, proc, warnings); + + if (a2.empty()) + return t; + + Tree tree {{op}}; + tree.add_child(std::move(t)); + tree.add_child(std::move(a2)); + + return tree; +} + + +static Mu::Tree +term_2 (Mu::Tokens& tokens, Node::Type& op, ProcPtr proc, + WarningVec& warnings) +{ + if (tokens.empty()) + return empty(); + + const auto token = look_ahead (tokens); + + switch (token.type) { + case Token::Type::Or: + op = Node::Type::OpOr; + break; + case Token::Type::Xor: + op = Node::Type::OpXor; + break; + default: + if (token.type != Token::Type::Close) + warnings.push_back({token.pos, "expected OR|XOR"}); + return empty(); + } + + tokens.pop_front(); + + return term_1 (tokens, proc, warnings); +} + +static Mu::Tree +term_1 (Mu::Tokens& tokens, ProcPtr proc, WarningVec& warnings) +{ + Node::Type op { Node::Type::Invalid }; + + auto t = factor_1 (tokens, proc, warnings); + auto o2 = term_2 (tokens, op, proc, warnings); + + if (o2.empty()) + return t; + else { + Tree tree {{op}}; + tree.add_child(std::move(t)); + tree.add_child(std::move(o2)); + return tree; + } +} + +static Mu::Tree +query (Mu::Tokens& tokens, ProcPtr proc, WarningVec& warnings) +{ + if (tokens.empty()) + return empty (); + else + return term_1 (tokens, proc, warnings); +} + +Mu::Tree +Mu::parse (const std::string& expr, WarningVec& warnings, ProcPtr proc) +{ + try { + auto tokens = tokenize (expr); + return query (tokens, proc, warnings); + + } catch (const std::runtime_error& ex) { + std::cerr << ex.what() << std::endl; + return empty(); + } +} diff --git a/lib/query/mu-parser.hh b/lib/query/mu-parser.hh new file mode 100644 index 0000000..0c2ffe9 --- /dev/null +++ b/lib/query/mu-parser.hh @@ -0,0 +1,89 @@ +/* +** Copyright (C) 2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + + +#ifndef __PARSER_HH__ +#define __PARSER_HH__ + +#include <string> +#include <vector> +#include <memory> + +#include <query/mu-data.hh> +#include <query/mu-tree.hh> +#include <query/mu-proc-iface.hh> + +// A simple recursive-descent parser for queries. Follows the Xapian syntax, +// but better handles non-alphanum; also implements regexp + +namespace Mu { + +/** + * A parser warning + * + */ +struct Warning { + size_t pos{}; /**< pos in string */ + const std::string msg; /**< warning message */ + + /** + * operator== + * + * @param rhs right-hand side + * + * @return true if rhs is equal to this; false otherwise + */ + bool operator==(const Warning& rhs) const { + return pos == rhs.pos && msg == rhs.msg; + } +}; + + +/** + * operator<< + * + * @param os an output stream + * @param w a warning + * + * @return the updated output stream + */ +inline std::ostream& +operator<< (std::ostream& os, const Warning& w) +{ + os << w.pos << ":" << w.msg; + return os; +} + +/** + * Parse a query string + * + * @param query a query string + * @param warnings vec to receive warnings + * @param proc a Processor object + * + * @return a parse-tree + */ +using WarningVec=std::vector<Warning>; +using ProcPtr = const std::unique_ptr<ProcIface>&; +Tree parse (const std::string& query, WarningVec& warnings, + ProcPtr proc = std::make_unique<DummyProc>()); + +} // namespace Mu + +#endif /* __PARSER_HH__ */ diff --git a/lib/query/mu-proc-iface.hh b/lib/query/mu-proc-iface.hh new file mode 100644 index 0000000..b43ef41 --- /dev/null +++ b/lib/query/mu-proc-iface.hh @@ -0,0 +1,132 @@ +/* +** Copyright (C) 2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ +#ifndef __PROC_IFACE_HH__ +#define __PROC_IFACE_HH__ + +#include <string> +#include <vector> +#include <tuple> +#include <regex> + +namespace Mu { + +struct ProcIface { + + virtual ~ProcIface() = default; + + /** + * Get the "shortcut"/internal fields for the the given fieldstr or empty if there is none + * + * @param fieldstr a fieldstr, e.g "subject" or "s" for the subject field + * + * @return a vector with "exploded" values, with a code and a fullname. E.g. "s" might map + * to [<"S","subject">], while "recip" could map to [<"to", "T">, <"cc", "C">, <"bcc", "B">] + */ + struct FieldInfo { + const std::string field; + const std::string prefix; + bool supports_phrase; + unsigned id; + }; + using FieldInfoVec = std::vector<FieldInfo>; + + virtual FieldInfoVec process_field (const std::string& field) const = 0; + + /** + * Process a value + * + * @param field a field name + * @param value a value + * + * @return the processed value + */ + virtual std::string process_value ( + const std::string& field, const std::string& value) const = 0; + + /** + * Is this a range field? + * + * @param field some field + * + * @return true if it is a range-field; false otherwise. + */ + virtual bool is_range_field (const std::string& field) const = 0; + + + /** + * Process a range field + * + * @param fieldstr a fieldstr, e.g "date" or "d" for the date field + * @param lower lower bound or empty + * @param upper upper bound or empty + * + * @return the processed range + */ + struct Range { + std::string lower; + std::string upper; + }; + virtual Range process_range (const std::string& field, const std::string& lower, + const std::string& upper) const = 0; + + /** + * + * + * @param field + * @param rx + * + * @return + */ + virtual std::vector<std::string> + process_regex (const std::string& field, const std::regex& rx) const = 0; + +}; // ProcIface + + +struct DummyProc: public ProcIface { // For testing + + std::vector<FieldInfo> + process_field (const std::string& field) const override { + return {{ field, "x", false, 0 }}; + } + + std::string + process_value (const std::string& field, const std::string& value) const override { + return value; + } + + bool is_range_field (const std::string& field) const override { + return field == "range"; + } + + Range process_range (const std::string& field, const std::string& lower, + const std::string& upper) const override { + return { lower, upper }; + } + + std::vector<std::string> + process_regex (const std::string& field, const std::regex& rx) const override { + return {}; + } +}; //Dummy + + +} // Mu + +#endif /* __PROC_IFACE_HH__ */ diff --git a/lib/query/mu-tokenizer.cc b/lib/query/mu-tokenizer.cc new file mode 100644 index 0000000..f314d04 --- /dev/null +++ b/lib/query/mu-tokenizer.cc @@ -0,0 +1,133 @@ +/* +** Copyright (C) 2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + +#include "mu-tokenizer.hh" +#include "utils/mu-utils.hh" + +#include <cctype> +#include <iostream> +#include <algorithm> + +using namespace Mu; + +static bool +is_separator (char c) +{ + if (isblank(c)) + return true; + + const auto seps = std::string ("()"); + return seps.find(c) != std::string::npos; +} + + +static Mu::Token +op_or_value (size_t pos, const std::string& val) +{ + auto s = val; + std::transform(s.begin(), s.end(), s.begin(), ::tolower); + + if (s == "and") + return Token{pos, Token::Type::And, val}; + else if (s == "or") + return Token{pos, Token::Type::Or, val}; + else if (s == "xor") + return Token{pos, Token::Type::Xor, val}; + else if (s == "not") + return Token{pos, Token::Type::Not, val}; + else + return Token{pos, Token::Type::Data, val}; +} + +static void +unread_char (std::string& food, char kar, size_t& pos) +{ + food = kar + food; + --pos; +} + +static Mu::Token +eat_token (std::string& food, size_t& pos) +{ + bool quoted{}; + bool escaped{}; + std::string value {}; + + while (!food.empty()) { + + const auto kar = food[0]; + food.erase(0, 1); + ++pos; + + if (kar == '\\') { + escaped = !escaped; + if (escaped) + continue; + } + + if (kar == '"') { + if (!escaped && quoted) + return Token{pos, Token::Type::Data, value}; + else { + quoted = true; + continue; + } + } + + if (!quoted && !escaped && is_separator(kar)) { + + if (!value.empty() && kar != ':') { + unread_char (food, kar, pos); + return op_or_value(pos, value); + } + + if (quoted || isblank(kar)) + continue; + + switch (kar) { + case '(': return {pos, Token::Type::Open, "("}; + case ')': return {pos, Token::Type::Close,")"}; + default: break; + } + } + + value += kar; + escaped = false; + } + + return {pos, Token::Type::Data, value}; +} + + +Mu::Tokens +Mu::tokenize (const std::string& s) +{ + Tokens tokens{}; + + std::string food = utf8_clean(s); + size_t pos{0}; + + if (s.empty()) + return {}; + + while (!food.empty()) + tokens.emplace_back(eat_token (food, pos)); + + return tokens; +} diff --git a/lib/query/mu-tokenizer.hh b/lib/query/mu-tokenizer.hh new file mode 100644 index 0000000..ac083c8 --- /dev/null +++ b/lib/query/mu-tokenizer.hh @@ -0,0 +1,140 @@ +/* +** Copyright (C) 2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + +#ifndef __TOKENIZER_HH__ +#define __TOKENIZER_HH__ + +#include <string> +#include <vector> +#include <deque> +#include <ostream> +#include <stdexcept> + +// A simple tokenizer, which turns a string into a deque of tokens +// +// It recognizes '(', ')', '*' 'and', 'or', 'xor', 'not' +// +// Note that even if we recognizes those at the lexical level, they might be demoted to mere strings +// when we're creating the parse tree. +// +// Furthermore, we detect ranges ("a..b") and regexps (/../) at the parser level, since we need a +// bit more context to resolve ambiguities. + +namespace Mu { + +// A token +struct Token { + enum class Type { + Data, /**< e .g., banana or date:..456 */ + + // Brackets + Open, /**< ( */ + Close, /**< ) */ + + // Unops + Not, /**< logical not*/ + + // Binops + And, /**< logical and */ + Or, /**< logical not */ + Xor, /**< logical xor */ + + Empty, /**< nothing */ + }; + + size_t pos{}; /**< position in string */ + Type type{}; /**< token type */ + const std::string str{}; /**< data for this token */ + + /** + * operator== + * + * @param rhs right-hand side + * + * @return true if rhs is equal to this; false otherwise + */ + bool operator==(const Token& rhs) const { + return pos == rhs.pos && + type == rhs.type && + str == rhs.str; + } +}; + +/** + * operator<< + * + * @param os an output stream + * @param t a token type + * + * @return the updated output stream + */ +inline std::ostream& +operator<< (std::ostream& os, Token::Type t) +{ + switch (t) { + case Token::Type::Data: os << "<data>"; break; + + case Token::Type::Open: os << "<open>"; break; + case Token::Type::Close: os << "<close>";break; + + case Token::Type::Not: os << "<not>"; break; + case Token::Type::And: os << "<and>"; break; + case Token::Type::Or: os << "<or>"; break; + case Token::Type::Xor: os << "<xor>"; break; + + default: // can't happen, but pacify compiler + throw std::runtime_error ("<<bug>>"); + } + + return os; +} + +/** + * operator<< + * + * @param os an output stream + * @param t a token + * + * @return the updated output stream + */ +inline std::ostream& +operator<< (std::ostream& os, const Token& t) +{ + os << t.pos << ": " << t.type; + + if (!t.str.empty()) + os << " [" << t.str << "]"; + + return os; +} + +/** + * Tokenize a string into a vector of tokens. The tokenization always succeeds, ie., ignoring errors + * such a missing end-". + * + * @param s a string + * + * @return a deque of tokens + */ +using Tokens = std::deque<Token>; +Tokens tokenize (const std::string& s); + +} // namespace Mu + +#endif /* __TOKENIZER_HH__ */ diff --git a/lib/query/mu-tree.hh b/lib/query/mu-tree.hh new file mode 100644 index 0000000..eacda98 --- /dev/null +++ b/lib/query/mu-tree.hh @@ -0,0 +1,111 @@ +/* +** Copyright (C) 2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + +#ifndef TREE_HH__ +#define TREE_HH__ + +#include <vector> +#include <string> +#include <iostream> + +#include <query/mu-data.hh> +#include <utils/mu-error.hh> + +namespace Mu { + +// A node in the parse tree +struct Node { + enum class Type { + Empty, // only for empty trees + OpAnd, + OpOr, + OpXor, + OpAndNot, + OpNot, + Value, + Range, + Invalid + }; + + Node(Type _type, std::unique_ptr<Data>&& _data): + type{_type}, data{std::move(_data)} {} + Node(Type _type): type{_type} {} + Node(Node&& rhs) = default; + + Type type; + std::unique_ptr<Data> data; + + static const char* type_name (Type t) { + switch (t) { + case Type::Empty: return ""; break; + case Type::OpAnd: return "and"; break; + case Type::OpOr: return "or"; break; + case Type::OpXor: return "xor"; break; + case Type::OpAndNot: return "andnot"; break; + case Type::OpNot: return "not"; break; + case Type::Value: return "value"; break; + case Type::Range: return "range"; break; + case Type::Invalid: return "<invalid>"; break; + default: + throw Mu::Error(Error::Code::Internal, "unexpected type"); + } + } + + static constexpr bool is_binop(Type t) { + return t == Type::OpAnd || t == Type::OpAndNot || + t == Type::OpOr || t == Type::OpXor; + } +}; + +inline std::ostream& +operator<< (std::ostream& os, const Node& t) +{ + os << Node::type_name(t.type); + if (t.data) + os << t.data; + + return os; +} + +struct Tree { + Tree(Node&& _node): node(std::move(_node)) {} + Tree(Tree&& rhs) = default; + + void add_child (Tree&& child) { children.emplace_back(std::move(child)); } + bool empty() const { return node.type == Node::Type::Empty; } + + Node node; + std::vector<Tree> children; +}; + +inline std::ostream& +operator<< (std::ostream& os, const Tree& tree) +{ + os << '(' << tree.node; + for (const auto& subtree : tree.children) + os << subtree; + os << ')'; + + return os; +} + +} // namespace Mu + + +#endif /* TREE_HH__ */ diff --git a/lib/query/mu-xapian.cc b/lib/query/mu-xapian.cc new file mode 100644 index 0000000..5112594 --- /dev/null +++ b/lib/query/mu-xapian.cc @@ -0,0 +1,116 @@ +/* +** Copyright (C) 2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /*HAVE_CONFIG_H*/ + +#include <xapian.h> +#include "mu-xapian.hh" +#include <utils/mu-error.hh> + +using namespace Mu; + +static Xapian::Query +xapian_query_op (const Mu::Tree& tree) +{ + Xapian::Query::op op; + + switch (tree.node.type) { + case Node::Type::OpNot: // OpNot x ::= <all> AND NOT x + if (tree.children.size() != 1) + throw std::runtime_error ("invalid # of children"); + return Xapian::Query (Xapian::Query::OP_AND_NOT, + Xapian::Query::MatchAll, + xapian_query(tree.children.front())); + case Node::Type::OpAnd: op = Xapian::Query::OP_AND; break; + case Node::Type::OpOr: op = Xapian::Query::OP_OR; break; + case Node::Type::OpXor: op = Xapian::Query::OP_XOR; break; + case Node::Type::OpAndNot: op = Xapian::Query::OP_AND_NOT; break; + default: throw Mu::Error (Error::Code::Internal, "invalid op"); // bug + } + + std::vector<Xapian::Query> childvec; + for (const auto& subtree: tree.children) + childvec.emplace_back(xapian_query(subtree)); + + return Xapian::Query(op, childvec.begin(), childvec.end()); +} + +static Xapian::Query +make_query (const Value* val, const std::string& str, bool maybe_wildcard) +{ + const auto vlen{str.length()}; + if (!maybe_wildcard || vlen <= 1 || str[vlen - 1] != '*') + return Xapian::Query(val->prefix + str); + else + return Xapian::Query(Xapian::Query::OP_WILDCARD, + val->prefix + str.substr(0, vlen - 1)); +} + +static Xapian::Query +xapian_query_value (const Mu::Tree& tree) +{ + const auto v = dynamic_cast<Value*> (tree.node.data.get()); + if (!v->phrase) + return make_query(v, v->value, true/*maybe-wildcard*/); + + const auto parts = split (v->value, " "); + if (parts.empty()) + return Xapian::Query::MatchNothing; // shouldn't happen + + if (parts.size() == 1) + return make_query(v, parts.front(), true/*maybe-wildcard*/); + + std::vector<Xapian::Query> phvec; + for (const auto p: parts) + phvec.emplace_back(make_query(v, p, false/*no wildcards*/)); + + return Xapian::Query (Xapian::Query::OP_PHRASE, phvec.begin(), phvec.end()); +} + +static Xapian::Query +xapian_query_range (const Mu::Tree& tree) +{ + const auto r { dynamic_cast<Range *>(tree.node.data.get()) }; + + return Xapian::Query(Xapian::Query::OP_VALUE_RANGE, (Xapian::valueno)r->id, + r->lower, r->upper); +} + +Xapian::Query +Mu::xapian_query (const Mu::Tree& tree) +{ + switch (tree.node.type) { + case Node::Type::Empty: + return Xapian::Query(); + case Node::Type::OpNot: + case Node::Type::OpAnd: + case Node::Type::OpOr: + case Node::Type::OpXor: + case Node::Type::OpAndNot: + return xapian_query_op (tree); + case Node::Type::Value: + return xapian_query_value (tree); + case Node::Type::Range: + return xapian_query_range (tree); + default: + throw Mu::Error (Error::Code::Internal, "invalid query"); // bug + } +} diff --git a/lib/query/mu-xapian.hh b/lib/query/mu-xapian.hh new file mode 100644 index 0000000..503d9eb --- /dev/null +++ b/lib/query/mu-xapian.hh @@ -0,0 +1,40 @@ +/* +** Copyright (C) 2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + + +#ifndef __XAPIAN_HH__ +#define __XAPIAN_HH__ + +#include <xapian.h> +#include <query/mu-parser.hh> + +namespace Mu { + +/** + * Transform a parse-tree into a Xapian query object + * + * @param tree a parse tree + * + * @return a Xapian query object + */ +Xapian::Query xapian_query (const Mu::Tree& tree); + +} // namespace Mu + +#endif /* __XAPIAN_H__ */ diff --git a/lib/query/parse.cc b/lib/query/parse.cc new file mode 100644 index 0000000..d988d6e --- /dev/null +++ b/lib/query/parse.cc @@ -0,0 +1,41 @@ +/* +** Copyright (C) 2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + +#include <string> +#include <iostream> +#include "mu-parser.hh" + +int +main (int argc, char *argv[]) +{ + std::string s; + + for (auto i = 1; i < argc; ++i) + s += " " + std::string(argv[i]); + + Mu::WarningVec warnings; + + const auto tree = Mu::parse (s, warnings); + for (const auto& w: warnings) + std::cerr << "1:" << w.pos << ": " << w.msg << std::endl; + + std::cout << tree << std::endl; + + return 0; +} diff --git a/lib/query/test-parser.cc b/lib/query/test-parser.cc new file mode 100644 index 0000000..2eadda9 --- /dev/null +++ b/lib/query/test-parser.cc @@ -0,0 +1,146 @@ +/* +** Copyright (C) 2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + +#include <vector> +#include <glib.h> + +#include <iostream> +#include <sstream> + +#include "mu-parser.hh" +using namespace Mu; + +struct Case { + const std::string expr; + const std::string expected; + WarningVec warnings; +}; + +using CaseVec = std::vector<Case>; + +static void +test_cases(const CaseVec& cases) +{ + for (const auto& casus : cases ) { + + WarningVec warnings; + const auto tree = parse (casus.expr, warnings); + + std::stringstream ss; + ss << tree; + + if (g_test_verbose()) { + std::cout << "\n"; + std::cout << casus.expr << std::endl; + std::cout << "exp:" << casus.expected << std::endl; + std::cout << "got:" << ss.str() << std::endl; + } + g_assert_true (casus.expected == ss.str()); + + // g_assert_cmpuint (casus.warnings.size(), ==, warnings.size()); + // for (auto i = 0; i != (int)casus.warnings.size(); ++i) { + // std::cout << "exp:" << casus.warnings[i] << std::endl; + // std::cout << "got:" << warnings[i] << std::endl; + // g_assert_true (casus.warnings[i] == warnings[i]); + // } + } +} + +static void +test_basic () +{ + CaseVec cases = { + //{ "", R"#((atom :value ""))#"}, + { "foo", R"#((value "" "foo"))#", }, + { "foo or bar", + R"#((or(value "" "foo")(value "" "bar")))#" }, + { "foo and bar", + R"#((and(value "" "foo")(value "" "bar")))#"}, + }; + + test_cases (cases); +} + +static void +test_complex () +{ + CaseVec cases = { + { "foo and bar or cuux", + R"#((or(and(value "" "foo")(value "" "bar")))#" + + std::string(R"#((value "" "cuux")))#") }, + + { "a and not b", + R"#((and(value "" "a")(not(value "" "b"))))#" + }, + { "a and b and c", + R"#((and(value "" "a")(and(value "" "b")(value "" "c"))))#" + }, + { "(a or b) and c", + R"#((and(or(value "" "a")(value "" "b"))(value "" "c")))#" + }, + { "a b", // implicit and + R"#((and(value "" "a")(value "" "b")))#" + }, + { "a not b", // implicit and not + R"#((and(value "" "a")(not(value "" "b"))))#" + }, + { "not b", // implicit and not + R"#((not(value "" "b")))#" + } + }; + + test_cases (cases); +} + + +static void +test_range () +{ + CaseVec cases = { + { "range:a..b", // implicit and + R"#((range "range" "a" "b"))#" + }, + }; + + test_cases (cases); +} + + +static void +test_flatten () +{ + CaseVec cases = { + { " Mötørhęåđ", R"#((value "" "motorhead"))#" } + }; + + test_cases (cases); +} + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/parser/basic", test_basic); + g_test_add_func ("/parser/complex", test_complex); + g_test_add_func ("/parser/range", test_range); + g_test_add_func ("/parser/flatten", test_flatten); + + return g_test_run (); +} diff --git a/lib/query/test-tokenizer.cc b/lib/query/test-tokenizer.cc new file mode 100644 index 0000000..62fa7ef --- /dev/null +++ b/lib/query/test-tokenizer.cc @@ -0,0 +1,158 @@ +/* +** Copyright (C) 2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + +#include <vector> +#include <glib.h> +#include <iostream> +#include <sstream> + +#include "mu-tokenizer.hh" + +struct Case { + const char *str; + const Mu::Tokens tokens; +}; + +using CaseVec = std::vector<Case>; + +using namespace Mu; +using TT = Token::Type; + +static void +test_cases(const CaseVec& cases) +{ + for (const auto& casus : cases ) { + const auto tokens = tokenize (casus.str); + + g_assert_cmpuint ((guint)tokens.size(),==,(guint)casus.tokens.size()); + for (size_t u = 0; u != tokens.size(); ++u) { + if (g_test_verbose()) { + std::cerr << "case " << u << " " << casus.str << std::endl; + std::cerr << "exp: '" << casus.tokens[u] << "'" << std::endl; + std::cerr << "got: '" << tokens[u] << "'" << std::endl; + + } + g_assert_true (tokens[u] == casus.tokens[u]); + } + } +} + +static void +test_basic () +{ + CaseVec cases = { + { "", {} }, + + { "foo", Tokens{Token{3, TT::Data, "foo"}}}, + + { "foo bar cuux", Tokens{Token{3, TT::Data, "foo"}, + Token{7, TT::Data, "bar"}, + Token{12, TT::Data, "cuux"}}}, + + { "\"foo bar\"", Tokens{ Token{9, TT::Data, "foo bar"}}}, + + // ie. ignore missing closing '"' + { "\"foo bar", Tokens{ Token{8, TT::Data, "foo bar"}}}, + + }; + + test_cases (cases); +} + +static void +test_specials () +{ + CaseVec cases = { + { ")*(", Tokens{Token{1, TT::Close, ")"}, + Token{2, TT::Data, "*"}, + Token{3, TT::Open, "("}}}, + { "\")*(\"", Tokens{Token{5, TT::Data, ")*("}}}, + }; + + test_cases (cases); +} + + +static void +test_ops () +{ + CaseVec cases = { + { "foo and bar oR cuux XoR fnorb", + Tokens{Token{3, TT::Data, "foo"}, + Token{7, TT::And, "and"}, + Token{11, TT::Data, "bar"}, + Token{14, TT::Or, "oR"}, + Token{19, TT::Data, "cuux"}, + Token{23, TT::Xor, "XoR"}, + Token{29, TT::Data, "fnorb"}}}, + { "NOT (aap or mies)", + Tokens{Token{3, TT::Not, "NOT"}, + Token{5, TT::Open, "("}, + Token{8, TT::Data, "aap"}, + Token{11, TT::Or, "or"}, + Token{16, TT::Data, "mies"}, + Token{17, TT::Close, ")"}}} + }; + + + test_cases (cases); +} + + +static void +test_escape () +{ + CaseVec cases = { + { "foo\"bar\"", Tokens{Token{8, TT::Data, "foobar"}}}, + { "\"fnorb\"", Tokens{Token{7, TT::Data, "fnorb"}}}, + { "\\\"fnorb\\\"", Tokens{Token{9, TT::Data, "fnorb"}}}, + { "foo\\\"bar\\\"", Tokens{Token{10, TT::Data, "foobar"}}} + }; + + test_cases (cases); +} + + +static void +test_to_string () +{ + std::stringstream ss; + for (const auto t: tokenize ("foo and bar xor not cuux or fnorb")) + ss << t << ' '; + + g_assert_true (ss.str() == + "3: <data> [foo] 7: <and> [and] 11: <data> [bar] " + "15: <xor> [xor] 19: <not> [not] 24: <data> [cuux] " + "27: <or> [or] 33: <data> [fnorb] "); +} + + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/tokens/basic", test_basic); + g_test_add_func ("/tokens/specials", test_specials); + g_test_add_func ("/tokens/ops", test_ops); + g_test_add_func ("/tokens/escape", test_escape); + g_test_add_func ("/tokens/to-string", test_to_string); + + return g_test_run (); +} diff --git a/lib/query/tokenize.cc b/lib/query/tokenize.cc new file mode 100644 index 0000000..81f6ef0 --- /dev/null +++ b/lib/query/tokenize.cc @@ -0,0 +1,38 @@ +/* +** Copyright (C) 2017-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + +#include <string> +#include <iostream> + +#include "mu-tokenizer.hh" + +int +main (int argc, char *argv[]) +{ + std::string s; + + for (auto i = 1; i < argc; ++i) + s += " " + std::string(argv[i]); + + const auto tvec = Mu::tokenize (s); + for (const auto& t : tvec) + std::cout << t << std::endl; + + return 0; +} diff --git a/lib/test-mu-common.c b/lib/test-mu-common.c new file mode 100644 index 0000000..5cabb76 --- /dev/null +++ b/lib/test-mu-common.c @@ -0,0 +1,93 @@ +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include <glib.h> +#include <glib/gstdio.h> + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include <langinfo.h> +#include <locale.h> + +#include "test-mu-common.h" + +char* +test_mu_common_get_random_tmpdir (void) +{ + char*dir; + int res; + + dir = g_strdup_printf ( + "%s%cmu-test-%d%ctest-%x", + g_get_tmp_dir(), + G_DIR_SEPARATOR, + getuid(), + G_DIR_SEPARATOR, + (int)random()*getpid()*(int)time(NULL)); + + res = g_mkdir_with_parents (dir, 0700); + g_assert (res != -1); + + return dir; +} + + +const char* +set_tz (const char* tz) +{ + static const char* oldtz; + + oldtz = getenv ("TZ"); + if (tz) + setenv ("TZ", tz, 1); + else + unsetenv ("TZ"); + + tzset (); + return oldtz; +} + + +gboolean +set_en_us_utf8_locale (void) +{ + setenv ("LC_ALL", "en_US.UTF-8", 1); + setlocale (LC_ALL, "en_US.UTF-8"); + + if (strcmp (nl_langinfo(CODESET), "UTF-8") != 0) { + g_print ("Note: Unit tests require the en_US.utf8 locale. " + "Ignoring test cases.\n"); + return FALSE; + } + + return TRUE; +} + + +void +black_hole (void) +{ + return; /* do nothing */ +} diff --git a/lib/test-mu-common.h b/lib/test-mu-common.h new file mode 100644 index 0000000..31f4d3a --- /dev/null +++ b/lib/test-mu-common.h @@ -0,0 +1,61 @@ +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __TEST_MU_COMMON_H__ +#define __TEST_MU_COMMON_H__ + +#include <glib.h> + +G_BEGIN_DECLS + +/** + * get a dir name for a random temporary directory to do tests + * + * @return a random dir name, g_free when it's no longer needed + */ +char* test_mu_common_get_random_tmpdir (void); + + + +/** + * set the output to /dev/null + * + */ +void black_hole (void); + +/** + * set the timezone + * + * @param tz timezone + * + * @return the old timezone + */ +const char* set_tz (const char* tz); + + +/** + * switch the locale to en_US.utf8, return TRUE if it succeeds + * + * @return TRUE if the switch succeeds, FALSE otherwise + */ +gboolean set_en_us_utf8_locale (void); + +G_END_DECLS + +#endif /*__TEST_MU_COMMON_H__*/ diff --git a/lib/test-mu-contacts.cc b/lib/test-mu-contacts.cc new file mode 100644 index 0000000..141f8b9 --- /dev/null +++ b/lib/test-mu-contacts.cc @@ -0,0 +1,91 @@ +/* +** Copyright (C) 2019 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + + +#include "config.h" + +#include <glib.h> +#include "test-mu-common.h" +#include "mu-contacts.hh" + +static void +test_mu_contacts_01() +{ + Mu::Contacts contacts (""); + + g_assert_true (contacts.empty()); + g_assert_cmpuint (contacts.size(), ==, 0); + + contacts.add(std::move(Mu::ContactInfo ("Foo <foo.bar@example.com>", + "foo.bar@example.com", "Foo", + false, 12345))); + g_assert_false (contacts.empty()); + g_assert_cmpuint (contacts.size(), ==, 1); + + contacts.add(std::move(Mu::ContactInfo ("Cuux <cuux.fnorb@example.com>", + "cuux@example.com", "Cuux", true, + 54321))); + + g_assert_cmpuint (contacts.size(), ==, 2); + + contacts.add(std::move(Mu::ContactInfo ("foo.bar@example.com", + "foo.bar@example.com", "Foo", + false, 77777))); + g_assert_cmpuint (contacts.size(), ==, 2); + + contacts.add(std::move(Mu::ContactInfo ("Foo.Bar@Example.Com", + "Foo.Bar@Example.Com", "Foo", + false, 88888))); + g_assert_cmpuint (contacts.size(), ==, 2); + // note: replaces first. + + { + const auto info = contacts._find("bla@example.com"); + g_assert_false (info); + } + + + { + const auto info = contacts._find("foo.BAR@example.com"); + g_assert_true (info); + + g_assert_cmpstr(info->email.c_str(), ==, "Foo.Bar@Example.Com"); + } + + contacts.clear(); + g_assert_true (contacts.empty()); + g_assert_cmpuint (contacts.size(), ==, 0); +} + + + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/mu-contacts/01", test_mu_contacts_01); + + g_log_set_handler (NULL, + (GLogLevelFlags) + (G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION), + (GLogFunc)black_hole, NULL); + + return g_test_run (); +} diff --git a/lib/test-mu-container.c b/lib/test-mu-container.c new file mode 100644 index 0000000..475e302 --- /dev/null +++ b/lib/test-mu-container.c @@ -0,0 +1,83 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2014 Jakub Sitnicki <jsitnicki@gmail.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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include <glib.h> + +#include "test-mu-common.h" +#include "mu-container.h" + +static gboolean +container_has_children (const MuContainer *c) +{ + return c && c->child; +} + +static gboolean +container_is_sibling_of (const MuContainer *c, const MuContainer *sibling) +{ + const MuContainer *cur; + + for (cur = c; cur; cur = cur->next) { + if (cur == sibling) + return TRUE; + } + + return container_is_sibling_of (sibling, c); +} + +static void +test_mu_container_splice_children_when_parent_has_no_siblings (void) +{ + MuContainer *child, *parent, *root_set; + + child = mu_container_new (NULL, 0, "child"); + parent = mu_container_new (NULL, 0, "parent"); + parent = mu_container_append_children (parent, child); + + root_set = parent; + root_set = mu_container_splice_children (root_set, parent); + + g_assert (root_set != NULL); + g_assert (!container_has_children(parent)); + g_assert (container_is_sibling_of (root_set, child)); + + mu_container_destroy(parent); + mu_container_destroy(child); +} + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/mu-container/mu-container-splice-children-when-parent-has-no-siblings", + test_mu_container_splice_children_when_parent_has_no_siblings); + + g_log_set_handler (NULL, + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION, + (GLogFunc)black_hole, NULL); + + return g_test_run (); +} diff --git a/lib/test-mu-date.c b/lib/test-mu-date.c new file mode 100644 index 0000000..5cb6d5f --- /dev/null +++ b/lib/test-mu-date.c @@ -0,0 +1,93 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include <glib.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> + +#include <locale.h> + +#include "test-mu-common.h" +#include "mu-date.h" + + + + + +static void +test_mu_date_interpret_begin (void) +{ + time_t now; + now = time (NULL); + + g_assert_cmpstr (mu_date_interpret_s ("now", TRUE) , ==, + mu_date_str_s("%Y%m%d%H%M%S", now)); + + g_assert_cmpstr (mu_date_interpret_s ("today", TRUE) , ==, + mu_date_str_s("%Y%m%d000000", now)); +} + +static void +test_mu_date_interpret_end (void) +{ + time_t now; + now = time (NULL); + + g_assert_cmpstr (mu_date_interpret_s ("now", FALSE) , ==, + mu_date_str_s("%Y%m%d%H%M%S", now)); + + g_assert_cmpstr (mu_date_interpret_s ("today", FALSE) , ==, + mu_date_str_s("%Y%m%d235959", now)); +} + + + + + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/mu-str/mu_date_parse_hdwmy", + test_mu_date_parse_hdwmy); + g_test_add_func ("/mu-str/mu_date_complete_begin", + test_mu_date_complete_begin); + g_test_add_func ("/mu-str/mu_date_complete_end", + test_mu_date_complete_end); + + g_test_add_func ("/mu-str/mu_date_interpret_begin", + test_mu_date_interpret_begin); + g_test_add_func ("/mu-str/mu_date_interpret_end", + test_mu_date_interpret_end); + + + g_log_set_handler (NULL, + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION, + (GLogFunc)black_hole, NULL); + + return g_test_run (); +} diff --git a/lib/test-mu-flags.c b/lib/test-mu-flags.c new file mode 100644 index 0000000..36db9c8 --- /dev/null +++ b/lib/test-mu-flags.c @@ -0,0 +1,193 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include <glib.h> +#include "mu-flags.h" +#include "test-mu-common.h" + + +static void +test_mu_flag_char (void) +{ + g_assert_cmpuint (mu_flag_char (MU_FLAG_DRAFT), ==, 'D'); + g_assert_cmpuint (mu_flag_char (MU_FLAG_FLAGGED), ==, 'F'); + g_assert_cmpuint (mu_flag_char (MU_FLAG_PASSED), ==, 'P'); + g_assert_cmpuint (mu_flag_char (MU_FLAG_REPLIED), ==, 'R'); + g_assert_cmpuint (mu_flag_char (MU_FLAG_SEEN), ==, 'S'); + g_assert_cmpuint (mu_flag_char (MU_FLAG_TRASHED), ==, 'T'); + g_assert_cmpuint (mu_flag_char (MU_FLAG_NEW), ==, 'N'); + g_assert_cmpuint (mu_flag_char (MU_FLAG_SIGNED), ==, 'z'); + g_assert_cmpuint (mu_flag_char (MU_FLAG_ENCRYPTED), ==, 'x'); + g_assert_cmpuint (mu_flag_char (MU_FLAG_HAS_ATTACH), ==, 'a'); + g_assert_cmpuint (mu_flag_char (MU_FLAG_UNREAD), ==, 'u'); + g_assert_cmpuint (mu_flag_char (12345), ==, 0); +} + + + +static void +test_mu_flag_name (void) +{ + g_assert_cmpstr (mu_flag_name (MU_FLAG_DRAFT), ==, "draft"); + g_assert_cmpstr (mu_flag_name (MU_FLAG_FLAGGED), ==, "flagged"); + g_assert_cmpstr (mu_flag_name (MU_FLAG_PASSED), ==, "passed"); + g_assert_cmpstr (mu_flag_name (MU_FLAG_REPLIED), ==, "replied"); + g_assert_cmpstr (mu_flag_name (MU_FLAG_SEEN), ==, "seen"); + g_assert_cmpstr (mu_flag_name (MU_FLAG_TRASHED), ==, "trashed"); + g_assert_cmpstr (mu_flag_name (MU_FLAG_NEW), ==, "new"); + g_assert_cmpstr (mu_flag_name (MU_FLAG_SIGNED), ==, "signed"); + g_assert_cmpstr (mu_flag_name (MU_FLAG_ENCRYPTED), ==, "encrypted"); + g_assert_cmpstr (mu_flag_name (MU_FLAG_HAS_ATTACH), ==, "attach"); + g_assert_cmpstr (mu_flag_name (MU_FLAG_UNREAD), ==, "unread"); + g_assert_cmpstr (mu_flag_name (12345), ==, NULL); +} + +static void +test_mu_flags_to_str_s (void) +{ + g_assert_cmpstr (mu_flags_to_str_s(MU_FLAG_PASSED|MU_FLAG_SIGNED, + MU_FLAG_TYPE_ANY), + ==, "Pz"); + g_assert_cmpstr (mu_flags_to_str_s(MU_FLAG_NEW, MU_FLAG_TYPE_ANY), + ==, "N"); + g_assert_cmpstr (mu_flags_to_str_s(MU_FLAG_HAS_ATTACH|MU_FLAG_TRASHED, + MU_FLAG_TYPE_ANY), + ==, "Ta"); + g_assert_cmpstr (mu_flags_to_str_s(MU_FLAG_NONE, MU_FLAG_TYPE_ANY), + ==, ""); + + g_assert_cmpstr (mu_flags_to_str_s(MU_FLAG_PASSED|MU_FLAG_SIGNED, + MU_FLAG_TYPE_CONTENT), + ==, "z"); + + g_assert_cmpstr (mu_flags_to_str_s(MU_FLAG_NEW, MU_FLAG_TYPE_MAILDIR), + ==, "N"); + g_assert_cmpstr (mu_flags_to_str_s(MU_FLAG_HAS_ATTACH|MU_FLAG_TRASHED, + MU_FLAG_TYPE_MAILFILE), + ==, "T"); + + g_assert_cmpstr (mu_flags_to_str_s(MU_FLAG_NONE, MU_FLAG_TYPE_PSEUDO), + ==, ""); +} + + +static void +test_mu_flags_from_str (void) +{ + /* note, the 3rd arg to mu_flags_from_str determines whether + * invalid flags will be ignored (if TRUE) or MU_FLAG_INVALID (if FALSE) + */ + + g_assert_cmpuint (mu_flags_from_str ("RP", MU_FLAG_TYPE_ANY, TRUE), ==, + MU_FLAG_REPLIED | MU_FLAG_PASSED); + g_assert_cmpuint (mu_flags_from_str ("Nz", MU_FLAG_TYPE_ANY, TRUE), ==, + MU_FLAG_NEW | MU_FLAG_SIGNED); + g_assert_cmpuint (mu_flags_from_str ("axD", MU_FLAG_TYPE_ANY, TRUE), ==, + MU_FLAG_HAS_ATTACH | MU_FLAG_ENCRYPTED | MU_FLAG_DRAFT); + + g_assert_cmpuint (mu_flags_from_str ("RP", MU_FLAG_TYPE_MAILFILE, TRUE), ==, + MU_FLAG_REPLIED | MU_FLAG_PASSED); + g_assert_cmpuint (mu_flags_from_str ("Nz", MU_FLAG_TYPE_MAILFILE, TRUE), ==, + MU_FLAG_NONE); + + /* ignore errors or not */ + g_assert_cmpuint (mu_flags_from_str ("qwi", MU_FLAG_TYPE_MAILFILE, FALSE), ==, + MU_FLAG_INVALID); + g_assert_cmpuint (mu_flags_from_str ("qwi", MU_FLAG_TYPE_MAILFILE, TRUE), ==, + 0); + + +} + +static void +test_mu_flags_from_str_delta (void) +{ + g_assert_cmpuint (mu_flags_from_str_delta ("+S-R", + MU_FLAG_REPLIED | MU_FLAG_DRAFT, + MU_FLAG_TYPE_ANY),==, + MU_FLAG_SEEN | MU_FLAG_DRAFT); + + g_assert_cmpuint (mu_flags_from_str_delta ("", + MU_FLAG_REPLIED | MU_FLAG_DRAFT, + MU_FLAG_TYPE_ANY),==, + MU_FLAG_REPLIED | MU_FLAG_DRAFT); + + g_assert_cmpuint (mu_flags_from_str_delta ("-N+P+S-D", + MU_FLAG_SIGNED | MU_FLAG_DRAFT, + MU_FLAG_TYPE_ANY),==, + MU_FLAG_PASSED | MU_FLAG_SEEN | MU_FLAG_SIGNED); +} + + +static void +test_mu_flags_custom_from_str (void) +{ + unsigned u; + + struct { + const char *str; + const char *expected; + } cases[] = { + { "ABC", "ABC" }, + { "PAF", "A" }, + { "ShelloPwoFrDldR123", "helloworld123" }, + { "SPD", NULL } + }; + + for (u = 0; u != G_N_ELEMENTS(cases); ++u) { + char *cust; + cust = mu_flags_custom_from_str (cases[u].str); + if (g_test_verbose()) + g_print ("%s: str:%s; got:%s; expected:%s\n", + __func__, cases[u].str, cust, cases[u].expected); + g_assert_cmpstr (cust, ==, cases[u].expected); + g_free (cust); + } +} + + + +int +main (int argc, char *argv[]) +{ + int rv; + g_test_init (&argc, &argv, NULL); + + /* mu_msg_str_date */ + g_test_add_func ("/mu-flags/test-mu-flag-char", test_mu_flag_char); + g_test_add_func ("/mu-flags/test-mu-flag-name",test_mu_flag_name); + g_test_add_func ("/mu-flags/test-mu-flags-to-str-s",test_mu_flags_to_str_s); + g_test_add_func ("/mu-flags/test-mu-flags-from-str",test_mu_flags_from_str); + g_test_add_func ("/mu-flags/test-mu-flags-from-str-delta",test_mu_flags_from_str_delta ); + g_test_add_func ("/mu-flags/test-mu-flags-custom-from-str", + test_mu_flags_custom_from_str); + + g_log_set_handler (NULL, + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION, + (GLogFunc)black_hole, NULL); + + rv = g_test_run (); + + return rv; +} diff --git a/lib/test-mu-maildir.c b/lib/test-mu-maildir.c new file mode 100644 index 0000000..3952127 --- /dev/null +++ b/lib/test-mu-maildir.c @@ -0,0 +1,693 @@ +/* +** Copyright (C) 2008-2016 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include <glib.h> +#include <glib/gstdio.h> + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include "test-mu-common.h" +#include "mu-maildir.h" +#include "utils/mu-util.h" + +static void +test_mu_maildir_mkdir_01 (void) +{ + int i; + gchar *tmpdir, *mdir, *tmp; + const gchar *subs[] = {"tmp", "cur", "new"}; + + tmpdir = test_mu_common_get_random_tmpdir (); + mdir = g_strdup_printf ("%s%c%s", tmpdir, G_DIR_SEPARATOR, + "cuux"); + + g_assert_cmpuint (mu_maildir_mkdir (mdir, 0755, FALSE, NULL), + ==, TRUE); + + for (i = 0; i != G_N_ELEMENTS(subs); ++i) { + gchar* dir; + + dir = g_strdup_printf ("%s%c%s", mdir, G_DIR_SEPARATOR, + subs[i]); + g_assert_cmpuint (g_access (dir, R_OK), ==, 0); + g_assert_cmpuint (g_access (dir, W_OK), ==, 0); + g_free (dir); + } + + tmp = g_strdup_printf ("%s%c%s", mdir, G_DIR_SEPARATOR, ".noindex"); + g_assert_cmpuint (g_access (tmp, F_OK), !=, 0); + + g_free (tmp); + g_free (tmpdir); + g_free (mdir); + +} + + +static void +test_mu_maildir_mkdir_02 (void) +{ + int i; + gchar *tmpdir, *mdir, *tmp; + const gchar *subs[] = {"tmp", "cur", "new"}; + + tmpdir = test_mu_common_get_random_tmpdir (); + mdir = g_strdup_printf ("%s%c%s", tmpdir, G_DIR_SEPARATOR, + "cuux"); + + g_assert_cmpuint (mu_maildir_mkdir (mdir, 0755, TRUE, NULL), + ==, TRUE); + + for (i = 0; i != G_N_ELEMENTS(subs); ++i) { + gchar* dir; + + dir = g_strdup_printf ("%s%c%s", mdir, G_DIR_SEPARATOR, + subs[i]); + g_assert_cmpuint (g_access (dir, R_OK), ==, 0); + + g_assert_cmpuint (g_access (dir, W_OK), ==, 0); + g_free (dir); + } + + tmp = g_strdup_printf ("%s%c%s", mdir, G_DIR_SEPARATOR, ".noindex"); + g_assert_cmpuint (g_access (tmp, F_OK), ==, 0); + + g_free (tmp); + g_free (tmpdir); + g_free (mdir); +} + + +static void +test_mu_maildir_mkdir_03 (void) +{ + int i; + gchar *tmpdir, *mdir, *tmp; + const gchar *subs[] = {"tmp", "cur", "new"}; + + tmpdir = test_mu_common_get_random_tmpdir (); + mdir = g_strdup_printf ("%s%c%s", tmpdir, G_DIR_SEPARATOR, + "cuux"); + + /* create part of the structure already... */ + { + gchar *dir; + dir = g_strdup_printf ("%s%ccur", mdir, G_DIR_SEPARATOR); + g_assert_cmpuint (g_mkdir_with_parents (dir, 0755), ==, 0); + g_free (dir); + } + + /* this should still work */ + g_assert_cmpuint (mu_maildir_mkdir (mdir, 0755, FALSE, NULL), + ==, TRUE); + + for (i = 0; i != G_N_ELEMENTS(subs); ++i) { + gchar* dir; + + dir = g_strdup_printf ("%s%c%s", mdir, G_DIR_SEPARATOR, + subs[i]); + g_assert_cmpuint (g_access (dir, R_OK), ==, 0); + g_assert_cmpuint (g_access (dir, W_OK), ==, 0); + g_free (dir); + } + + tmp = g_strdup_printf ("%s%c%s", mdir, G_DIR_SEPARATOR, ".noindex"); + g_assert_cmpuint (g_access (tmp, F_OK), !=, 0); + + g_free (tmp); + g_free (tmpdir); + g_free (mdir); + +} + + + +static void +test_mu_maildir_mkdir_04 (void) +{ + gchar *tmpdir, *mdir; + + tmpdir = test_mu_common_get_random_tmpdir (); + mdir = g_strdup_printf ("%s%c%s", tmpdir, G_DIR_SEPARATOR, + "cuux"); + + /* create part of the structure already... */ + { + gchar *dir; + g_assert_cmpuint (g_mkdir_with_parents (mdir, 0755), ==, 0); + dir = g_strdup_printf ("%s%ccur", mdir, G_DIR_SEPARATOR); + g_assert_cmpuint (g_mkdir_with_parents (dir, 0000), ==, 0); + g_free (dir); + } + + /* this should fail now, because cur is not read/writable */ + g_assert_cmpuint (mu_maildir_mkdir (mdir, 0755, FALSE, NULL), + ==, (geteuid()==0 ? TRUE : FALSE)); + g_free (tmpdir); + g_free (mdir); +} + + + + +static gboolean +ignore_error (const char* log_domain, GLogLevelFlags log_level, const gchar* msg, + gpointer user_data) +{ + return FALSE; /* don't abort */ +} + +static void +test_mu_maildir_mkdir_05 (void) +{ + /* this must fail */ + g_test_log_set_fatal_handler ((GTestLogFatalFunc)ignore_error, NULL); + + g_assert_cmpuint (mu_maildir_mkdir (NULL, 0755, TRUE, NULL), + ==, FALSE); +} + + +static gchar* +copy_test_data (void) +{ + gchar *dir, *cmd; + + dir = test_mu_common_get_random_tmpdir(); + cmd = g_strdup_printf ("mkdir -m 0700 %s", dir); + if (g_test_verbose()) + g_print ("cmd: %s\n", cmd); + g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL)); + g_free (cmd); + + cmd = g_strdup_printf ("cp -R %s %s", MU_TESTMAILDIR, dir); + if (g_test_verbose()) + g_print ("cmd: %s\n", cmd); + g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL)); + g_free (cmd); + + return dir; +} + + +typedef struct { + int _file_count; + int _dir_entered; + int _dir_left; +} WalkData; + +static MuError +dir_cb (const char *fullpath, gboolean enter, WalkData *data) +{ + if (enter) + ++data->_dir_entered; + else + ++data->_dir_left; + + if (g_test_verbose()) + g_print ("%s: %s: %s (%u)\n", __func__, enter ? "entering" : "leaving", + fullpath, enter ? data->_dir_entered : data->_dir_left); + + return MU_OK; +} + + +static MuError +msg_cb (const char *fullpath, const char* mdir, struct stat *statinfo, + WalkData *data) +{ + ++data->_file_count; + return MU_OK; +} + + +static void +test_mu_maildir_walk_01 (void) +{ + char *tmpdir; + WalkData data; + MuError rv; + + tmpdir = copy_test_data (); + memset (&data, 0, sizeof(WalkData)); + + rv = mu_maildir_walk (tmpdir, + (MuMaildirWalkMsgCallback)msg_cb, + (MuMaildirWalkDirCallback)dir_cb, + TRUE, + &data); + + g_assert_cmpuint (MU_OK, ==, rv); + g_assert_cmpuint (data._file_count, ==, 19); + + g_assert_cmpuint (data._dir_entered,==, 5); + g_assert_cmpuint (data._dir_left,==, 5); + + g_free (tmpdir); +} + + +static void +test_mu_maildir_walk (void) +{ + char *tmpdir, *cmd, *dir; + WalkData data; + MuError rv; + + tmpdir = copy_test_data (); + memset (&data, 0, sizeof(WalkData)); + + /* mark the 'new' dir with '.noindex', to ignore it */ + dir = g_strdup_printf ("%s%ctestdir%cnew", tmpdir, + G_DIR_SEPARATOR, G_DIR_SEPARATOR); + cmd = g_strdup_printf ("chmod 700 %s", dir); + g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL)); + g_free (cmd); + + cmd = g_strdup_printf ("touch %s%c.noindex", dir, G_DIR_SEPARATOR); + g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL)); + g_free (cmd); + g_free (dir); + + rv = mu_maildir_walk (tmpdir, + (MuMaildirWalkMsgCallback)msg_cb, + (MuMaildirWalkDirCallback)dir_cb, + TRUE, + &data); + + g_assert_cmpuint (MU_OK, ==, rv); + g_assert_cmpuint (data._file_count, ==, 15); + + g_assert_cmpuint (data._dir_entered,==, 4); + g_assert_cmpuint (data._dir_left,==, 4); + + g_free (tmpdir); +} + +static void +test_mu_maildir_walk_with_noupdate (void) +{ + char *tmpdir, *cmd, *dir; + WalkData data; + MuError rv; + + tmpdir = copy_test_data (); + + /* mark the 'new' dir with '.noindex', to ignore it */ + dir = g_strdup_printf ("%s%ctestdir%cnew", tmpdir, + G_DIR_SEPARATOR, G_DIR_SEPARATOR); + cmd = g_strdup_printf ("chmod 700 %s", dir); + g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL)); + g_free (cmd); + + memset (&data, 0, sizeof(WalkData)); + rv = mu_maildir_walk (tmpdir, + (MuMaildirWalkMsgCallback)msg_cb, + (MuMaildirWalkDirCallback)dir_cb, + FALSE, /* ie., non-full update */ + &data); + + g_assert_cmpuint (MU_OK, ==, rv); + g_assert_cmpuint (data._file_count, ==, 19); + g_assert_cmpuint (data._dir_entered,==, 5); + g_assert_cmpuint (data._dir_left,==, 5); + + /* again, full update. results should be the same, since there + * is no noupdate yet */ + memset (&data, 0, sizeof(WalkData)); + rv = mu_maildir_walk (tmpdir, + (MuMaildirWalkMsgCallback)msg_cb, + (MuMaildirWalkDirCallback)dir_cb, + TRUE, /* ie., full update */ + &data); + + g_assert_cmpuint (MU_OK, ==, rv); + g_assert_cmpuint (data._file_count, ==, 19); + g_assert_cmpuint (data._dir_entered,==, 5); + g_assert_cmpuint (data._dir_left,==, 5); + + /* add a '.noupdate' file; this affects the outcome when the + * 4th arg to mu_maildir_walk is FALSE */ + cmd = g_strdup_printf ("touch %s%c.noupdate", dir, G_DIR_SEPARATOR); + g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL)); + g_free (cmd); + + memset (&data, 0, sizeof(WalkData)); + rv = mu_maildir_walk (tmpdir, + (MuMaildirWalkMsgCallback)msg_cb, + (MuMaildirWalkDirCallback)dir_cb, + FALSE, /* non-full update */ + &data); + + g_assert_cmpuint (MU_OK, ==, rv); + g_assert_cmpuint (data._file_count, ==, 15); + + g_assert_cmpuint (data._dir_entered,==, 4); + g_assert_cmpuint (data._dir_left,==, 4); + + /* now run again, but do a full update */ + memset (&data, 0, sizeof(WalkData)); + rv = mu_maildir_walk (tmpdir, + (MuMaildirWalkMsgCallback)msg_cb, + (MuMaildirWalkDirCallback)dir_cb, + TRUE, /* full update */ + &data); + + g_assert_cmpuint (MU_OK, ==, rv); + g_assert_cmpuint (data._file_count, ==, 19); + + g_assert_cmpuint (data._dir_entered,==, 5); + g_assert_cmpuint (data._dir_left,==, 5); + + g_free (dir); + g_free (tmpdir); +} + + + + + + +static void +test_mu_maildir_get_flags_from_path (void) +{ + int i; + struct { + const char *path; + MuFlags flags; + } paths[] = { + { + "/home/foo/Maildir/test/cur/123456:2,FSR", + MU_FLAG_REPLIED | MU_FLAG_SEEN | MU_FLAG_FLAGGED + }, + { + "/home/foo/Maildir/test/new/123456", + MU_FLAG_NEW + }, + { + /* NOTE: when in new/, the :2,.. stuff is ignored */ + "/home/foo/Maildir/test/new/123456:2,FR", + MU_FLAG_NEW + }, + { + "/home/foo/Maildir/test/cur/123456:2,DTP", + MU_FLAG_DRAFT | MU_FLAG_TRASHED | + MU_FLAG_PASSED + }, + { + "/home/foo/Maildir/test/cur/123456:2,S", + MU_FLAG_SEEN + } + }; + + for (i = 0; i != G_N_ELEMENTS(paths); ++i) { + MuFlags flags; + flags = mu_maildir_get_flags_from_path(paths[i].path); + g_assert_cmpuint(flags, ==, paths[i].flags); + } +} + + + +static void +assert_matches_regexp (const char *str, const char *rx) +{ + if (!g_regex_match_simple (rx, str, 0, 0)) { + if (g_test_verbose ()) + g_print ("%s does not match %s", str, rx); + g_assert (0); + } +} + + + +static void +test_mu_maildir_get_new_path_new (void) +{ + int i; + + struct { + const char *oldpath; + MuFlags flags; + const char *newpath; + } paths[] = { + { + "/home/foo/Maildir/test/cur/123456:2,FR", + MU_FLAG_REPLIED, + "/home/foo/Maildir/test/cur/123456:2,R" + }, { + "/home/foo/Maildir/test/cur/123456:2,FR", + MU_FLAG_NEW, + "/home/foo/Maildir/test/new/123456" + }, { + "/home/foo/Maildir/test/new/123456:2,FR", + MU_FLAG_SEEN | MU_FLAG_REPLIED, + "/home/foo/Maildir/test/cur/123456:2,RS" + }, { + "/home/foo/Maildir/test/new/1313038887_0.697:2,", + MU_FLAG_SEEN | MU_FLAG_FLAGGED | MU_FLAG_PASSED, + "/home/foo/Maildir/test/cur/1313038887_0.697:2,FPS" + }, { + "/home/djcb/Maildir/trash/new/1312920597.2206_16.cthulhu", + MU_FLAG_SEEN, + "/home/djcb/Maildir/trash/cur/1312920597.2206_16.cthulhu:2,S" + } + }; + + for (i = 0; i != G_N_ELEMENTS(paths); ++i) { + char *str, *newbase; + str = mu_maildir_get_new_path (paths[i].oldpath, NULL, + paths[i].flags, TRUE); + newbase = g_path_get_basename (str); + assert_matches_regexp (newbase, + "\\d+\\." + "[[:xdigit:]]{16}\\." + "[[:alnum:]][[:alnum:]-]+(:2,.*)?"); + g_free (newbase); + g_free(str); + } +} + + + + +static void +test_mu_maildir_get_new_path_01 (void) +{ + int i; + + struct { + const char *oldpath; + MuFlags flags; + const char *newpath; + } paths[] = { + { + "/home/foo/Maildir/test/cur/123456:2,FR", + MU_FLAG_REPLIED, + "/home/foo/Maildir/test/cur/123456:2,R" + }, { + "/home/foo/Maildir/test/cur/123456:2,FR", + MU_FLAG_NEW, + "/home/foo/Maildir/test/new/123456" + }, { + "/home/foo/Maildir/test/new/123456:2,FR", + MU_FLAG_SEEN | MU_FLAG_REPLIED, + "/home/foo/Maildir/test/cur/123456:2,RS" + }, { + "/home/foo/Maildir/test/new/1313038887_0.697:2,", + MU_FLAG_SEEN | MU_FLAG_FLAGGED | MU_FLAG_PASSED, + "/home/foo/Maildir/test/cur/1313038887_0.697:2,FPS" + }, { + "/home/djcb/Maildir/trash/new/1312920597.2206_16.cthulhu", + MU_FLAG_SEEN, + "/home/djcb/Maildir/trash/cur/1312920597.2206_16.cthulhu:2,S" + } + }; + + for (i = 0; i != G_N_ELEMENTS(paths); ++i) { + gchar *str; + str = mu_maildir_get_new_path(paths[i].oldpath, NULL, + paths[i].flags, FALSE); + g_assert_cmpstr(str, ==, paths[i].newpath); + g_free(str); + } +} + + +static void +test_mu_maildir_get_new_path_02 (void) +{ + int i; + + struct { + const char *oldpath; + MuFlags flags; + const char *targetdir; + const char *newpath; + } paths[] = { + { + "/home/foo/Maildir/test/cur/123456:2,FR", + MU_FLAG_REPLIED, "/home/foo/Maildir/blabla", + "/home/foo/Maildir/blabla/cur/123456:2,R" + }, { + "/home/foo/Maildir/test/cur/123456:2,FR", + MU_FLAG_NEW, "/home/bar/Maildir/coffee", + "/home/bar/Maildir/coffee/new/123456" + }, { + "/home/foo/Maildir/test/new/123456", + MU_FLAG_SEEN | MU_FLAG_REPLIED, + "/home/cuux/Maildir/tea", + "/home/cuux/Maildir/tea/cur/123456:2,RS" + }, { + "/home/foo/Maildir/test/new/1313038887_0.697:2,", + MU_FLAG_SEEN | MU_FLAG_FLAGGED | MU_FLAG_PASSED, + "/home/boy/Maildir/stuff", + "/home/boy/Maildir/stuff/cur/1313038887_0.697:2,FPS" + } + }; + + for (i = 0; i != G_N_ELEMENTS(paths); ++i) { + gchar *str; + str = mu_maildir_get_new_path(paths[i].oldpath, + paths[i].targetdir, + paths[i].flags, FALSE); + g_assert_cmpstr(str, ==, paths[i].newpath); + g_free(str); + } +} + + +static void +test_mu_maildir_get_new_path_custom (void) +{ + int i; + + struct { + const char *oldpath; + MuFlags flags; + const char *targetdir; + const char *newpath; + } paths[] = { + { + "/home/foo/Maildir/test/cur/123456:2,FR", + MU_FLAG_REPLIED, "/home/foo/Maildir/blabla", + "/home/foo/Maildir/blabla/cur/123456:2,R" + }, { + "/home/foo/Maildir/test/cur/123456:2,hFeRllo123", + MU_FLAG_FLAGGED, "/home/foo/Maildir/blabla", + "/home/foo/Maildir/blabla/cur/123456:2,Fhello123" + }, { + "/home/foo/Maildir/test/cur/123456:2,abc", + MU_FLAG_PASSED, "/home/foo/Maildir/blabla", + "/home/foo/Maildir/blabla/cur/123456:2,Pabc" + } + }; + + for (i = 0; i != G_N_ELEMENTS(paths); ++i) { + gchar *str; + str = mu_maildir_get_new_path(paths[i].oldpath, + paths[i].targetdir, + paths[i].flags, FALSE); + g_assert_cmpstr(str, ==, paths[i].newpath); + g_free(str); + } +} + + + +static void +test_mu_maildir_get_maildir_from_path (void) +{ + unsigned u; + + struct { + const char *path, *exp; + } cases[] = { + {"/home/foo/Maildir/test/cur/123456:2,FR", + "/home/foo/Maildir/test"}, + {"/home/foo/Maildir/lala/new/1313038887_0.697:2,", + "/home/foo/Maildir/lala"} + }; + + + for (u = 0; u != G_N_ELEMENTS(cases); ++u) { + gchar *mdir; + mdir = mu_maildir_get_maildir_from_path (cases[u].path); + g_assert_cmpstr(mdir,==,cases[u].exp); + g_free (mdir); + } +} + + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + /* mu_util_maildir_mkmdir */ + g_test_add_func ("/mu-maildir/mu-maildir-mkdir-01", + test_mu_maildir_mkdir_01); + g_test_add_func ("/mu-maildir/mu-maildir-mkdir-02", + test_mu_maildir_mkdir_02); + g_test_add_func ("/mu-maildir/mu-maildir-mkdir-03", + test_mu_maildir_mkdir_03); + g_test_add_func ("/mu-maildir/mu-maildir-mkdir-04", + test_mu_maildir_mkdir_04); + g_test_add_func ("/mu-maildir/mu-maildir-mkdir-05", + test_mu_maildir_mkdir_05); + + + /* mu_util_maildir_walk */ + g_test_add_func ("/mu-maildir/mu-maildir-walk-01", + test_mu_maildir_walk_01); + g_test_add_func ("/mu-maildir/mu-maildir-walk", + test_mu_maildir_walk); + g_test_add_func ("/mu-maildir/mu-maildir-walk-with-noupdate", + test_mu_maildir_walk_with_noupdate); + + /* get/set flags */ + g_test_add_func("/mu-maildir/mu-maildir-get-new-path-new", + test_mu_maildir_get_new_path_new); + + g_test_add_func("/mu-maildir/mu-maildir-get-new-path-01", + test_mu_maildir_get_new_path_01); + g_test_add_func("/mu-maildir/mu-maildir-get-new-path-02", + test_mu_maildir_get_new_path_02); + g_test_add_func("/mu-maildir/mu-maildir-get-new-path-custom", + test_mu_maildir_get_new_path_custom); + g_test_add_func("/mu-maildir/mu-maildir-get-flags-from-path", + test_mu_maildir_get_flags_from_path); + + + g_test_add_func("/mu-maildir/mu-maildir-get-maildir-from-path", + test_mu_maildir_get_maildir_from_path); + + g_log_set_handler (NULL, + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| + G_LOG_FLAG_RECURSION, + (GLogFunc)black_hole, NULL); + + return g_test_run (); +} diff --git a/lib/test-mu-msg-fields.c b/lib/test-mu-msg-fields.c new file mode 100644 index 0000000..27864d8 --- /dev/null +++ b/lib/test-mu-msg-fields.c @@ -0,0 +1,134 @@ +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include <glib.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> + +#include <locale.h> + +#include "test-mu-common.h" +#include "mu-msg-fields.h" + +static void +test_mu_msg_field_body (void) +{ + MuMsgFieldId field; + + field = MU_MSG_FIELD_ID_BODY_TEXT; + + g_assert_cmpstr (mu_msg_field_name(field),==, "body"); + g_assert_cmpuint (mu_msg_field_shortcut(field),==, 'b'); + g_assert_cmpuint (mu_msg_field_xapian_prefix(field),==, 'B'); + + g_assert_cmpuint (mu_msg_field_is_numeric(field), ==, FALSE); +} + +static void +test_mu_msg_field_subject (void) +{ + MuMsgFieldId field; + + field = MU_MSG_FIELD_ID_SUBJECT; + + g_assert_cmpstr (mu_msg_field_name(field),==, "subject"); + g_assert_cmpuint (mu_msg_field_shortcut(field),==, 's'); + g_assert_cmpuint (mu_msg_field_xapian_prefix(field),==, 'S'); + + g_assert_cmpuint (mu_msg_field_is_numeric(field), ==,FALSE); +} + +static void +test_mu_msg_field_to (void) +{ + MuMsgFieldId field; + + field = MU_MSG_FIELD_ID_TO; + + g_assert_cmpstr (mu_msg_field_name(field),==, "to"); + g_assert_cmpuint (mu_msg_field_shortcut(field),==, 't'); + g_assert_cmpuint (mu_msg_field_xapian_prefix(field),==, 'T'); + + g_assert_cmpuint (mu_msg_field_is_numeric(field), ==, FALSE); +} + + +static void +test_mu_msg_field_prio (void) +{ + MuMsgFieldId field; + + field = MU_MSG_FIELD_ID_PRIO; + + g_assert_cmpstr (mu_msg_field_name(field),==, "prio"); + g_assert_cmpuint (mu_msg_field_shortcut(field),==, 'p'); + g_assert_cmpuint (mu_msg_field_xapian_prefix(field),==, 'P'); + + g_assert_cmpuint (mu_msg_field_is_numeric(field), ==, TRUE); +} + +static void +test_mu_msg_field_flags (void) +{ + MuMsgFieldId field; + + field = MU_MSG_FIELD_ID_FLAGS; + + g_assert_cmpstr (mu_msg_field_name(field),==, "flag"); + g_assert_cmpuint (mu_msg_field_shortcut(field),==, 'g'); + g_assert_cmpuint (mu_msg_field_xapian_prefix(field),==, 'G'); + + g_assert_cmpuint (mu_msg_field_is_numeric(field),==, TRUE); +} + + + + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + /* mu_msg_str_date */ + g_test_add_func ("/mu-msg-fields/mu-msg-field-body", + test_mu_msg_field_body); + g_test_add_func ("/mu-msg-fields/mu-msg-field-subject", + test_mu_msg_field_subject); + g_test_add_func ("/mu-msg-fields/mu-msg-field-to", + test_mu_msg_field_to); + g_test_add_func ("/mu-msg-fields/mu-msg-field-prio", + test_mu_msg_field_prio); + g_test_add_func ("/mu-msg-fields/mu-msg-field-flags", + test_mu_msg_field_flags); + + /* FIXME: add tests for mu_msg_str_flags; but note the + * function simply calls mu_msg_field_str */ + + g_log_set_handler (NULL, + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | + G_LOG_FLAG_RECURSION, + (GLogFunc)black_hole, NULL); + + return g_test_run (); +} diff --git a/lib/test-mu-msg.c b/lib/test-mu-msg.c new file mode 100644 index 0000000..fef368b --- /dev/null +++ b/lib/test-mu-msg.c @@ -0,0 +1,598 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include <glib.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> + +#include <locale.h> + +#include "test-mu-common.h" +#include "mu-msg.h" +#include "utils/mu-str.h" + + +static MuMsg* +get_msg (const char *path) +{ + GError *err; + MuMsg *msg; + + if (g_test_verbose ()) + g_print (">> %s\n", path); + + err = NULL; + msg = mu_msg_new_from_file (path, NULL, &err); + + if (!msg) { + g_printerr ("failed to load %s: %s\n", + path, err ? err->message : "something went wrong"); + g_clear_error (&err); + g_assert (0); + } + + return msg; +} + + + +static gboolean +check_contact_01 (MuMsgContact *contact, int *idx) +{ + switch (*idx) { + case 0: + g_assert_cmpstr (mu_msg_contact_name (contact), + ==, "Mickey Mouse"); + g_assert_cmpstr (mu_msg_contact_email (contact), + ==, "anon@example.com"); + break; + case 1: + g_assert_cmpstr (mu_msg_contact_name (contact), + ==, "Donald Duck"); + g_assert_cmpstr (mu_msg_contact_email (contact), + ==, "gcc-help@gcc.gnu.org"); + break; + default: + g_assert_not_reached (); + } + ++(*idx); + + return TRUE; +} + + +static void +test_mu_msg_01 (void) +{ + MuMsg *msg; + gint i; + + msg = get_msg (MU_TESTMAILDIR4 "/1220863042.12663_1.mindcrime!2,S"); + + g_assert_cmpstr (mu_msg_get_to(msg), + ==, "Donald Duck <gcc-help@gcc.gnu.org>"); + g_assert_cmpstr (mu_msg_get_subject(msg), + ==, "gcc include search order"); + g_assert_cmpstr (mu_msg_get_from(msg), + ==, "Mickey Mouse <anon@example.com>"); + g_assert_cmpstr (mu_msg_get_msgid(msg), + ==, "3BE9E6535E3029448670913581E7A1A20D852173@" + "emss35m06.us.lmco.com"); + g_assert_cmpstr (mu_msg_get_header(msg, "Mailing-List"), + ==, + "contact gcc-help-help@gcc.gnu.org; run by ezmlm"); + g_assert_cmpuint (mu_msg_get_prio(msg), /* 'klub' */ + ==, MU_MSG_PRIO_NORMAL); + g_assert_cmpuint (mu_msg_get_date(msg), + ==, 1217530645); + + i = 0; + mu_msg_contact_foreach (msg, (MuMsgContactForeachFunc)check_contact_01, + &i); + g_assert_cmpint (i,==,2); + + mu_msg_unref (msg); +} + + + + + + +static gboolean +check_contact_02 (MuMsgContact *contact, int *idx) +{ + switch (*idx) { + case 0: + g_assert_cmpstr (mu_msg_contact_name (contact), + ==, NULL); + g_assert_cmpstr (mu_msg_contact_email (contact), + ==, "anon@example.com"); + break; + case 1: + g_assert_cmpstr (mu_msg_contact_name (contact), + ==, NULL); + g_assert_cmpstr (mu_msg_contact_email (contact), + ==, "help-gnu-emacs@gnu.org"); + break; + default: + g_assert_not_reached (); + } + ++(*idx); + + return TRUE; +} + + + +static void +test_mu_msg_02 (void) +{ + MuMsg *msg; + int i; + + msg = get_msg (MU_TESTMAILDIR4 "/1220863087.12663_19.mindcrime!2,S"); + + g_assert_cmpstr (mu_msg_get_to(msg), + ==, "help-gnu-emacs@gnu.org"); + g_assert_cmpstr (mu_msg_get_subject(msg), + ==, "Re: Learning LISP; Scheme vs elisp."); + g_assert_cmpstr (mu_msg_get_from(msg), + ==, "anon@example.com"); + g_assert_cmpstr (mu_msg_get_msgid(msg), + ==, "r6bpm5-6n6.ln1@news.ducksburg.com"); + g_assert_cmpstr (mu_msg_get_header(msg, "Errors-To"), + ==, "help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org"); + g_assert_cmpuint (mu_msg_get_prio(msg), /* 'low' */ + ==, MU_MSG_PRIO_LOW); + g_assert_cmpuint (mu_msg_get_date(msg), + ==, 1218051515); + + i = 0; + mu_msg_contact_foreach (msg, + (MuMsgContactForeachFunc)check_contact_02, + &i); + g_assert_cmpint (i,==,2); + g_assert_cmpuint (mu_msg_get_flags(msg), ==, MU_FLAG_SEEN|MU_FLAG_LIST); + + mu_msg_unref (msg); +} + +static void +test_mu_msg_03 (void) +{ + MuMsg *msg; + const GSList *params; + + msg = get_msg (MU_TESTMAILDIR4 "/1283599333.1840_11.cthulhu!2,"); + g_assert_cmpstr (mu_msg_get_to(msg), + ==, "Bilbo Baggins <bilbo@anotherexample.com>"); + g_assert_cmpstr (mu_msg_get_subject(msg), + ==, "Greetings from Lothlórien"); + g_assert_cmpstr (mu_msg_get_from(msg), + ==, "Frodo Baggins <frodo@example.com>"); + g_assert_cmpuint (mu_msg_get_prio(msg), /* 'low' */ + ==, MU_MSG_PRIO_NORMAL); + g_assert_cmpuint (mu_msg_get_date(msg), + ==, 0); + g_assert_cmpstr (mu_msg_get_body_text(msg, MU_MSG_OPTION_NONE), + ==, + "\nLet's write some fünkÿ text\nusing umlauts.\n\nFoo.\n"); + + params = mu_msg_get_body_text_content_type_parameters( + msg, MU_MSG_OPTION_NONE); + g_assert_cmpuint (g_slist_length ((GSList*)params), ==, 2); + + g_assert_cmpstr ((char*)params->data,==, "charset"); + params = g_slist_next(params); + g_assert_cmpstr ((char*)params->data,==,"UTF-8"); + + g_assert_cmpuint (mu_msg_get_flags(msg), + ==, MU_FLAG_UNREAD); /* not seen => unread */ + + mu_msg_unref (msg); +} + + +static void +test_mu_msg_04 (void) +{ + MuMsg *msg; + + msg = get_msg (MU_TESTMAILDIR4 "/mail5"); + g_assert_cmpstr (mu_msg_get_to(msg), + ==, "George Custer <gac@example.com>"); + g_assert_cmpstr (mu_msg_get_subject(msg), + ==, "pics for you"); + g_assert_cmpstr (mu_msg_get_from(msg), + ==, "Sitting Bull <sb@example.com>"); + g_assert_cmpuint (mu_msg_get_prio(msg), /* 'low' */ + ==, MU_MSG_PRIO_NORMAL); + g_assert_cmpuint (mu_msg_get_date(msg), + ==, 0); + g_assert_cmpuint (mu_msg_get_flags(msg), + ==, MU_FLAG_HAS_ATTACH|MU_FLAG_UNREAD); + mu_msg_unref (msg); +} + + +static void +test_mu_msg_multimime (void) +{ + MuMsg *msg; + + msg = get_msg (MU_TESTMAILDIR4 "/multimime!2,FS"); + /* ie., are text parts properly concatenated? */ + g_assert_cmpstr (mu_msg_get_subject(msg), + ==, "multimime"); + g_assert_cmpstr (mu_msg_get_body_text(msg, MU_MSG_OPTION_NONE), + ==, "abcdef"); + g_assert_cmpuint (mu_msg_get_flags(msg), + ==, MU_FLAG_FLAGGED | MU_FLAG_SEEN | + MU_FLAG_HAS_ATTACH); + mu_msg_unref (msg); +} + + + +static void +test_mu_msg_flags (void) +{ + unsigned u; + + struct { + const char *path; + MuFlags flags; + } msgflags [] = { + { MU_TESTMAILDIR4 "/multimime!2,FS", + MU_FLAG_FLAGGED | MU_FLAG_SEEN | + MU_FLAG_HAS_ATTACH }, + { MU_TESTMAILDIR4 "/special!2,Sabc", + MU_FLAG_SEEN } + + }; + + for (u = 0; u != G_N_ELEMENTS(msgflags); ++u) { + MuMsg *msg; + MuFlags flags; + + g_assert ((msg = get_msg (msgflags[u].path))); + flags = mu_msg_get_flags (msg); + + if (g_test_verbose()) + g_print ("=> %s [ %s, %u] <=> [ %s, %u]\n", + msgflags[u].path, + mu_flags_to_str_s(msgflags[u].flags, + MU_FLAG_TYPE_ANY), + (unsigned)msgflags[u].flags, + mu_flags_to_str_s(flags, MU_FLAG_TYPE_ANY), + (unsigned)flags); + g_assert_cmpuint (flags ,==, msgflags[u].flags); + mu_msg_unref (msg); + } +} + + +static void +test_mu_msg_umlaut (void) +{ + MuMsg *msg; + + msg = get_msg (MU_TESTMAILDIR4 "/1305664394.2171_402.cthulhu!2,"); + g_assert_cmpstr (mu_msg_get_to(msg), + ==, "Helmut Kröger <hk@testmu.xxx>"); + g_assert_cmpstr (mu_msg_get_subject(msg), + ==, "Motörhead"); + g_assert_cmpstr (mu_msg_get_from(msg), + ==, "Mü <testmu@testmu.xx>"); + g_assert_cmpuint (mu_msg_get_prio(msg), /* 'low' */ + ==, MU_MSG_PRIO_NORMAL); + g_assert_cmpuint (mu_msg_get_date(msg), + ==, 0); + + mu_msg_unref (msg); +} + + +static void +test_mu_msg_references (void) +{ + MuMsg *msg; + const GSList *refs; + + msg = get_msg (MU_TESTMAILDIR4 "/1305664394.2171_402.cthulhu!2,"); + refs = mu_msg_get_references(msg); + + g_assert_cmpuint (g_slist_length ((GSList*)refs), ==, 4); + + g_assert_cmpstr ((char*)refs->data,==, "non-exist-01@msg.id"); + refs = g_slist_next (refs); + g_assert_cmpstr ((char*)refs->data,==, "non-exist-02@msg.id"); + refs = g_slist_next (refs); + g_assert_cmpstr ((char*)refs->data,==, "non-exist-03@msg.id"); + refs = g_slist_next (refs); + g_assert_cmpstr ((char*)refs->data,==, "non-exist-04@msg.id"); + refs = g_slist_next (refs); + + mu_msg_unref (msg); +} + + + +static void +test_mu_msg_references_dups (void) +{ + MuMsg *msg; + const GSList *refs; + const char *mlist; + + msg = get_msg (MU_TESTMAILDIR4 "/1252168370_3.14675.cthulhu!2,S"); + refs = mu_msg_get_references(msg); + + /* make sure duplicate msg-ids are filtered out */ + + g_assert_cmpuint (g_slist_length ((GSList*)refs), ==, 6); + + g_assert_cmpstr ((char*)refs->data,==, + "439C1136.90504@euler.org"); + refs = g_slist_next (refs); + g_assert_cmpstr ((char*)refs->data,==, + "4399DD94.5070309@euler.org"); + refs = g_slist_next (refs); + g_assert_cmpstr ((char*)refs->data,==, + "20051209233303.GA13812@gauss.org"); + refs = g_slist_next (refs); + g_assert_cmpstr ((char*)refs->data,==, + "439B41ED.2080402@euler.org"); + refs = g_slist_next (refs); + g_assert_cmpstr ((char*)refs->data,==, + "439A1E03.3090604@euler.org"); + refs = g_slist_next (refs); + g_assert_cmpstr ((char*)refs->data,==, + "20051211184308.GB13513@gauss.org"); + refs = g_slist_next (refs); + + mlist = mu_msg_get_mailing_list (msg); + g_assert_cmpstr (mlist ,==, "Example of List Id"); + + mu_msg_unref (msg); +} + + +static void +test_mu_msg_references_many (void) +{ + MuMsg *msg; + unsigned u; + const GSList *refs, *cur; + const char* expt_refs[] = { + "e9065dac-13c1-4103-9e31-6974ca232a89@t15g2000prt.googlegroups.com", + "87hbblwelr.fsf@sapphire.mobileactivedefense.com", + "pql248-4va.ln1@wilbur.25thandClement.com", + "ikns6r$li3$1@Iltempo.Update.UU.SE", + "8762s0jreh.fsf@sapphire.mobileactivedefense.com", + "ikqqp1$jv0$1@Iltempo.Update.UU.SE", + "87hbbjc5jt.fsf@sapphire.mobileactivedefense.com", + "ikr0na$lru$1@Iltempo.Update.UU.SE", + "tO8cp.1228$GE6.370@news.usenetserver.com", + "ikr6ks$nlf$1@Iltempo.Update.UU.SE", + "8ioh48-8mu.ln1@leafnode-msgid.gclare.org.uk" + }; + + msg = get_msg (MU_TESTMAILDIR2 "/bar/cur/181736.eml"); + refs = mu_msg_get_references(msg); + + g_assert_cmpuint (G_N_ELEMENTS(expt_refs), ==, + g_slist_length((GSList*)refs)); + + for (cur = refs, u = 0; cur; cur = g_slist_next(cur), ++u) { + if (g_test_verbose()) + g_print ("%u. '%s' =? '%s'\n", + u, (char*)cur->data, + expt_refs[u]); + + g_assert_cmpstr ((char*)cur->data, ==, expt_refs[u]); + } + + mu_msg_unref (msg); +} + +static void +test_mu_msg_tags (void) +{ + MuMsg *msg; + const GSList *tags; + + msg = get_msg (MU_TESTMAILDIR4 "/mail1"); + + g_assert_cmpstr (mu_msg_get_to(msg), + ==, "Julius Caesar <jc@example.com>"); + g_assert_cmpstr (mu_msg_get_subject(msg), + ==, "Fere libenter homines id quod volunt credunt"); + g_assert_cmpstr (mu_msg_get_from(msg), + ==, "John Milton <jm@example.com>"); + g_assert_cmpuint (mu_msg_get_prio(msg), /* 'low' */ + ==, MU_MSG_PRIO_HIGH); + g_assert_cmpuint (mu_msg_get_date(msg), + ==, 1217530645); + + tags = mu_msg_get_tags (msg); + g_assert_cmpstr ((char*)tags->data,==,"Paradise"); + g_assert_cmpstr ((char*)tags->next->data,==,"losT"); + g_assert_cmpstr ((char*)tags->next->next->data,==,"john"); + g_assert_cmpstr ((char*)tags->next->next->next->data,==,"milton"); + + g_assert (!tags->next->next->next->next); + + mu_msg_unref (msg); +} + + +static void +test_mu_msg_comp_unix_programmer (void) +{ + MuMsg *msg; + char *refs; + + msg = get_msg (MU_TESTMAILDIR4 "/181736.eml"); + g_assert_cmpstr (mu_msg_get_to(msg), + ==, NULL); + g_assert_cmpstr (mu_msg_get_subject(msg), + ==, "Re: Are writes \"atomic\" to readers of the file?"); + g_assert_cmpstr (mu_msg_get_from(msg), + ==, "Jimbo Foobarcuux <jimbo@slp53.sl.home>"); + g_assert_cmpstr (mu_msg_get_msgid(msg), + ==, "oktdp.42997$Te.22361@news.usenetserver.com"); + + refs = mu_str_from_list (mu_msg_get_references(msg), ','); + g_assert_cmpstr (refs, ==, + "e9065dac-13c1-4103-9e31-6974ca232a89@t15g2000prt" + ".googlegroups.com," + "87hbblwelr.fsf@sapphire.mobileactivedefense.com," + "pql248-4va.ln1@wilbur.25thandClement.com," + "ikns6r$li3$1@Iltempo.Update.UU.SE," + "8762s0jreh.fsf@sapphire.mobileactivedefense.com," + "ikqqp1$jv0$1@Iltempo.Update.UU.SE," + "87hbbjc5jt.fsf@sapphire.mobileactivedefense.com," + "ikr0na$lru$1@Iltempo.Update.UU.SE," + "tO8cp.1228$GE6.370@news.usenetserver.com," + "ikr6ks$nlf$1@Iltempo.Update.UU.SE," + "8ioh48-8mu.ln1@leafnode-msgid.gclare.org.uk"); + g_free (refs); + + //"jimbo@slp53.sl.home (Jimbo Foobarcuux)"; + g_assert_cmpuint (mu_msg_get_prio(msg), /* 'low' */ + ==, MU_MSG_PRIO_NORMAL); + g_assert_cmpuint (mu_msg_get_date(msg), + ==, 1299603860); + + mu_msg_unref (msg); +} + + + +static void +test_mu_str_prio_01 (void) +{ + g_assert_cmpstr(mu_msg_prio_name(MU_MSG_PRIO_LOW), ==, "low"); + g_assert_cmpstr(mu_msg_prio_name(MU_MSG_PRIO_NORMAL), ==, "normal"); + g_assert_cmpstr(mu_msg_prio_name(MU_MSG_PRIO_HIGH), ==, "high"); +} + + +static gboolean +ignore_error (const char* log_domain, GLogLevelFlags log_level, + const gchar* msg, gpointer user_data) +{ + return FALSE; /* don't abort */ +} + + +static void +test_mu_str_prio_02 (void) +{ + /* this must fail */ + g_test_log_set_fatal_handler ((GTestLogFatalFunc)ignore_error, NULL); + g_assert_cmpstr (mu_msg_prio_name(666), ==, NULL); +} + + + +static void +test_mu_str_display_contact (void) +{ + int i; + struct { + const char* word; + const char* disp; + } words [] = { + { "\"Foo Bar\" <aap@noot.mies>", "Foo Bar"}, + { "Foo Bar <aap@noot.mies>", "Foo Bar" }, + { "<aap@noot.mies>", "aap@noot.mies" }, + { "foo@bar.nl", "foo@bar.nl" } + }; + + for (i = 0; i != G_N_ELEMENTS(words); ++i) + g_assert_cmpstr (mu_str_display_contact_s (words[i].word), ==, + words[i].disp); +} + + +int +main (int argc, char *argv[]) +{ + int rv; + + g_test_init (&argc, &argv, NULL); + + /* mu_msg_str_date */ + g_test_add_func ("/mu-msg/mu-msg-01", + test_mu_msg_01); + g_test_add_func ("/mu-msg/mu-msg-02", + test_mu_msg_02); + g_test_add_func ("/mu-msg/mu-msg-03", + test_mu_msg_03); + g_test_add_func ("/mu-msg/mu-msg-04", + test_mu_msg_04); + g_test_add_func ("/mu-msg/mu-msg-multimime", + test_mu_msg_multimime); + + g_test_add_func ("/mu-msg/mu-msg-flags", + test_mu_msg_flags); + + g_test_add_func ("/mu-msg/mu-msg-tags", + test_mu_msg_tags); + g_test_add_func ("/mu-msg/mu-msg-references", + test_mu_msg_references); + g_test_add_func ("/mu-msg/mu-msg-references_dups", + test_mu_msg_references_dups); + g_test_add_func ("/mu-msg/mu-msg-references_many", + test_mu_msg_references_many); + + g_test_add_func ("/mu-msg/mu-msg-umlaut", + test_mu_msg_umlaut); + g_test_add_func ("/mu-msg/mu-msg-comp-unix-programmer", + test_mu_msg_comp_unix_programmer); + + /* mu_str_prio */ + g_test_add_func ("/mu-str/mu-str-prio-01", + test_mu_str_prio_01); + g_test_add_func ("/mu-str/mu-str-prio-02", + test_mu_str_prio_02); + + + g_test_add_func ("/mu-str/mu-str-display_contact", + test_mu_str_display_contact); + + + g_log_set_handler (NULL, + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| + G_LOG_FLAG_RECURSION, + (GLogFunc)black_hole, NULL); + + rv = g_test_run (); + + return rv; +} diff --git a/lib/test-mu-store.c b/lib/test-mu-store.c new file mode 100644 index 0000000..3276d57 --- /dev/null +++ b/lib/test-mu-store.c @@ -0,0 +1,206 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include <glib.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> + +#include <locale.h> + +#include "test-mu-common.h" +#include "mu-store.hh" + +static void +test_mu_store_new_destroy (void) +{ + MuStore *store; + gchar* tmpdir; + GError *err; + + tmpdir = test_mu_common_get_random_tmpdir(); + g_assert (tmpdir); + + err = NULL; + store = mu_store_new_create (tmpdir, "/tmp", NULL, &err); + g_assert_no_error (err); + g_assert (store); + + g_assert_cmpuint (0,==,mu_store_count (store, NULL)); + + mu_store_flush (store); + mu_store_unref (store); + + g_free (tmpdir); +} + + +static void +test_mu_store_version (void) +{ + MuStore *store; + gchar* tmpdir; + GError *err; + + tmpdir = test_mu_common_get_random_tmpdir(); + g_assert (tmpdir); + + err = NULL; + store = mu_store_new_create (tmpdir, "/tmp", NULL, &err); + g_assert (store); + mu_store_unref (store); + store = mu_store_new_readable (tmpdir, &err); + g_assert (store); + + g_assert (err == NULL); + + g_assert_cmpuint (0,==,mu_store_count (store, NULL)); + g_assert_cmpstr (MU_STORE_SCHEMA_VERSION,==, + mu_store_schema_version(store)); + + mu_store_unref (store); + g_free (tmpdir); +} + + +G_GNUC_UNUSED static void +test_mu_store_store_msg_and_count (void) +{ + MuMsg *msg; + MuStore *store; + gchar* tmpdir; + + tmpdir = test_mu_common_get_random_tmpdir(); + g_assert (tmpdir); + + store = mu_store_new_create (tmpdir, MU_TESTMAILDIR, NULL, NULL); + g_assert (store); + g_free (tmpdir); + + g_assert_cmpuint (0,==,mu_store_count (store, NULL)); + + /* add one */ + /* XXX this passes, but not make-dist; investigate */ + msg = mu_msg_new_from_file ( + MU_TESTMAILDIR "/cur/1283599333.1840_11.cthulhu!2,", + NULL, NULL); + g_assert (msg); + g_assert_cmpuint (mu_store_add_msg (store, msg, NULL), + !=, MU_STORE_INVALID_DOCID); + g_assert_cmpuint (1,==,mu_store_count (store, NULL)); + g_assert_cmpuint (TRUE,==,mu_store_contains_message + (store, + MU_TESTMAILDIR "/cur/1283599333.1840_11.cthulhu!2,")); + mu_msg_unref (msg); + + /* add another one */ + msg = mu_msg_new_from_file (MU_TESTMAILDIR2 + "/bar/cur/mail3", NULL, NULL); + g_assert (msg); + g_assert_cmpuint (mu_store_add_msg (store, msg, NULL), + !=, MU_STORE_INVALID_DOCID); + g_assert_cmpuint (2,==,mu_store_count (store, NULL)); + g_assert_cmpuint (TRUE,==, + mu_store_contains_message (store, MU_TESTMAILDIR2 + "/bar/cur/mail3")); + mu_msg_unref (msg); + + /* try to add the first one again. count should be 2 still */ + msg = mu_msg_new_from_file + (MU_TESTMAILDIR "/cur/1283599333.1840_11.cthulhu!2,", + NULL, NULL); + g_assert (msg); + g_assert_cmpuint (mu_store_add_msg (store, msg, NULL), + !=, MU_STORE_INVALID_DOCID); + g_assert_cmpuint (2,==,mu_store_count (store, NULL)); + + mu_msg_unref (msg); + mu_store_unref (store); +} + + +G_GNUC_UNUSED static void +test_mu_store_store_msg_remove_and_count (void) +{ + MuMsg *msg; + MuStore *store; + gchar* tmpdir; + GError *err; + + tmpdir = test_mu_common_get_random_tmpdir(); + g_assert (tmpdir); + + store = mu_store_new_create (tmpdir, MU_TESTMAILDIR, NULL, NULL); + g_assert (store); + + g_assert_cmpuint (0,==,mu_store_count (store, NULL)); + + /* add one */ + err = NULL; + msg = mu_msg_new_from_file ( + MU_TESTMAILDIR "/cur/1283599333.1840_11.cthulhu!2,", + NULL, &err); + g_assert (msg); + g_assert_cmpuint (mu_store_add_msg (store, msg, NULL), + !=, MU_STORE_INVALID_DOCID); + g_assert_cmpuint (1,==,mu_store_count (store, NULL)); + mu_msg_unref (msg); + + /* remove one */ + mu_store_remove_path (store, + MU_TESTMAILDIR "/cur/1283599333.1840_11.cthulhu!2,"); + g_assert_cmpuint (0,==,mu_store_count (store, NULL)); + g_assert_cmpuint (FALSE,==,mu_store_contains_message + (store, + MU_TESTMAILDIR "/cur/1283599333.1840_11.cthulhu!2,")); + g_free (tmpdir); + mu_store_unref (store); +} + + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + /* mu_runtime_init/uninit */ + g_test_add_func ("/mu-store/mu-store-new-destroy", + test_mu_store_new_destroy); + g_test_add_func ("/mu-store/mu-store-version", + test_mu_store_version); +#if 0 + /* XXX this passes, but not make-dist; investigate */ + g_test_add_func ("/mu-store/mu-store-store-and-count", + test_mu_store_store_msg_and_count); + g_test_add_func ("/mu-store/mu-store-store-remove-and-count", + test_mu_store_store_msg_remove_and_count); +#endif + if (!g_test_verbose()) + g_log_set_handler (NULL, + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION, + (GLogFunc)black_hole, NULL); + + return g_test_run (); +} diff --git a/lib/testdir/cur/1220863042.12663_1.mindcrime!2,S b/lib/testdir/cur/1220863042.12663_1.mindcrime!2,S new file mode 100644 index 0000000..ab1500f --- /dev/null +++ b/lib/testdir/cur/1220863042.12663_1.mindcrime!2,S @@ -0,0 +1,146 @@ +Return-Path: <gcc-help-return-33661-xxxx.klub=gmail.com@gcc.gnu.org> +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime +X-Spam-Level: +X-Spam-Status: No, score=-4.9 required=3.0 tests=BAYES_00,DATE_IN_PAST_96_XX, + RCVD_IN_DNSWL_MED autolearn=ham version=3.2.5 +X-Original-To: xxxx@localhost +Delivered-To: xxxx@localhost +Received: from mindcrime (localhost [127.0.0.1]) + by mail.xxxxsoftware.nl (Postfix) with ESMTP id 5123469CB3 + for <xxxx@localhost>; Thu, 7 Aug 2008 08:10:19 +0300 (EEST) +Delivered-To: xxxx.klub@gmail.com +Received: from gmail-imap.l.google.com [66.249.91.109] + by mindcrime with IMAP (fetchmail-6.3.8) + for <xxxx@localhost> (single-drop); Thu, 07 Aug 2008 08:10:19 +0300 (EEST) +Received: by 10.142.237.21 with SMTP id k21cs39272wfh; Wed, 6 Aug 2008 + 20:15:17 -0700 (PDT) +Received: by 10.65.133.8 with SMTP id k8mr2071878qbn.7.1218078916289; Wed, 06 + Aug 2008 20:15:16 -0700 (PDT) +Received: from sourceware.org (sourceware.org [209.132.176.174]) by + mx.google.com with SMTP id 28si7904461qbw.0.2008.08.06.20.15.15; Wed, 06 Aug + 2008 20:15:16 -0700 (PDT) +Received-SPF: neutral (google.com: 209.132.176.174 is neither permitted nor + denied by domain of gcc-help-return-33661-xxxx.klub=gmail.com@gcc.gnu.org) + client-ip=209.132.176.174; +Authentication-Results: mx.google.com; spf=neutral (google.com: + 209.132.176.174 is neither permitted nor denied by domain of + gcc-help-return-33661-xxxx.klub=gmail.com@gcc.gnu.org) + smtp.mail=gcc-help-return-33661-xxxx.klub=gmail.com@gcc.gnu.org +Received: (qmail 13493 invoked by alias); 7 Aug 2008 03:15:13 -0000 +Received: (qmail 13485 invoked by uid 22791); 7 Aug 2008 03:15:12 -0000 +Received: from mailgw1a.lmco.com (HELO mailgw1a.lmco.com) (192.31.106.7) + by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 07 Aug 2008 03:14:27 +0000 +Received: from emss07g01.ems.lmco.com (relay5.ems.lmco.com [166.29.2.16])by + mailgw1a.lmco.com (LM-6) with ESMTP id m773EPZH014730for + <gcc-help@gcc.gnu.org>; Wed, 6 Aug 2008 21:14:25 -0600 (MDT) +Received: from CONVERSION2-DAEMON.lmco.com by lmco.com (PMDF V6.3-x14 #31428) + id <0K5700601NO18J@lmco.com> for gcc-help@gcc.gnu.org; Wed, 06 Aug 2008 + 21:14:25 -0600 (MDT) +Received: from EMSS04I00.us.lmco.com ([166.17.13.135]) by lmco.com (PMDF + V6.3-x14 #31428) with ESMTP id <0K5700H5MNNWGX@lmco.com> for + gcc-help@gcc.gnu.org; Wed, 06 Aug 2008 21:14:20 -0600 (MDT) +Received: from EMSS35M06.us.lmco.com ([158.187.107.143]) by + EMSS04I00.us.lmco.com with Microsoft SMTPSVC(5.0.2195.6713); Wed, 06 Aug + 2008 23:14:20 -0400 +Date: Thu, 31 Jul 2008 14:57:25 -0400 +From: "Mickey Mouse" <anon@example.com> +Subject: gcc include search order +To: "Donald Duck" <gcc-help@gcc.gnu.org> +Message-id: <3BE9E6535E3029448670913581E7A1A20D852173@emss35m06.us.lmco.com> +MIME-version: 1.0 +Content-type: text/plain; charset=us-ascii +Content-transfer-encoding: 7BIT +Content-class: urn:content-classes:message +Mailing-List: contact gcc-help-help@gcc.gnu.org; run by ezmlm +Precedence: klub +List-Id: <gcc-help.gcc.gnu.org> +List-Unsubscribe: <mailto:gcc-help-unsubscribe-xxxx.klub=gmail.com@gcc.gnu.org> +List-Archive: <http://gcc.gnu.org/ml/gcc-help/> +List-Post: <mailto:gcc-help@gcc.gnu.org> +List-Help: <mailto:gcc-help-help@gcc.gnu.org> +Sender: gcc-help-owner@gcc.gnu.org +Delivered-To: mailing list gcc-help@gcc.gnu.org +Content-Length: 3024 + + +Hi. +In my unit testing I need to change some header files (target is +vxWorks, which supports some things that the sun does not). +So, what I do is fetch the development tree, and then in a new unit test +directory I attempt to compile the unit under test. Since this is NOT +vxworks, I use sed to change some of the .h files and put them in a +./changed directory. + +When I try to compile the file, it is still using the .h file from the +original location, even though I have listed the include path for +./changed before the include path for the development tree. + +Here is a partial output from gcc using the -v option + +GNU CPP version 3.1 (cpplib) (sparc ELF) +GNU C++ version 3.1 (sparc-sun-solaris2.8) + compiled by GNU C version 3.1. +ignoring nonexistent directory "NONE/include" +#include "..." search starts here: +#include <...> search starts here: + . + changed + /export/home4/xxx/yyyy/builds/int_rel5_latest/src/mp/interface + /export/home4/xxx/yyyy/builds/int_rel5_latest/src/ap/app + /export/home4/xxx/yyyy/builds/int_rel5_latest/src/shared/common + /export/home4/xxx/yyyy/builds/int_rel5_latest/src/shared/interface + /usr/local/include/g++-v3 + /usr/local/include/g++-v3/sparc-sun-solaris2.8 + /usr/local/include/g++-v3/backward + /usr/local/include + /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/3.1/include + /usr/local/sparc-sun-solaris2.8/include + /usr/include +End of search list. + +I know the changed file is correct and that the include is not working +as expected, because when I copy the file from ./changed, back into the +development tree, the compilation works as expected. + +One more bit of information. The source that I cam compiling is in +/export/home4/xxx/yyyy/builds/int_rel5_latest/src/ap/app +And it is including files from +/export/home4/xxx/yyyy/builds/int_rel5_latest/src/shared/common +These include files should be including the files from ./changed (when +they exist) but they are ignoring the .h files in the ./changed +directory and are instead using other, unchanged files in the +/export/home4/xxx/yyyy/builds/int_rel5_latest/src/shared/common +directory. + +The gcc command line is something like + + TEST_DIR="." + + CHANGED_DIR_NAME=changed + CHANGED_FILES_DIR=${TEST_DIR}/${CHANGED_DIR_NAME} + + CICU_HEADER_FILES="-I ${AP_INTERFACE_FILES} -I ${AP_APP_FILES} -I +${SHARED_COMMON_FILES} -I ${SHARED_INTERFACE_FILES}" + + HEADERS="-I ./ -I ${CHANGED_FILES_DIR} ${CICU_HEADER_FILES}" + DEFINES="-DSUNRUN -DA10_DEBUG -DJOETEST" + + CFLAGS="-v -c -g -O1 -pipe -Wformat -Wunused -Wuninitialized -Wshadow +-Wmissing-prototypes -Wmissing-declarations" + + printf "Compiling the UUT File\n" + gcc -fprofile-arcs -ftest-coverage ${CFLAGS} ${HEADERS} ${DEFINES} +${AP_APP_FILES}/unitUnderTest.cpp + + +I hope this explanation is clear. If anyone knows how to fix the command +line so that it gets the .h files in the "changed" directory are used +instead of files in the other include directories. + +Thanks +Joe + +---------------------------------------------------- +Time Flies like an Arrow. Fruit Flies like a Banana + + diff --git a/lib/testdir/cur/1220863060.12663_3.mindcrime!2,S b/lib/testdir/cur/1220863060.12663_3.mindcrime!2,S new file mode 100644 index 0000000..d0ff0d7 --- /dev/null +++ b/lib/testdir/cur/1220863060.12663_3.mindcrime!2,S @@ -0,0 +1,230 @@ +Return-Path: <sqlite-dev-bounces@sqlite.org> +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime +X-Spam-Level: +X-Spam-Status: No, score=-2.6 required=3.0 tests=BAYES_00,HTML_MESSAGE + autolearn=ham version=3.2.5 +X-Original-To: xxxx@localhost +Delivered-To: xxxx@localhost +Received: from mindcrime (localhost [127.0.0.1]) + by mail.xxxxsoftware.nl (Postfix) with ESMTP id D724F6963B + for <xxxx@localhost>; Mon, 4 Aug 2008 21:49:27 +0300 (EEST) +Delivered-To: xxxx.klub@gmail.com +Received: from gmail-imap.l.google.com [72.14.221.111] + by mindcrime with IMAP (fetchmail-6.3.8) + for <xxxx@localhost> (single-drop); Mon, 04 Aug 2008 21:49:27 +0300 (EEST) +Received: by 10.142.51.12 with SMTP id y12cs86537wfy; Mon, 4 Aug 2008 00:38:51 + -0700 (PDT) +Received: by 10.151.113.5 with SMTP id q5mr272266ybm.37.1217835529913; Mon, 04 + Aug 2008 00:38:49 -0700 (PDT) +Received: from sqlite.org (sqlite.org [67.18.92.124]) by mx.google.com with + ESMTP id 5si5754915ywd.8.2008.08.04.00.38.30; Mon, 04 Aug 2008 00:38:50 -0700 + (PDT) +Received-SPF: pass (google.com: best guess record for domain of + sqlite-dev-bounces@sqlite.org designates 67.18.92.124 as permitted sender) + client-ip=67.18.92.124; +Authentication-Results: mx.google.com; spf=pass (google.com: best guess record + for domain of sqlite-dev-bounces@sqlite.org designates 67.18.92.124 as + permitted sender) smtp.mail=sqlite-dev-bounces@sqlite.org +Received: from sqlite.org (localhost [127.0.0.1]) by sqlite.org (Postfix) with + ESMTP id 765A511C46; Mon, 4 Aug 2008 03:38:27 -0400 (EDT) +X-Original-To: sqlite-dev@sqlite.org +Delivered-To: sqlite-dev@sqlite.org +Received: from ik-out-1112.google.com (ik-out-1112.google.com [66.249.90.176]) + by sqlite.org (Postfix) with ESMTP id 4C59511C41 for <sqlite-dev@sqlite.org>; + Mon, 4 Aug 2008 03:38:23 -0400 (EDT) +Received: by ik-out-1112.google.com with SMTP id b32so2163423ika.0 for + <sqlite-dev@sqlite.org>; Mon, 04 Aug 2008 00:38:23 -0700 (PDT) +Received: by 10.210.54.19 with SMTP id c19mr14589042eba.107.1217835502549; + Mon, 04 Aug 2008 00:38:22 -0700 (PDT) +Received: by 10.210.115.10 with HTTP; Mon, 4 Aug 2008 00:38:22 -0700 (PDT) +Message-ID: <477821040808040038s381bf382p7411451e3c1a2e4e@mail.gmail.com> +Date: Mon, 4 Aug 2008 10:38:22 +0300 +From: anon@example.com +To: sqlite-dev@sqlite.org +In-Reply-To: <73d4fc50808030747g303a170ieac567723c2d4f24@mail.gmail.com> +MIME-Version: 1.0 +References: <477821040808030533y41f1501dq32447b568b6e6ca5@mail.gmail.com> + <73d4fc50808030747g303a170ieac567723c2d4f24@mail.gmail.com> +Subject: Re: [sqlite-dev] SQLite exception A&B +X-BeenThere: sqlite-dev@sqlite.org +X-Mailman-Version: 2.1.9 +Priority: normal +Reply-To: sqlite-dev@sqlite.org +List-Id: <sqlite-dev.sqlite.org> +List-Unsubscribe: <http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev>, + <mailto:sqlite-dev-request@sqlite.org?subject=unsubscribe> +List-Archive: <http://sqlite.org:8080/cgi-bin/mailman/private/sqlite-dev> +List-Post: <mailto:sqlite-dev@sqlite.org> +List-Help: <mailto:sqlite-dev-request@sqlite.org?subject=help> +List-Subscribe: <http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev>, + <mailto:sqlite-dev-request@sqlite.org?subject=subscribe> +Content-Type: multipart/mixed; boundary="===============2123623832==" +Mime-version: 1.0 +Sender: sqlite-dev-bounces@sqlite.org +Errors-To: sqlite-dev-bounces@sqlite.org +Content-Length: 8475 + +--===============2123623832== +Content-Type: multipart/alternative; + boundary="----=_Part_29556_25702991.1217835502493" + +------=_Part_29556_25702991.1217835502493 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 7bit +Content-Disposition: inline + +Hi Grant, + +Thanks for your reply. +I am using a different session for each thread, whenever a thread wishes to +access the database it gets a session from the session pool and works with +that session until its work is done. + +Most of the actions the threads are doing on the database are quite +complicated and are required to be fully committed or completely ignored, so +yes, I am (most of the time) explicitly beginning and committing my +transactions. + +Regarding the SQLiteStatementImpl, I believe the Poco manual explains that +sessions and statements for that matter cannot be shared between threads, +therefore if you are using a session via one thread only it should work +fine. + +My first impression was that the problem was in the Poco infrastructure (I +have found several Poco related bugs in the past), but the problem ALWAYS +occurs when I perform the "BEGIN IMMEDIATE" action, if it were a Poco +related bug, I would expect to see it here and there without any relation to +this specific statement, but that is not the case. + +None the less, I will also post my question on the Poco forums. + +Nadav. + +On Sun, Aug 3, 2008 at 5:47 PM, Grant Gatchel <grant.gatchel@gmail.com>wrote: + +> Are you using the same Poco::Session for every thread or does each call +> create a new session/handle to the database? +> +> Are you explicitly BEGINning and COMMITting your transactions? +> +> In looking at the 1.3.2 branch of Poco::Data::SQLite, there appears to be a +> race condition in the SQLiteStatementImpl::next() method in which the member +> _nextResponse is being accessed before the SQLiteStatementImpl::hasNext() +> method has a chance to interpret that value and throw an exception. +> +> This question might be more suitable in the Poco forums or mailinglist. +> +> - Grant +> +> On Sun, Aug 3, 2008 at 8:33 AM, nadav g <nadav.gr@gmail.com> wrote: +> +>> Hi All, +>> +>> I have been using SQLite with Poco (www.appinf.com) as my infrastructure. +>> The program is running several threads that access this database very +>> often and are synchronized by SQLite itself. +>> Everything seems to work just fine most of time (usually days - weeks) but +>> I do get an occasional exception: +>> +>> Exception: SQL error or missing database: Iterator Error: trying to check +>> if there is a next value +>> +>> The backtrace leads to this statement: +>> *"BEGIN IMMEDIATE"* +>> +>> This specific code runs numerous times before an exception occurs (if +>> occurs at all) and I cannot think of any reason for it to fail later rather +>> than sooner. +>> It is pretty obvious that this situation occurs due to some rare thread +>> state, but I could not find any information that gives me any hint as to +>> what this state might be. +>> +>> So what I am asking is: +>> 1) Does anyone know why this sort of exception occurs? +>> 2) Can anyone think of a reason for such an exception to occur in the +>> situation I have described? +>> +>> Thanks in advance, +>> Nadav. +>> +>> +>> _______________________________________________ +>> sqlite-dev mailing list +>> sqlite-dev@sqlite.org +>> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev +>> +>> +> +> _______________________________________________ +> sqlite-dev mailing list +> sqlite-dev@sqlite.org +> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev +> +> + +------=_Part_29556_25702991.1217835502493 +Content-Type: text/html; charset=ISO-8859-1 +Content-Transfer-Encoding: 7bit +Content-Disposition: inline + +<div dir="ltr">Hi Grant,<br><br>Thanks for your reply.<br>I am using a different session for each thread, whenever a thread wishes to access the database it gets a session from the session pool and works with that session until its work is done.<br> +<br>Most of the actions the threads are doing on the database are quite complicated and are required to be fully committed or completely ignored, so yes, I am (most of the time) explicitly beginning and committing my transactions.<br> +<br>Regarding the SQLiteStatementImpl, I believe the Poco manual explains that sessions and statements for that matter cannot be shared between threads, therefore if you are using a session via one thread only it should work fine.<br> +<br>My first impression was that the problem was in the Poco infrastructure (I have found several Poco related bugs in the past), but the problem ALWAYS occurs when I perform the "BEGIN IMMEDIATE" action, if it were a Poco related bug, I would expect to see it here and there without any relation to this specific statement, but that is not the case.<br> +<br>None the less, I will also post my question on the Poco forums.<br><br>Nadav.<br><br><div class="gmail_quote">On Sun, Aug 3, 2008 at 5:47 PM, Grant Gatchel <span dir="ltr"><<a href="mailto:grant.gatchel@gmail.com">grant.gatchel@gmail.com</a>></span> wrote:<br> +<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div dir="ltr">Are you using the same Poco::Session for every thread or does each call create a new session/handle to the database?<br> +<br>Are you explicitly BEGINning and COMMITting your transactions?<br><br>In looking at the 1.3.2 branch of Poco::Data::SQLite, there appears to be a race condition in the SQLiteStatementImpl::next() method in which the member _nextResponse is being accessed before the SQLiteStatementImpl::hasNext() method has a chance to interpret that value and throw an exception.<br> + +<br>This question might be more suitable in the Poco forums or mailinglist.<br><br>- Grant<br> +<br><div class="gmail_quote"><div><div></div><div class="Wj3C7c"> +On Sun, Aug 3, 2008 at 8:33 AM, nadav g <span dir="ltr"><<a href="http://nadav.gr" target="_blank">nadav.gr</a>@<a href="http://gmail.com" target="_blank">gmail.com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> +<div><div></div><div class="Wj3C7c"> + + +<div dir="ltr">Hi All,<br><br>I have been using SQLite with Poco (<a href="http://www.appinf.com" target="_blank">www.appinf.com</a>) as my infrastructure.<br>The program is running several threads that access this database very often and are synchronized by SQLite itself.<br> + + + + +Everything seems to work just fine most of time (usually days - weeks) but I do get an occasional exception:<br><br>Exception: SQL error or missing database: Iterator Error: trying to check if there is a next value<br><br> + + + + +The backtrace leads to this statement:<br><b>"BEGIN IMMEDIATE"</b><br><br>This specific code runs numerous times before an exception occurs (if occurs at all) and I cannot think of any reason for it to fail later rather than sooner.<br> + + + + +It is pretty obvious that this situation occurs due to some rare thread state, but I could not find any information that gives me any hint as to what this state might be.<br><br>So what I am asking is:<br>1) Does anyone know why this sort of exception occurs?<br> + + + + +2) Can anyone think of a reason for such an exception to occur in the situation I have described?<br><br>Thanks in advance,<br>Nadav.<br><br></div> +<br></div></div>_______________________________________________<br> +sqlite-dev mailing list<br> +<a href="mailto:sqlite-dev@sqlite.org" target="_blank">sqlite-dev@sqlite.org</a><br> +<a href="http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev" target="_blank">http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev</a><br> +<br></blockquote></div><br></div> +<br>_______________________________________________<br> +sqlite-dev mailing list<br> +<a href="mailto:sqlite-dev@sqlite.org">sqlite-dev@sqlite.org</a><br> +<a href="http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev" target="_blank">http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev</a><br> +<br></blockquote></div><br></div> + +------=_Part_29556_25702991.1217835502493-- + +--===============2123623832== +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Content-Disposition: inline + +_______________________________________________ +sqlite-dev mailing list +sqlite-dev@sqlite.org +http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev + +--===============2123623832==-- + diff --git a/lib/testdir/cur/1220863087.12663_15.mindcrime!2,PS b/lib/testdir/cur/1220863087.12663_15.mindcrime!2,PS new file mode 100644 index 0000000..d6487c0 --- /dev/null +++ b/lib/testdir/cur/1220863087.12663_15.mindcrime!2,PS @@ -0,0 +1,136 @@ +Return-Path: <help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org> +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime +X-Spam-Level: +X-Spam-Status: No, score=-3.6 required=3.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW, + SPF_PASS,WHOIS_NETSOLPR autolearn=ham version=3.2.5 +X-Original-To: xxxx@localhost +Delivered-To: xxxx@localhost +Received: from mindcrime (localhost [127.0.0.1]) + by mail.xxxxsoftware.nl (Postfix) with ESMTP id 1A6CD69CB6 + for <xxxx@localhost>; Tue, 12 Aug 2008 21:42:38 +0300 (EEST) +Delivered-To: xxxx.klub@gmail.com +Received: from gmail-imap.l.google.com [72.14.221.109] + by mindcrime with IMAP (fetchmail-6.3.8) + for <xxxx@localhost> (single-drop); Tue, 12 Aug 2008 21:42:38 +0300 (EEST) +Received: by 10.142.237.21 with SMTP id k21cs123119wfh; Sun, 10 Aug 2008 + 22:06:31 -0700 (PDT) +Received: by 10.100.166.10 with SMTP id o10mr9327844ane.0.1218431190107; Sun, + 10 Aug 2008 22:06:30 -0700 (PDT) +Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) by mx.google.com + with ESMTP id c29si10110392anc.13.2008.08.10.22.06.29; Sun, 10 Aug 2008 + 22:06:30 -0700 (PDT) +Received-SPF: pass (google.com: domain of + help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 + as permitted sender) client-ip=199.232.76.165; +Authentication-Results: mx.google.com; spf=pass (google.com: domain of + help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 + as permitted sender) + smtp.mail=help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Received: from localhost ([127.0.0.1]:45637 helo=lists.gnu.org) by + lists.gnu.org with esmtp (Exim 4.43) id 1KSPbx-0006dj-96 for + xxxx.klub@gmail.com; Mon, 11 Aug 2008 01:06:29 -0400 +Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id + 1KSPbE-0006cQ-Nd for help-gnu-emacs@gnu.org; Mon, 11 Aug 2008 01:05:44 -0400 +Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id + 1KSPbD-0006bs-Px for help-gnu-emacs@gnu.org; Mon, 11 Aug 2008 01:05:44 -0400 +Received: from [199.232.76.173] (port=37426 helo=monty-python.gnu.org) by + lists.gnu.org with esmtp (Exim 4.43) id 1KSPbD-0006bk-HT for + help-gnu-emacs@gnu.org; Mon, 11 Aug 2008 01:05:43 -0400 +Received: from main.gmane.org ([80.91.229.2]:46446 helo=ciao.gmane.org) by + monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim + 4.60) (envelope-from <geh-help-gnu-emacs@m.gmane.org>) id 1KSPbD-0003Kl-CA + for help-gnu-emacs@gnu.org; Mon, 11 Aug 2008 01:05:43 -0400 +Received: from list by ciao.gmane.org with local (Exim 4.43) id + 1KSPb9-00080r-CX for help-gnu-emacs@gnu.org; Mon, 11 Aug 2008 05:05:39 +0000 +Received: from bas2-toronto63-1088792724.dsl.bell.ca ([64.229.168.148]) by + main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for + <help-gnu-emacs@gnu.org>; Mon, 11 Aug 2008 05:05:39 +0000 +Received: from cpchan by bas2-toronto63-1088792724.dsl.bell.ca with local + (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for <help-gnu-emacs@gnu.org>; Mon, + 11 Aug 2008 05:05:39 +0000 +X-Injected-Via-Gmane: http://gmane.org/ +To: help-gnu-emacs@gnu.org +From: anon@example.com +Date: Mon, 11 Aug 2008 01:03:22 -0400 +Organization: Linux Private Site +Message-ID: <87bq00nnxh.fsf@MagnumOpus.Mercurius> +References: <877iav5s49.fsf@163.com> <86hc9yc5sj.fsf@timbral.net> + <877iat7udd.fsf@163.com> <87fxphcsxi.fsf@lion.rapttech.com.au> + <8504ddd4-5e3b-4ed5-bf77-aa9cce81b59a@1g2000pre.googlegroups.com> + <87k5es59we.fsf@lion.rapttech.com.au> + <63c824e3-62b1-4a93-8fa8-2813e1f9397f@v13g2000pro.googlegroups.com> + <874p5vsgg8.fsf@nonospaz.fatphil.org> + <8250972e-1886-4021-80bc-376e34881c80@v39g2000pro.googlegroups.com> + <87zlnnqvvs.fsf@nonospaz.fatphil.org> + <57add0e0-b39d-4c71-8d2c-d3b9ddfaa1a9@1g2000pre.googlegroups.com> + <87sktfnz5p.fsf@atthis.clsnet.nl> + <562e1111-d9e7-4b6a-b661-3f9af13fea17@b30g2000prf.googlegroups.com> + <87d4khoq97.fsf@atthis.clsnet.nl> + <0fe404c5-cab8-4692-8a27-532e737a7813@i24g2000prf.googlegroups.com> +Mime-Version: 1.0 +Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha1; + protocol="application/pgp-signature" +X-Complaints-To: usenet@ger.gmane.org +X-Gmane-NNTP-Posting-Host: bas2-toronto63-1088792724.dsl.bell.ca +X-Face: G; + Z,`sm>)4t4LB/GUrgH$W`!AmfHMj,LG)Z}X0ax@s9:0>0)B&@vcm{v-le)wng)?|o]D<V6&ay<F=H{M5?$T%p!dPdJeF,au\E@TA"v22K!Zl\\mzpU4]6$ZnAI3_L)h; + fpd}mn2py/7gv^|*85-D_f:07cT>\Z}0:6X +User-Agent: Gnus/5.110011 (No Gnus v0.11) Emacs/23.0.60 (gnu/linux) +Cancel-Lock: sha1:IKyfrl5drOw6HllHFSmWHAKEeC8= +X-detected-kernel: by monty-python.gnu.org: Linux 2.6, seldom 2.4 (older, 4) +Subject: Re: Can anybody tell me how to send HTML-format mail in gnus +X-BeenThere: help-gnu-emacs@gnu.org +X-Mailman-Version: 2.1.5 +Precedence: list +List-Id: Users list for the GNU Emacs text editor <help-gnu-emacs.gnu.org> +List-Unsubscribe: <http://lists.gnu.org/mailman/listinfo/help-gnu-emacs>, + <mailto:help-gnu-emacs-request@gnu.org?subject=unsubscribe> +List-Archive: <http://lists.gnu.org/pipermail/help-gnu-emacs> +List-Post: <mailto:help-gnu-emacs@gnu.org> +List-Help: <mailto:help-gnu-emacs-request@gnu.org?subject=help> +List-Subscribe: <http://lists.gnu.org/mailman/listinfo/help-gnu-emacs>, + <mailto:help-gnu-emacs-request@gnu.org?subject=subscribe> +Sender: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Errors-To: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Content-Length: 1229 +Lines: 36 + +--=-=-= +Content-Type: text/plain + +Xah <xahlee@gmail.com> writes: + +> So, i was reading about it in Wikipedia. Although i don't have a TV, +> and haven't had since 2000, but i still enjoyed the festive spirits +> anyhow. After all, i'm Chinese by blood. So, in my wandering, i ran +> into this welcome song on youtube: +> +> http://www.youtube.com/watch?v=1HEndNYVhZo + +What is your point? Your email is in plain text and I can click on the +link just fine- it is not exactly rocket science to implement parsing of +URL's to workable links in an Email program (a lot of programs does +that, including Gnus). Images can be included inline if you want. Also +mail markups such as *this*, **this** and _this_ have been around since +the Usenet days and displayed appropriately by a number of mailers. Like +others have said, most html messages that I have seen either contains +useless information, or are plain spam and can introduce a host of +security problems in some mailers. + +Charles + + +--=-=-= +Content-Type: application/pgp-signature + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +iD8DBQFIn8gm3epPyyKbwPYRApbvAKDRirXwzMzI+NHV77+QcP3EgTPaCgCfb/6m +GtNVKdYAeftaYm1nwRVoCDA= +=ULo3 +-----END PGP SIGNATURE----- +--=-=-=-- + + + diff --git a/lib/testdir/cur/1220863087.12663_19.mindcrime!2,S b/lib/testdir/cur/1220863087.12663_19.mindcrime!2,S new file mode 100644 index 0000000..78efa2a --- /dev/null +++ b/lib/testdir/cur/1220863087.12663_19.mindcrime!2,S @@ -0,0 +1,77 @@ +Return-Path: <help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org> +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime +X-Spam-Level: +X-Spam-Status: No, score=-2.6 required=3.0 tests=BAYES_00 autolearn=ham + version=3.2.5 +X-Original-To: xxxx@localhost +Delivered-To: xxxx@localhost +Received: from mindcrime (localhost [127.0.0.1]) + by mail.xxxxsoftware.nl (Postfix) with ESMTP id C4D6569CB3 + for <xxxx@localhost>; Thu, 7 Aug 2008 08:10:08 +0300 (EEST) +Delivered-To: xxxx.klub@gmail.com +Received: from gmail-imap.l.google.com [66.249.91.109] + by mindcrime with IMAP (fetchmail-6.3.8) + for <xxxx@localhost> (single-drop); Thu, 07 Aug 2008 08:10:08 +0300 (EEST) +Received: by 10.142.237.21 with SMTP id k21cs34794wfh; Wed, 6 Aug 2008 + 13:40:29 -0700 (PDT) +Received: by 10.100.33.13 with SMTP id g13mr1093301ang.79.1218055228418; Wed, + 06 Aug 2008 13:40:28 -0700 (PDT) +Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) by mx.google.com + with ESMTP id d19si15908789and.17.2008.08.06.13.40.27; Wed, 06 Aug 2008 + 13:40:28 -0700 (PDT) +Received-SPF: pass (google.com: domain of + help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 + as permitted sender) client-ip=199.232.76.165; +Authentication-Results: mx.google.com; spf=pass (google.com: domain of + help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 + as permitted sender) + smtp.mail=help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Received: from localhost ([127.0.0.1]:56316 helo=lists.gnu.org) by + lists.gnu.org with esmtp (Exim 4.43) id 1KQpo3-0007Pc-Qk for + xxxx.klub@gmail.com; Wed, 06 Aug 2008 16:40:27 -0400 +From: anon@example.com +Newsgroups: gnu.emacs.help +Date: Wed, 6 Aug 2008 20:38:35 +0100 +Message-ID: <r6bpm5-6n6.ln1@news.ducksburg.com> +References: <55dbm5-qcl.ln1@news.ducksburg.com> + <mailman.15710.1217599959.18990.help-gnu-emacs@gnu.org> +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +X-Trace: individual.net bABVU1hcJwWAuRwe/097AAoOXnGGeYR8G1In635iFGIyfDLPUv +X-Orig-Path: news.ducksburg.com!news +Cancel-Lock: sha1:wK7dsPRpNiVxpL/SfvmNzlvUR94= + sha1:oepBoM0tJBLN52DotWmBBvW5wbg= +User-Agent: slrn/pre0.9.9-120/mm/ao (Ubuntu Hardy) +Path: news.stanford.edu!headwall.stanford.edu!newshub.sdsu.edu!feeder.erje.net!proxad.net!feeder1-2.proxad.net!feed.ac-versailles.fr!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail +Xref: news.stanford.edu gnu.emacs.help:160868 +To: help-gnu-emacs@gnu.org +Subject: Re: Learning LISP; Scheme vs elisp. +X-BeenThere: help-gnu-emacs@gnu.org +X-Mailman-Version: 2.1.5 +Precedence: list +List-Id: Users list for the GNU Emacs text editor <help-gnu-emacs.gnu.org> +List-Unsubscribe: <http://lists.gnu.org/mailman/listinfo/help-gnu-emacs>, + <mailto:help-gnu-emacs-request@gnu.org?subject=unsubscribe> +List-Archive: <http://lists.gnu.org/pipermail/help-gnu-emacs> +List-Post: <mailto:help-gnu-emacs@gnu.org> +List-Help: <mailto:help-gnu-emacs-request@gnu.org?subject=help> +List-Subscribe: <http://lists.gnu.org/mailman/listinfo/help-gnu-emacs>, + <mailto:help-gnu-emacs-request@gnu.org?subject=subscribe> +Sender: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Errors-To: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Content-Length: 417 +Lines: 11 + +On 2008-08-01, Thien-Thi Nguyen wrote: + +> warriors attack, felling foe after foe, +> few growing old til they realize: to know +> what deceit is worth deflection; +> such receipt reversed rejection! +> then their heavy arms, e'er transformed to shields: +> balanced hooked charms, ploughed deep, rich yields. + +Aha: the exercise for the reader is to place the parens correctly. +Might take me a while to solve this puzzle. + diff --git a/lib/testdir/cur/1220863087.12663_5.mindcrime!2,S b/lib/testdir/cur/1220863087.12663_5.mindcrime!2,S new file mode 100644 index 0000000..de46cc8 --- /dev/null +++ b/lib/testdir/cur/1220863087.12663_5.mindcrime!2,S @@ -0,0 +1,84 @@ +Return-Path: <sqlite-dev-bounces@sqlite.org> +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime +X-Spam-Level: +X-Spam-Status: No, score=-2.6 required=3.0 tests=BAYES_00 autolearn=ham + version=3.2.5 +X-Original-To: xxxx@localhost +Delivered-To: xxxx@localhost +Received: from mindcrime (localhost [127.0.0.1]) + by mail.xxxxsoftware.nl (Postfix) with ESMTP id 32F276963F + for <xxxx@localhost>; Mon, 4 Aug 2008 21:49:34 +0300 (EEST) +Delivered-To: xxxx.klub@gmail.com +Received: from gmail-imap.l.google.com [72.14.221.111] + by mindcrime with IMAP (fetchmail-6.3.8) + for <xxxx@localhost> (single-drop); Mon, 04 Aug 2008 21:49:34 +0300 (EEST) +Received: by 10.142.51.12 with SMTP id y12cs89397wfy; Mon, 4 Aug 2008 02:41:16 + -0700 (PDT) +Received: by 10.150.156.20 with SMTP id d20mr963580ybe.104.1217842875596; Mon, + 04 Aug 2008 02:41:15 -0700 (PDT) +Received: from sqlite.org (sqlite.org [67.18.92.124]) by mx.google.com with + ESMTP id 6si3605185ywi.1.2008.08.04.02.40.57; Mon, 04 Aug 2008 02:41:15 -0700 + (PDT) +Received-SPF: pass (google.com: best guess record for domain of + sqlite-dev-bounces@sqlite.org designates 67.18.92.124 as permitted sender) + client-ip=67.18.92.124; +Authentication-Results: mx.google.com; spf=pass (google.com: best guess record + for domain of sqlite-dev-bounces@sqlite.org designates 67.18.92.124 as + permitted sender) smtp.mail=sqlite-dev-bounces@sqlite.org +Received: from sqlite.org (localhost [127.0.0.1]) by sqlite.org (Postfix) with + ESMTP id 7147F11C45; Mon, 4 Aug 2008 05:40:55 -0400 (EDT) +X-Original-To: sqlite-dev@sqlite.org +Delivered-To: sqlite-dev@sqlite.org +Received: from relay00.pair.com (relay00.pair.com [209.68.5.9]) by sqlite.org + (Postfix) with SMTP id B5F901192C for <sqlite-dev@sqlite.org>; Mon, 4 Aug + 2008 05:40:52 -0400 (EDT) +Received: (qmail 59961 invoked from network); 4 Aug 2008 09:40:50 -0000 +Received: from unknown (HELO ?192.168.0.17?) (unknown) by unknown with SMTP; 4 + Aug 2008 09:40:50 -0000 +X-pair-Authenticated: 87.13.75.164 +Message-Id: <83B5AF40-DBFA-4578-A043-04C80276E195@sqlabs.net> +From: anon@example.com +To: sqlite-dev@sqlite.org +Mime-Version: 1.0 (Apple Message framework v926) +Date: Mon, 4 Aug 2008 11:40:49 +0200 +X-Mailer: Apple Mail (2.926) +Subject: [sqlite-dev] VM optimization inside sqlite3VdbeExec +X-BeenThere: sqlite-dev@sqlite.org +X-Mailman-Version: 2.1.9 +Precedence: list +Reply-To: sqlite-dev@sqlite.org +List-Id: <sqlite-dev.sqlite.org> +List-Unsubscribe: <http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev>, + <mailto:sqlite-dev-request@sqlite.org?subject=unsubscribe> +List-Archive: <http://sqlite.org:8080/cgi-bin/mailman/private/sqlite-dev> +List-Post: <mailto:sqlite-dev@sqlite.org> +List-Help: <mailto:sqlite-dev-request@sqlite.org?subject=help> +List-Subscribe: <http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev>, + <mailto:sqlite-dev-request@sqlite.org?subject=subscribe> +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +Sender: sqlite-dev-bounces@sqlite.org +Errors-To: sqlite-dev-bounces@sqlite.org +Content-Length: 639 + +Inside sqlite3VdbeExec there is a very big switch statement. +In order to increase performance with few modifications to the +original code, why not use this technique ? +http://docs.freebsd.org/info/gcc/gcc.info.Labels_as_Values.html + +With a properly defined "instructions" array, instead of the switch +statement you can use something like: +goto * instructions[pOp->opcode]; +--- +Marco Bambini +http://www.sqlabs.net +http://www.sqlabs.net/blog/ +http://www.sqlabs.net/realsqlserver/ + + + +_______________________________________________ +sqlite-dev mailing list +sqlite-dev@sqlite.org +http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev + diff --git a/lib/testdir/cur/1220863087.12663_7.mindcrime!2,RS b/lib/testdir/cur/1220863087.12663_7.mindcrime!2,RS new file mode 100644 index 0000000..b5c0651 --- /dev/null +++ b/lib/testdir/cur/1220863087.12663_7.mindcrime!2,RS @@ -0,0 +1,138 @@ +Return-Path: <sqlite-dev-bounces@sqlite.org> +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime +X-Spam-Level: +X-Spam-Status: No, score=-2.6 required=3.0 tests=BAYES_00 autolearn=ham + version=3.2.5 +X-Original-To: xxxx@localhost +Delivered-To: xxxx@localhost +Received: from mindcrime (localhost [127.0.0.1]) + by mail.xxxxsoftware.nl (Postfix) with ESMTP id 3EBAB6963B + for <xxxx@localhost>; Mon, 4 Aug 2008 21:49:35 +0300 (EEST) +Delivered-To: xxxx.klub@gmail.com +Received: from gmail-imap.l.google.com [72.14.221.111] + by mindcrime with IMAP (fetchmail-6.3.8) + for <xxxx@localhost> (single-drop); Mon, 04 Aug 2008 21:49:35 +0300 (EEST) +Received: by 10.142.51.12 with SMTP id y12cs89536wfy; Mon, 4 Aug 2008 02:48:56 + -0700 (PDT) +Received: by 10.150.134.21 with SMTP id h21mr7950048ybd.181.1217843335665; + Mon, 04 Aug 2008 02:48:55 -0700 (PDT) +Received: from sqlite.org (sqlite.org [67.18.92.124]) by mx.google.com with + ESMTP id 6si5897081ywi.1.2008.08.04.02.48.35; Mon, 04 Aug 2008 02:48:55 -0700 + (PDT) +Received-SPF: pass (google.com: best guess record for domain of + sqlite-dev-bounces@sqlite.org designates 67.18.92.124 as permitted sender) + client-ip=67.18.92.124; +Authentication-Results: mx.google.com; spf=pass (google.com: best guess record + for domain of sqlite-dev-bounces@sqlite.org designates 67.18.92.124 as + permitted sender) smtp.mail=sqlite-dev-bounces@sqlite.org +Received: from sqlite.org (localhost [127.0.0.1]) by sqlite.org (Postfix) with + ESMTP id ED01611C4E; Mon, 4 Aug 2008 05:48:31 -0400 (EDT) +X-Original-To: sqlite-dev@sqlite.org +Delivered-To: sqlite-dev@sqlite.org +Received: from mx0.security.ro (mx0.security.ro [80.96.72.194]) by sqlite.org + (Postfix) with ESMTP id EB3F51192C for <sqlite-dev@sqlite.org>; Mon, 4 Aug + 2008 05:48:28 -0400 (EDT) +Received: (qmail 348 invoked from network); 4 Aug 2008 12:48:03 +0300 +Received: from dev.security.ro (HELO ?192.168.1.70?) (192.168.1.70) by + mx0.security.ro with SMTP; 4 Aug 2008 12:48:03 +0300 +Message-ID: <4896D06A.8000901@security.ro> +Date: Mon, 04 Aug 2008 12:48:26 +0300 +From: anon@example.com +User-Agent: Thunderbird 2.0.0.16 (Windows/20080708) +MIME-Version: 1.0 +To: sqlite-dev@sqlite.org +References: <83B5AF40-DBFA-4578-A043-04C80276E195@sqlabs.net> +In-Reply-To: <83B5AF40-DBFA-4578-A043-04C80276E195@sqlabs.net> +Content-Type: multipart/mixed; boundary="------------000207070200050102060301" +X-BitDefender-Scanner: Clean, Agent: BitDefender qmail 2.0.0 on + mx0.security.ro +X-BitDefender-Spam: No (0) +X-BitDefender-SpamStamp: v1, whitelisted, total: 0 +Subject: Re: [sqlite-dev] VM optimization inside sqlite3VdbeExec +X-BeenThere: sqlite-dev@sqlite.org +X-Mailman-Version: 2.1.9 +Precedence: high +Reply-To: sqlite-dev@sqlite.org +List-Id: <sqlite-dev.sqlite.org> +List-Unsubscribe: <http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev>, + <mailto:sqlite-dev-request@sqlite.org?subject=unsubscribe> +List-Archive: <http://sqlite.org:8080/cgi-bin/mailman/private/sqlite-dev> +List-Post: <mailto:sqlite-dev@sqlite.org> +List-Help: <mailto:sqlite-dev-request@sqlite.org?subject=help> +List-Subscribe: <http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev>, + <mailto:sqlite-dev-request@sqlite.org?subject=subscribe> +Sender: sqlite-dev-bounces@sqlite.org +Errors-To: sqlite-dev-bounces@sqlite.org +Content-Length: 2212 + +This is a multi-part message in MIME format. +--------------000207070200050102060301 +Content-Type: text/plain; charset=ISO-8859-1; format=flowed +Content-Transfer-Encoding: 7bit + +Marco Bambini wrote: +> Inside sqlite3VdbeExec there is a very big switch statement. +> In order to increase performance with few modifications to the +> original code, why not use this technique ? +> http://docs.freebsd.org/info/gcc/gcc.info.Labels_as_Values.html +> +> With a properly defined "instructions" array, instead of the switch +> statement you can use something like: +> goto * instructions[pOp->opcode]; +> --- +> Marco Bambini +> http://www.sqlabs.net +> http://www.sqlabs.net/blog/ +> http://www.sqlabs.net/realsqlserver/ +> +> +> +> _______________________________________________ +> sqlite-dev mailing list +> sqlite-dev@sqlite.org +> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev +> +All the world's not a VAX. This technique is GCC-specific. The SQLite +source must be as portable as possible thus tying it to a specific +compiler is out of the question. While one could conceivably use some +preprocessor magic to provide alternate implementations, that would be +impractical considering the sheer size of the code affected. +On the other hand - perhaps you could benchmark the change and provide +some data on whether this actually improves performance? + + +--------------000207070200050102060301 +Content-Type: text/x-vcard; charset=utf-8; + name="mihailim.vcf" +Content-Transfer-Encoding: 7bit +Content-Disposition: attachment; + filename="mihailim.vcf" + +begin:vcard +fn:Mihai Limbasan +n:Limbasan;Mihai +org:SC SECPRAL COM SRL +adr:;;str. Actorului nr. 9;Cluj-Napoca;Cluj;400441;Romania +email;internet:mihailim@security.ro +title:SoftwareDeveloper +tel;work:+40 264 449579 +tel;fax:+40 264 418594 +tel;cell:+40 729 038302 +url:http://secpral.ro/ +version:2.1 +end:vcard + + +--------------000207070200050102060301 +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Content-Disposition: inline + +_______________________________________________ +sqlite-dev mailing list +sqlite-dev@sqlite.org +http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev + +--------------000207070200050102060301-- + diff --git a/lib/testdir/cur/1252168370_3.14675.cthulhu!2,S b/lib/testdir/cur/1252168370_3.14675.cthulhu!2,S new file mode 100644 index 0000000..4fad706 --- /dev/null +++ b/lib/testdir/cur/1252168370_3.14675.cthulhu!2,S @@ -0,0 +1,21 @@ +Return-Path: <dfgh@floppydisk.nl> +X-Spam-Checker-Version: SpamAssassin 3.1.0 (2005-09-13) on mindcrime +X-Spam-Level: +Delivered-To: dfgh@floppydisk.nl +Message-ID: <43A09C49.9040902@euler.org> +Date: Wed, 14 Dec 2005 23:27:21 +0100 +From: Fred Flintstone <fred@euler.org> +User-Agent: Mozilla Thunderbird 1.0.7 (X11/20051010) +X-Accept-Language: nl-NL, nl, en +MIME-Version: 1.0 +To: dfgh@floppydisk.nl +Subject: Re: xyz +References: <439C1136.90504@euler.org> <4399DD94.5070309@euler.org> <20051209233303.GA13812@gauss.org> <439B41ED.2080402@euler.org> <4399DD94.5070309@euler.org> <20051209233303.GA13812@gauss.org> <439A1E03.3090604@euler.org> <20051211184308.GB13513@gauss.org> +In-Reply-To: <20051211184308.GB13513@gauss.org> +X-Enigmail-Version: 0.92.0.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 7bit +X-UIDL: T<?"!%LG"!cAK"!_j(#! +Content-Length: 1879 + +Test 123. diff --git a/lib/testdir/cur/1283599333.1840_11.cthulhu!2, b/lib/testdir/cur/1283599333.1840_11.cthulhu!2, new file mode 100644 index 0000000..25c7180 --- /dev/null +++ b/lib/testdir/cur/1283599333.1840_11.cthulhu!2, @@ -0,0 +1,16 @@ +From: Frodo Baggins <frodo@example.com> +To: Bilbo Baggins <bilbo@anotherexample.com> +Subject: Greetings from =?UTF-8?B?TG90aGzDs3JpZW4=?= +User-Agent: Wanderlust/2.15.9 (Almost Unreal) Emacs/24.0 Mule/6.0 (HANACHIRUSATO) +Fcc: .sent +Organization: The Fellowship of the Ring +MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Message-Id: <abcd$efgh@example.com> + + +Let's write some fünkÿ text +using umlauts. + +Foo. diff --git a/lib/testdir/cur/1305664394.2171_402.cthulhu!2, b/lib/testdir/cur/1305664394.2171_402.cthulhu!2, new file mode 100644 index 0000000..863f714 --- /dev/null +++ b/lib/testdir/cur/1305664394.2171_402.cthulhu!2, @@ -0,0 +1,17 @@ +From: =?UTF-8?B?TcO8?= <testmu@testmu.xx> +To: Helmut =?UTF-8?B?S3LDtmdlcg==?= <hk@testmu.xxx> +Subject: =?UTF-8?B?TW90w7ZyaGVhZA==?= +User-Agent: Wanderlust/2.15.9 (Almost Unreal) Emacs/24.0 Mule/6.0 (HANACHIRUSATO) +References: <non-exist-01@msg.id> <non-exist-02@msg.id> <non-exist-03@msg.id> <non-exist-04@msg.id> +1n-Reply-To: <non-exist-04@msg.id> +MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + +Test for issue #38, where apparently searching for accented words in subject, +to etc. fails. + +What about here? Queensrÿche. Mötley Crüe. + + diff --git a/lib/testdir/cur/encrypted!2,S b/lib/testdir/cur/encrypted!2,S new file mode 100644 index 0000000..f75fd40 --- /dev/null +++ b/lib/testdir/cur/encrypted!2,S @@ -0,0 +1,56 @@ +Return-path: <> +Envelope-to: peter@example.com +Delivery-date: Fri, 11 May 2012 16:22:03 +0300 +Received: from localhost.example.com ([127.0.0.1] helo=borealis) + by borealis with esmtp (Exim 4.77) + id 1SSpnB-00038a-Ux + for djcb@localhost; Fri, 11 May 2012 16:21:58 +0300 +Delivered-To: peter@example.com +From: Brian <brian@example.com> +To: Peter <peter@example.com> +Subject: encrypted +User-agent: mu4e 0.9.8.5-dev1; emacs 24.1.50.8 +Date: Fri, 11 May 2012 16:21:42 +0300 +Message-ID: <!&!AAAAAAAAAYAAAAAAAAAOH1+8mkk+lLn7Gg5fke7FbCgAAAEAAAAJ7eBDgcactKhXL6r8cEnJ8BAAAAAA==@example.com> +MIME-Version: 1.0 +Content-Type: multipart/encrypted; boundary="=-=-="; + protocol="application/pgp-encrypted" + +--=-=-= +Content-Type: application/pgp-encrypted + +Version: 1 + +--=-=-= +Content-Type: application/octet-stream + +-----BEGIN PGP MESSAGE----- +Version: GnuPG v1.4.12 (GNU/Linux) + +hQQOA1T38TPQrHD6EA//YXkUB4Dy09ngCRyHWbXmV3XBjuKTr8xrak5ML1kwurav +gyagOHKLMU+5CKvObChiKtXhtgU0od7IC8o+ALlHevQ0XXcqNYA2KUfX8R7akq7d +Xx9mA6D8P7Y/P8juUCLBpfrCi2GC42DtvPZSUu3bL/ctUJ3InPHIfHibKF2HMm7/ +gUHAKY8VPJF39dLP8GLcfki6qFdeWbxgtzmuyzHfCBCLnDL0J9vpEQBpGDFMcc4v +cCbmMJaiPOmRb6U4WOuRVnuXuTztLiIn0jMslzOSFDcLTVBAsrC01r71O+XZKfN4 +mIfcpcWJYKM2NQW8Jwf+8Hr84uznBqs8uTTlrmppjkAHZGqGMjiQDxLhDVaCQzMy +O8PSV4xT6HPlKXOwV1OLc+vm0A0RAdSBctgZg40oFn4XdB1ur8edwAkLvc0hJKaz +gyTQiPaXm2Uh2cDeEx4xNgXmwCKasqc9jAlnDC2QwA33+pw3OqgZT5h1obn0fAeR +mgB+iW1503DIi/96p8HLZcr2EswLEH9ViHIEaFj/vlR5BaOncsLB0SsNV/MHRvym +Xg5GUjzPIiyBZ3KaR9OIBiZ5eXw+bSrPAo/CAs0Zwxag7W3CH//oK39Qo1GnkYpc +4IQxhx4IwkzqtCnripltV/kfpGu0yA/OdK8lOjkUqCwvL97o73utXIxm21Zd3mEP +/iLNrduZjMCq+goz1pDAQa9Dez6VjwRuRPTqeAac8Fx/nzrVzIoIEAt36hpuaH1l +KpbmHpKgsUWcrE5iYT0RRlRRtRF4PfJg8PUmP1hvw8TaEmNfT+0HgzcJB/gRsVdy +gTzkzUDzGZLhRcpmM5eW4BkuUmIO7625pM6Jd3HOGyfCGSXyEZGYYeVKzv8xbzYf +QM6YYKooRN9Ya2jdcWguW0sCSJO/RZ9eaORpTeOba2+Fp6w5L7lga+XM9GLfgref +Cf39XX1RsmRBsrJTw0z5COf4bT8G3/IfQP0QyKWIFITiFjGmpZhLsKQ3KT4vSe/d +gTY1xViVhkjvMFn3cgSOSrvktQpAhsXx0IRazN0T7pTU33a5K0SrZajY9ynFDIw9 +we7XYyVwZzYEXjGih5mTH1PhWYK5fZZEKKqaz5TyYv9SeWJ+8FrHeXUKD38SQEHM +qkpl9Iv17RF4Qy9uASWwRoobhKO+GykTaBSTyw8R8ctG/hfAlnaZxQ3TwNyHWyvU +9SVJsp27ulv/W9MLZtGpEMK0ckAR164Vyou1KOn200BqxbC2tJpegNeD2TP5ZtdY +HIcxkgKr0haYcDnVEf1ulSxv23pZWIexbgvVCG7dRL0eB+6O28f9CWehle10MDyM +0AYyw8Da2cu7PONMovqt4nayScyGTacFBp7c2KXR9DGZ0mcBwOjL/mGRKcVWN3MG +2auCrwn2KVWmKZI3Jp0T8KhfGBnFs9lUElpDTOiED1/2bKz6Yoc385QtWx99DFMZ +IWiH5wMxkWFpzjE+GHiJ09vSbTTL4JY9eu2n5nxQmtjYMBVxQm7S7qwH +=0Paa +-----END PGP MESSAGE----- +--=-=-=-- diff --git a/lib/testdir/cur/multimime!2,FS b/lib/testdir/cur/multimime!2,FS new file mode 100644 index 0000000..84f85aa --- /dev/null +++ b/lib/testdir/cur/multimime!2,FS @@ -0,0 +1,27 @@ +Return-path: <> +Envelope-to: djcb@localhost +Delivery-date: Sun, 20 May 2012 09:59:51 +0300 +From: Steve Jobs <jobs@example.com> +To: Bill Gates <bg@example.com> +Subject: multimime +User-agent: mu4e 0.9.8.4; emacs 23.3.1 +Date: Sat, 19 May 2012 20:57:56 +0100 +Message-ID: <m2fwaw2baz.fsf@example.com> +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="=-=-=" + +--=-=-= +Content-Type: text/plain + +abc +--=-=-= +Content-Type: application/octet-stream +Content-Disposition: attachment; filename="test1.C" +Content-Transfer-Encoding: base64 + +aGVyZSBpcyBhIHNpbXBsZSB0ZXN0IGZpbGUuCg== +--=-=-= +Content-Type: text/plain + +def +--=-=-=-- diff --git a/lib/testdir/cur/multirecip!2,S b/lib/testdir/cur/multirecip!2,S new file mode 100644 index 0000000..c997503 --- /dev/null +++ b/lib/testdir/cur/multirecip!2,S @@ -0,0 +1,11 @@ +Date: Thu, 15 May 2016 14:57:25 -0200 +From: +To: a@example.com,b@example.com,c@example.com +Cc: d@example.com,e@example.com +Subject: test with multi to and cc +Message-id: <3BE9E652343245@emss35m06.us.lmco.com> + +Message with multi cc and to. + + + diff --git a/lib/testdir/cur/signed!2,S b/lib/testdir/cur/signed!2,S new file mode 100644 index 0000000..a2e7e21 --- /dev/null +++ b/lib/testdir/cur/signed!2,S @@ -0,0 +1,36 @@ +Return-path: <> +Envelope-to: skipio@localhost +Delivery-date: Fri, 11 May 2012 16:21:57 +0300 +Received: from localhost.roma.net([127.0.0.1] helo=borealis) + by borealis with esmtp (Exim 4.77) + id 1SSpnB-00038a-55 + for djcb@localhost; Fri, 11 May 2012 16:21:57 +0300 +Delivered-To: diggler@gmail.com +From: Skipio <skipio@roma.net> +To: Hannibal <hanni@carthago.net> +Subject: signed +User-agent: mu4e 0.9.8.5-dev1; emacs 24.1.50.8 +Date: Fri, 11 May 2012 16:20:45 +0300 +Message-ID: <878vgy97ma.fsf@roma.net> +MIME-Version: 1.0 +Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha1; + protocol="application/pgp-signature" + +--=-=-= +Content-Type: text/plain + + +I am signed! + +--=-=-= +Content-Type: application/pgp-signature + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.12 (GNU/Linux) + +iEYEARECAAYFAk+tEi0ACgkQ6WrHoQF92jxTzACeKd/XxY+P7bpymWL3JBRHaW9p +DpwAoKw7PDW4z/lNTkWjndVTjoO9jGhs +=blXz +-----END PGP SIGNATURE----- +--=-=-=-- + diff --git a/lib/testdir/cur/signed-encrypted!2,S b/lib/testdir/cur/signed-encrypted!2,S new file mode 100644 index 0000000..a3910e6 --- /dev/null +++ b/lib/testdir/cur/signed-encrypted!2,S @@ -0,0 +1,54 @@ +Return-path: <> +Envelope-to: karjala@localhost +Delivery-date: Fri, 11 May 2012 16:37:57 +0300 +From: karjala@example.com +To: lapinkulta@example.com +Subject: signed + encrypted +User-agent: mu4e 0.9.8.5-dev1; emacs 24.1.50.8 +Date: Fri, 11 May 2012 16:36:08 +0300 +Message-ID: <874nrm96wn.fsf@example.com> +MIME-Version: 1.0 +Content-Type: multipart/encrypted; boundary="=-=-="; + protocol="application/pgp-encrypted" + +--=-=-= +Content-Type: application/pgp-encrypted + +Version: 1 + +--=-=-= +Content-Type: application/octet-stream + +-----BEGIN PGP MESSAGE----- +Version: GnuPG v1.4.12 (GNU/Linux) + +hQQOA1T38TPQrHD6EA/+K4kSpMa7zk+qihUkQnHSq28xYxisNQx6X5DVNjA/Qx16 +uZj/40ae+PoSMTVfklP+B2S/IomuTW6dwVqS7aQ3u4MTzi+YOi11k1lEMD7hR0Wb +L0i48o3/iCPuCTpnOsaLZvRL06g+oTi0BF2pgz/YdsgsBTGrTb3pkDGSlLIhvh/J +P8eE3OuzkXS6d8ymJKx2S2wQJrc1AFf1BgJfgc5T0iAvcV+zIMG+PIYcVd04zVpj +cORFEfvGgfxWkeX+Ks3tu/l5PA1EesnoqFdNFZm+RKBg3RFsOm8tBlJ46xJjfeHg +zLgifeSLy3tOX7CvWYs9torrx7s7UOI2gV8kzBqz+a7diyCMezceeQ9l0nIRybwW +C9Egp8Bpfb02iXTOGdE/vRiNItQH14GKmXf4nCSwdtQUm3yzaqY9yL3xBxAlW53e +YOFfPMESt+E7IlPn0c7llWGrcdrhJbUEoGOIPezES7kdeNPzi8G1lLtvT04/SSZJ +QxPH5FNzSFaYFAQSdI7TR69P7L7vtLL8ndkjY49HfLFXochQQzsqrzVxzRCruHxA +zbZSRptNf9SuXEaX9buO1vlFHheGvrCKzEWa6O7JD/DiyrE/zqy4jdlh9abMCouQ +GWGSbn8jk6SMTQQ2Yv/VOyFqifHZp0UJD59tyIdenpxoYu5M0lwHLNVDlRjLEwUQ +AIDz1tbLoM7lxs2FOKGr8QqbKIeMfL+NUmbvVIDc4mJrOlRnHh+cZYm4Z49iTl1v +bYNMYgR5nY7W6rqh0ae7ZOW0h2NzpkAwTzuf1YrSjNavd9KBwOCFtAoZhRwfwFVx +ju+ByHFNnf7g/R6DekHS0pSiatM0cPDJT05atEZb+13CRHHznonmLHi+VahXjrpg +cIUA8Lhjdfm6Fsabo7gNZnTTRxNBqUXKK2vJF/XLbNrH5K2BH2dCCmUNtm3yFWiM +DOzaw3665Y3S6MvZdyKpatbNrVoJdBpRgPxJ1YCSEituFUqHJBStay+aRb5fVkQR +w3+9hWw+Ob0+2EumKbgfQ7iMwTZBCZP4VOxkoqdHvs9aWm4N7wHtXsyCew3icbJx +lyUWsDx/FI+HlQRfOqeAMxmp8kKybmHNw8oGiw+uPPUHSD1NFYVm2DtwhYll3Fvs +YY7r5s3yP1ZnwxMqWI3OsExVUXs8MS4UTAgO+cggO7YidPcANbBDihBFP8mTXtni +Oo5n5v+/eRoLfHmnsGcaK8EkKsfFHpbqn4gxXGcBuHaTTJ/ZhbW6bi1WWZA9ExaJ +IeTDtp5Bks1pJvTjCDacvgwl3rEBM6yaeIvB7575Y/GPMTOZhawhfOxV1smMmTKI +JOWYb3+PuN2cvWetkjFgH8re4sRXq22DKBZHJEWYU8sH0sACAePnIr+pkrOtGeJB +t1zBqZUnrupH6ptk9n/AjbQ+XSMTEKu55gSjYLAYx1EHApx52QLkdh+ej5xCIVeY +6wS1Iipkoc6/r6F7CKctupXurNY2AlD4uQIOfD6kQgkqK4PY3hsRHQA+Zqj6oRfr +kxysFJZvhgt26IeBVapFs10WuYt9iHfpbPUBQUIZCLyPAh08UdVW64Uc2DvUPy+I +C+3RrmTHQPP/YNKgDQaZ3ySVEDkqjaDPmXr5K0Ibaib2dtPCLcA= +=pv03 +-----END PGP MESSAGE----- +--=-=-=-- + diff --git a/lib/testdir/cur/special!2,Sabc b/lib/testdir/cur/special!2,Sabc new file mode 100644 index 0000000..7f1de8e --- /dev/null +++ b/lib/testdir/cur/special!2,Sabc @@ -0,0 +1,10 @@ +Date: Thu, 1 Jun 2012 14:57:25 -0200 +From: "Rocky Balboa" <rocky@example.com> +To: "Ivan Drago" <ivan@example.com> +Subject: currying and tail optimization +Message-id: <3BE9E653ef345@emss35m06.us.lmco.com> +MIME-version: 1.0 +Content-type: text/plain; charset=us-ascii +Content-transfer-encoding: 7BIT + +Test 123. I'm a special message with special flags. diff --git a/lib/testdir/new/1220863087.12663_21.mindcrime b/lib/testdir/new/1220863087.12663_21.mindcrime new file mode 100644 index 0000000..4101716 --- /dev/null +++ b/lib/testdir/new/1220863087.12663_21.mindcrime @@ -0,0 +1,111 @@ +Return-Path: <help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org> +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime +X-Spam-Level: +X-Spam-Status: No, score=-2.6 required=3.0 tests=BAYES_00 autolearn=ham + version=3.2.5 +X-Original-To: xxxx@localhost +Delivered-To: xxxx@localhost +Received: from mindcrime (localhost [127.0.0.1]) + by mail.xxxxsoftware.nl (Postfix) with ESMTP id 6389969CB2 + for <xxxx@localhost>; Thu, 7 Aug 2008 08:10:07 +0300 (EEST) +Delivered-To: xxxx.klub@gmail.com +Received: from gmail-imap.l.google.com [66.249.91.109] + by mindcrime with IMAP (fetchmail-6.3.8) + for <xxxx@localhost> (single-drop); Thu, 07 Aug 2008 08:10:07 +0300 (EEST) +Received: by 10.142.237.21 with SMTP id k21cs34769wfh; Wed, 6 Aug 2008 + 13:38:53 -0700 (PDT) +Received: by 10.100.6.13 with SMTP id 13mr4103508anf.83.1218055131215; Wed, 06 + Aug 2008 13:38:51 -0700 (PDT) +Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) by mx.google.com + with ESMTP id b32si10199298ana.34.2008.08.06.13.38.49; Wed, 06 Aug 2008 + 13:38:51 -0700 (PDT) +Received-SPF: pass (google.com: domain of + help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 + as permitted sender) client-ip=199.232.76.165; +DomainKey-Status: good (test mode) +Authentication-Results: mx.google.com; spf=pass (google.com: domain of + help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 + as permitted sender) + smtp.mail=help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org; domainkeys=pass + (test mode) header.From=juanma_bellon@yahoo.es +Received: from localhost ([127.0.0.1]:55648 helo=lists.gnu.org) by + lists.gnu.org with esmtp (Exim 4.43) id 1KQpmT-0005W9-AQ for + xxxx.klub@gmail.com; Wed, 06 Aug 2008 16:38:49 -0400 +Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id + 1KQplz-0005U5-Pk for help-gnu-emacs@gnu.org; Wed, 06 Aug 2008 16:38:19 -0400 +Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id + 1KQplw-0005Nw-OG for help-gnu-emacs@gnu.org; Wed, 06 Aug 2008 16:38:19 -0400 +Received: from [199.232.76.173] (port=45465 helo=monty-python.gnu.org) by + lists.gnu.org with esmtp (Exim 4.43) id 1KQplw-0005NX-I6 for + help-gnu-emacs@gnu.org; Wed, 06 Aug 2008 16:38:16 -0400 +Received: from n74a.bullet.mail.sp1.yahoo.com ([98.136.45.21]:29868) by + monty-python.gnu.org with smtp (Exim 4.60) (envelope-from + <juanma_bellon@yahoo.es>) id 1KQplw-0007EF-7Z for help-gnu-emacs@gnu.org; + Wed, 06 Aug 2008 16:38:16 -0400 +Received: from [216.252.122.216] by n74.bullet.mail.sp1.yahoo.com with NNFMP; + 06 Aug 2008 20:38:14 -0000 +Received: from [68.142.237.89] by t1.bullet.sp1.yahoo.com with NNFMP; 06 Aug + 2008 20:38:14 -0000 +Received: from [69.147.75.180] by t5.bullet.re3.yahoo.com with NNFMP; 06 Aug + 2008 20:38:14 -0000 +Received: from [127.0.0.1] by omp101.mail.re1.yahoo.com with NNFMP; 06 Aug + 2008 20:38:14 -0000 +X-Yahoo-Newman-Id: 778995.62909.bm@omp101.mail.re1.yahoo.com +Received: (qmail 43643 invoked from network); 6 Aug 2008 20:38:14 -0000 +DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=s1024; d=yahoo.es; + h=Received:X-YMail-OSG:X-Yahoo-Newman-Property:From:To:Subject:Date:User-Agent:References:In-Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-Disposition:Message-Id; + b=ThdHlND5CNUsLPGuk+XhCWkdUA9w7lg4hiAgx8F8egsmQteMpwUlV/Y5tfe6K3O2jzHjtsklkzWqm7WY3VAcxxD/QgxLnianK5ZQHoelDAiGaFRqu8Y42XMZso2ccCBFWUQaKo9C+KIfa3e3ci73qehVxTtmr7bxLjurcSYEBPo= + ; +Received: from unknown (HELO 212251170160.customer.cdi.no) + (juanma_bellon@212.251.170.160 with plain) by smtp109.plus.mail.re1.yahoo.com + with SMTP; 6 Aug 2008 20:38:14 -0000 +X-YMail-OSG: k86L54kVM1kiZbUlYx7gayoBrCLYMFIRDL.KJLBKetNucAbwU4RjeeE1vhjw33hREaUig0CCjG7BTwIfbeZZpRmUcHbxl6gR0z6Sd3lYqA-- +X-Yahoo-Newman-Property: ymail-3 +From: anon@example.com +To: help-gnu-emacs@gnu.org +Date: Wed, 6 Aug 2008 22:38:15 +0200 +User-Agent: KMail/1.9.6 (enterprise 0.20070907.709405) +References: <mailman.15123.1216681940.18990.help-gnu-emacs@gnu.org> + <mailman.15143.1216715014.18990.help-gnu-emacs@gnu.org> + <9bc17528-8ea9-49f7-8e9d-07f5ede91415@p31g2000prf.googlegroups.com> +In-Reply-To: <9bc17528-8ea9-49f7-8e9d-07f5ede91415@p31g2000prf.googlegroups.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: quoted-printable +Content-Disposition: inline +Message-Id: <200808062238.15634.juanma_bellon@yahoo.es> +X-detected-kernel: by monty-python.gnu.org: FreeBSD 6.x (1) +Subject: Re: basic question: going back to dired +X-BeenThere: help-gnu-emacs@gnu.org +X-Mailman-Version: 2.1.5 +Precedence: list +List-Id: Users list for the GNU Emacs text editor <help-gnu-emacs.gnu.org> +List-Unsubscribe: <http://lists.gnu.org/mailman/listinfo/help-gnu-emacs>, + <mailto:help-gnu-emacs-request@gnu.org?subject=unsubscribe> +List-Archive: <http://lists.gnu.org/pipermail/help-gnu-emacs> +List-Post: <mailto:help-gnu-emacs@gnu.org> +List-Help: <mailto:help-gnu-emacs-request@gnu.org?subject=help> +List-Subscribe: <http://lists.gnu.org/mailman/listinfo/help-gnu-emacs>, + <mailto:help-gnu-emacs-request@gnu.org?subject=subscribe> +Sender: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Errors-To: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Content-Length: 361 + +On Thursday 31 July 2008, Xah wrote: +> what's the logic of =E2=80=9COK=E2=80=9D? + +=46or all I know, it comes from "0 Knock-outs" (from USA civil war times, +IIRC), i.e., all went really well. + +But this is really off-topic. +=2D-=20 +Juanma + +"Having a smoking section in a restaurant is like + having a peeing section in a swimming pool." + -- Edward Burr + + + + + diff --git a/lib/testdir/new/1220863087.12663_23.mindcrime b/lib/testdir/new/1220863087.12663_23.mindcrime new file mode 100644 index 0000000..ca46f2b --- /dev/null +++ b/lib/testdir/new/1220863087.12663_23.mindcrime @@ -0,0 +1,105 @@ +Return-Path: <help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org> +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime +X-Spam-Level: +X-Spam-Status: No, score=-2.6 required=3.0 tests=BAYES_00 autolearn=ham + version=3.2.5 +X-Original-To: xxxx@localhost +Delivered-To: xxxx@localhost +Received: from mindcrime (localhost [127.0.0.1]) + by mail.xxxxsoftware.nl (Postfix) with ESMTP id C3EF069CB3 + for <xxxx@localhost>; Thu, 7 Aug 2008 08:10:10 +0300 (EEST) +Delivered-To: xxxx.klub@gmail.com +Received: from gmail-imap.l.google.com [66.249.91.109] + by mindcrime with IMAP (fetchmail-6.3.8) + for <xxxx@localhost> (single-drop); Thu, 07 Aug 2008 08:10:10 +0300 (EEST) +Received: by 10.142.237.21 with SMTP id k21cs35153wfh; Wed, 6 Aug 2008 + 13:58:17 -0700 (PDT) +Received: by 10.100.166.10 with SMTP id o10mr4182182ane.0.1218056296101; Wed, + 06 Aug 2008 13:58:16 -0700 (PDT) +Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) by mx.google.com + with ESMTP id d34si13875743and.3.2008.08.06.13.58.14; Wed, 06 Aug 2008 + 13:58:16 -0700 (PDT) +Received-SPF: pass (google.com: domain of + help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 + as permitted sender) client-ip=199.232.76.165; +Authentication-Results: mx.google.com; spf=pass (google.com: domain of + help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 + as permitted sender) + smtp.mail=help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org; dkim=pass (test + mode) header.i=@gmail.com +Received: from localhost ([127.0.0.1]:33418 helo=lists.gnu.org) by + lists.gnu.org with esmtp (Exim 4.43) id 1KQq5G-0001aY-Cr for + xxxx.klub@gmail.com; Wed, 06 Aug 2008 16:58:14 -0400 +Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id + 1KQq4n-0001Z9-06 for help-gnu-emacs@gnu.org; Wed, 06 Aug 2008 16:57:45 -0400 +Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id + 1KQq4l-0001V8-6c for help-gnu-emacs@gnu.org; Wed, 06 Aug 2008 16:57:44 -0400 +Received: from [199.232.76.173] (port=46438 helo=monty-python.gnu.org) by + lists.gnu.org with esmtp (Exim 4.43) id 1KQq4k-0001Un-V2 for + help-gnu-emacs@gnu.org; Wed, 06 Aug 2008 16:57:42 -0400 +Received: from ik-out-1112.google.com ([66.249.90.180]:17562) by + monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from + <lekktu@gmail.com>) id 1KQq4k-0001fk-OW for help-gnu-emacs@gnu.org; Wed, 06 + Aug 2008 16:57:42 -0400 +Received: by ik-out-1112.google.com with SMTP id c21so94956ika.2 for + <help-gnu-emacs@gnu.org>; Wed, 06 Aug 2008 13:57:41 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; + h=domainkey-signature:received:received:message-id:date:from:to + :subject:cc:in-reply-to:mime-version:content-type + :content-transfer-encoding:content-disposition:references; + bh=TTNY9749hpg1+TXOwdaCr+zbQGhBUt3IvsjLWp+pxp0=; + b=BOfudUT/SiW9V4e9+k3dXDzwm+ogdrq4m5OlO+f1H+oE6OAYGIm8dbdqDAOwUewBoS + jRpfZo07YamP9rkko79SeFdQnf7UAPFAw9x7DFCm3x6muSlCcJBR7vYs1rgHOSINAn2B + vQx2//lKR4fXfKNURNu+B30KrvoEmw6m2C8dI= +DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; + h=message-id:date:from:to:subject:cc:in-reply-to:mime-version + :content-type:content-transfer-encoding:content-disposition :references; + b=UMDBulH/LwxDywEH0pfK3DbJ4u2kIZCVDLIM++PqrdcR82HjcS/O3Jhf5OFrf7Fnyj + GH76xmc7zkTG/3aQy2WY6DeWCJaFarEItmhxy3h/xS+kUKeDARzNox0OzK6lIv/u9bdy + f2LnFlYRJ7Q5vy3lxpxAWB4v0qCwtF9LjWFg4= +Received: by 10.210.47.7 with SMTP id u7mr3100239ebu.30.1218056261587; Wed, 06 + Aug 2008 13:57:41 -0700 (PDT) +Received: by 10.210.71.14 with HTTP; Wed, 6 Aug 2008 13:57:41 -0700 (PDT) +Message-ID: <f7ccd24b0808061357t453f5962w8b61f9a453b684d0@mail.gmail.com> +Date: Wed, 6 Aug 2008 22:57:41 +0200 +From: anon@example.com +To: Juanma <juanma_bellon@yahoo.es> +In-Reply-To: <200808062238.15634.juanma_bellon@yahoo.es> +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 7bit +Content-Disposition: inline +References: <mailman.15123.1216681940.18990.help-gnu-emacs@gnu.org> + <mailman.15143.1216715014.18990.help-gnu-emacs@gnu.org> + <9bc17528-8ea9-49f7-8e9d-07f5ede91415@p31g2000prf.googlegroups.com> + <200808062238.15634.juanma_bellon@yahoo.es> +X-detected-kernel: by monty-python.gnu.org: Linux 2.6 (newer, 2) +Cc: help-gnu-emacs@gnu.org +Subject: Re: basic question: going back to dired +X-BeenThere: help-gnu-emacs@gnu.org +X-Mailman-Version: 2.1.5 +Precedence: list +List-Id: Users list for the GNU Emacs text editor <help-gnu-emacs.gnu.org> +List-Unsubscribe: <http://lists.gnu.org/mailman/listinfo/help-gnu-emacs>, + <mailto:help-gnu-emacs-request@gnu.org?subject=unsubscribe> +List-Archive: <http://lists.gnu.org/pipermail/help-gnu-emacs> +List-Post: <mailto:help-gnu-emacs@gnu.org> +List-Help: <mailto:help-gnu-emacs-request@gnu.org?subject=help> +List-Subscribe: <http://lists.gnu.org/mailman/listinfo/help-gnu-emacs>, + <mailto:help-gnu-emacs-request@gnu.org?subject=subscribe> +Sender: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Errors-To: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Content-Length: 309 + +On Wed, Aug 6, 2008 at 22:38, Juanma <juanma_bellon@yahoo.es> wrote: + +> For all I know, it comes from "0 Knock-outs" (from USA civil war times, +> IIRC), i.e., all went really well. + +See http://en.wikipedia.org/wiki/Okay#Etymology + +"0 knock-outs" is among the "Improbable or refuted etymologies". + + Juanma + + diff --git a/lib/testdir/new/1220863087.12663_25.mindcrime b/lib/testdir/new/1220863087.12663_25.mindcrime new file mode 100644 index 0000000..588ace1 --- /dev/null +++ b/lib/testdir/new/1220863087.12663_25.mindcrime @@ -0,0 +1,98 @@ +Return-Path: <help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org> +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime +X-Spam-Level: +X-Spam-Status: No, score=-3.6 required=3.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW, + SPF_PASS autolearn=ham version=3.2.5 +X-Original-To: xxxx@localhost +Delivered-To: xxxx@localhost +Received: from mindcrime (localhost [127.0.0.1]) + by mail.xxxxsoftware.nl (Postfix) with ESMTP id D68E769CB5 + for <xxxx@localhost>; Fri, 8 Aug 2008 20:56:25 +0300 (EEST) +Delivered-To: xxxx.klub@gmail.com +Received: from gmail-imap.l.google.com [72.14.221.111] + by mindcrime with IMAP (fetchmail-6.3.8) + for <xxxx@localhost> (single-drop); Fri, 08 Aug 2008 20:56:25 +0300 (EEST) +Received: by 10.142.237.21 with SMTP id k21cs71287wfh; Fri, 8 Aug 2008 + 07:40:46 -0700 (PDT) +Received: by 10.100.122.8 with SMTP id u8mr3824321anc.77.1218206446062; Fri, + 08 Aug 2008 07:40:46 -0700 (PDT) +Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) by mx.google.com + with ESMTP id d35si2718351and.38.2008.08.08.07.40.45; Fri, 08 Aug 2008 + 07:40:46 -0700 (PDT) +Received-SPF: pass (google.com: domain of + help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 + as permitted sender) client-ip=199.232.76.165; +Authentication-Results: mx.google.com; spf=pass (google.com: domain of + help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 + as permitted sender) + smtp.mail=help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Received: from localhost ([127.0.0.1]:47349 helo=lists.gnu.org) by + lists.gnu.org with esmtp (Exim 4.43) id 1KRT93-0006Po-A3 for + xxxx.klub@gmail.com; Fri, 08 Aug 2008 10:40:45 -0400 +Path: news.stanford.edu!headwall.stanford.edu!newshub.sdsu.edu!news-out.readnews.com!news-xxxfer.readnews.com!panix!not-for-mail +From: anon@example.com +Newsgroups: gnu.emacs.help +Date: Fri, 08 Aug 2008 10:07:30 -0400 +Organization: PANIX Public Access Internet and UNIX, NYC +Message-ID: <uwsireh25.fsf@one.dot.net> +References: <mailman.15123.1216681940.18990.help-gnu-emacs@gnu.org> + <mailman.15143.1216715014.18990.help-gnu-emacs@gnu.org> + <9bc17528-8ea9-49f7-8e9d-07f5ede91415@p31g2000prf.googlegroups.com> + <200808062238.15634.juanma_bellon@yahoo.es> + <mailman.15958.1218056266.18990.help-gnu-emacs@gnu.org> +NNTP-Posting-Host: panix5.panix.com +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +X-Trace: reader1.panix.com 1218204439 22850 166.84.1.5 (8 Aug 2008 14:07:19 + GMT) +X-Complaints-To: abuse@panix.com +NNTP-Posting-Date: Fri, 8 Aug 2008 14:07:19 +0000 (UTC) +User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.2 (windows-nt) +Cancel-Lock: sha1:Ckkp5oJPIMuAVgEHGnS/9MkZsEs= +Xref: news.stanford.edu gnu.emacs.help:160963 +To: help-gnu-emacs@gnu.org +Subject: Re: basic question: going back to dired +X-BeenThere: help-gnu-emacs@gnu.org +X-Mailman-Version: 2.1.5 +Precedence: list +List-Id: Users list for the GNU Emacs text editor <help-gnu-emacs.gnu.org> +List-Unsubscribe: <http://lists.gnu.org/mailman/listinfo/help-gnu-emacs>, + <mailto:help-gnu-emacs-request@gnu.org?subject=unsubscribe> +List-Archive: <http://lists.gnu.org/pipermail/help-gnu-emacs> +List-Post: <mailto:help-gnu-emacs@gnu.org> +List-Help: <mailto:help-gnu-emacs-request@gnu.org?subject=help> +List-Subscribe: <http://lists.gnu.org/mailman/listinfo/help-gnu-emacs>, + <mailto:help-gnu-emacs-request@gnu.org?subject=subscribe> +Sender: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Errors-To: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Content-Length: 710 +Lines: 27 + +I seem to remember from my early school days it was a campaign slogan +for someone nick-named Kinderhook that went something like + +Old Kinderhook is OK + +- Chris + +"Juanma Barranquero" <lekktu@gmail.com> writes: + +> On Wed, Aug 6, 2008 at 22:38, Juanma <juanma_bellon@yahoo.es> wrote: +> +>> For all I know, it comes from "0 Knock-outs" (from USA civil war times, +>> IIRC), i.e., all went really well. +> +> See http://en.wikipedia.org/wiki/Okay#Etymology +> +> "0 knock-outs" is among the "Improbable or refuted etymologies". +> +> Juanma +> +> + +-- + (. .) + =ooO=(_)=Ooo===================================== + Chris McMahan | first_initiallastname@one.dot.net + ================================================= + diff --git a/lib/testdir/new/1220863087.12663_9.mindcrime b/lib/testdir/new/1220863087.12663_9.mindcrime new file mode 100644 index 0000000..734ee35 --- /dev/null +++ b/lib/testdir/new/1220863087.12663_9.mindcrime @@ -0,0 +1,209 @@ +Return-Path: <sqlite-dev-bounces@sqlite.org> +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime +X-Spam-Level: +X-Spam-Status: No, score=-1.2 required=3.0 tests=BAYES_00,HTML_MESSAGE, + MIME_QP_LONG_LINE autolearn=no version=3.2.5 +X-Original-To: xxxx@localhost +Delivered-To: xxxx@localhost +Received: from mindcrime (localhost [127.0.0.1]) + by mail.xxxxsoftware.nl (Postfix) with ESMTP id 4E3CF6963B + for <xxxx@localhost>; Mon, 4 Aug 2008 21:49:37 +0300 (EEST) +Delivered-To: xxxx.klub@gmail.com +Received: from gmail-imap.l.google.com [72.14.221.111] + by mindcrime with IMAP (fetchmail-6.3.8) + for <xxxx@localhost> (single-drop); Mon, 04 Aug 2008 21:49:37 +0300 (EEST) +Received: by 10.142.51.12 with SMTP id y12cs94317wfy; Mon, 4 Aug 2008 05:48:28 + -0700 (PDT) +Received: by 10.150.152.17 with SMTP id z17mr1245909ybd.194.1217854107583; + Mon, 04 Aug 2008 05:48:27 -0700 (PDT) +Received: from sqlite.org (sqlite.org [67.18.92.124]) by mx.google.com with + ESMTP id 9si6334793yws.5.2008.08.04.05.47.57; Mon, 04 Aug 2008 05:48:27 -0700 + (PDT) +Received-SPF: pass (google.com: best guess record for domain of + sqlite-dev-bounces@sqlite.org designates 67.18.92.124 as permitted sender) + client-ip=67.18.92.124; +Authentication-Results: mx.google.com; spf=pass (google.com: best guess record + for domain of sqlite-dev-bounces@sqlite.org designates 67.18.92.124 as + permitted sender) smtp.mail=sqlite-dev-bounces@sqlite.org +Received: from sqlite.org (localhost [127.0.0.1]) by sqlite.org (Postfix) with + ESMTP id 4FBC111C6F; Mon, 4 Aug 2008 08:47:54 -0400 (EDT) +X-Original-To: sqlite-dev@sqlite.org +Delivered-To: sqlite-dev@sqlite.org +Received: from cpsmtpo-eml02.kpnxchange.com (cpsmtpo-eml02.kpnxchange.com + [213.75.38.151]) by sqlite.org (Postfix) with ESMTP id AA4F111C10 for + <sqlite-dev@sqlite.org>; Mon, 4 Aug 2008 08:47:51 -0400 (EDT) +Received: from hpsmtp-eml21.kpnxchange.com ([213.75.38.121]) by + cpsmtpo-eml02.kpnxchange.com with Microsoft SMTPSVC(6.0.3790.1830); Mon, 4 + Aug 2008 14:47:50 +0200 +Received: from cpbrm-eml13.kpnsp.local ([195.121.247.250]) by + hpsmtp-eml21.kpnxchange.com with Microsoft SMTPSVC(6.0.3790.1830); Mon, 4 + Aug 2008 14:47:50 +0200 +Received: from hpsmtp-eml30.kpnxchange.com ([10.94.53.250]) by + cpbrm-eml13.kpnsp.local with Microsoft SMTPSVC(6.0.3790.1830); Mon, 4 Aug + 2008 14:47:50 +0200 +Received: from localhost ([10.94.53.250]) by hpsmtp-eml30.kpnxchange.com with + Microsoft SMTPSVC(6.0.3790.1830); Mon, 4 Aug 2008 14:47:49 +0200 +Content-class: urn:content-classes:message +MIME-Version: 1.0 +X-MimeOLE: Produced By Microsoft Exchange V6.5 +Date: Mon, 4 Aug 2008 14:46:06 +0200 +Message-ID: <F687EC042917A94E8BB4B0902946453AE17D6C@CPEXBE-EML18.kpnsp.local> +X-MS-Has-Attach: +X-MS-TNEF-Correlator: +Thread-Topic: [sqlite-dev] VM optimization inside sqlite3VdbeExec +Thread-Index: Acj2FjkWvteFtLHTTYeVz4ES7E2ggAAGRxeI +References: <83B5AF40-DBFA-4578-A043-04C80276E195@sqlabs.net> +From: anon@example.com +To: <sqlite-dev@sqlite.org> +X-OriginalArrivalTime: 04 Aug 2008 12:47:49.0650 (UTC) + FILETIME=[4D577720:01C8F630] +Subject: Re: [sqlite-dev] VM optimization inside sqlite3VdbeExec +X-BeenThere: sqlite-dev@sqlite.org +X-Mailman-Version: 2.1.9 +Precedence: list +Reply-To: sqlite-dev@sqlite.org +List-Id: <sqlite-dev.sqlite.org> +List-Unsubscribe: <http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev>, + <mailto:sqlite-dev-request@sqlite.org?subject=unsubscribe> +List-Archive: <http://sqlite.org:8080/cgi-bin/mailman/private/sqlite-dev> +List-Post: <mailto:sqlite-dev@sqlite.org> +List-Help: <mailto:sqlite-dev-request@sqlite.org?subject=help> +List-Subscribe: <http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev>, + <mailto:sqlite-dev-request@sqlite.org?subject=subscribe> +Content-Type: multipart/mixed; boundary="===============1911358387==" +Mime-version: 1.0 +Sender: sqlite-dev-bounces@sqlite.org +Errors-To: sqlite-dev-bounces@sqlite.org +Content-Length: 5318 + +This is a multi-part message in MIME format. + +--===============1911358387== +Content-class: urn:content-classes:message +Content-Type: multipart/alternative; + boundary="----_=_NextPart_001_01C8F630.0FC2EC1E" + +This is a multi-part message in MIME format. + +------_=_NextPart_001_01C8F630.0FC2EC1E +Content-Type: text/plain; + charset="iso-8859-1" +Content-Transfer-Encoding: quoted-printable + +Actually, almost every C compiler will already do what you suggest: if = +the range of case labels is compact, the switch will be compiled using a = +jump table. Only if the range is limited and/or sparse other techniques = +will be used, such as linear search and binary search. +=20 +I'm pretty sure, if you perform the tests suggested by Mihai, that you = +will find zero performance difference, neither better, nor worse. +=20 +Paul +=20 +________________________________ + +From: anon@example.com +Sent: Mon 8/4/2008 11:40 AM +To: sqlite-dev@sqlite.org +Subject: [sqlite-dev] VM optimization inside sqlite3VdbeExec + + + +Inside sqlite3VdbeExec there is a very big switch statement. +In order to increase performance with few modifications to the=20 +original code, why not use this technique ? +http://docs.freebsd.org/info/gcc/gcc.info.Labels_as_Values.html = +<http://docs.freebsd.org/info/gcc/gcc.info.Labels_as_Values.html>=20 + +With a properly defined "instructions" array, instead of the switch=20 +statement you can use something like: +goto * instructions[pOp->opcode]; +--- +Marco Bambini +http://www.sqlabs.net <http://www.sqlabs.net/>=20 +http://www.sqlabs.net/blog/ <http://www.sqlabs.net/blog/>=20 +http://www.sqlabs.net/realsqlserver/ = +<http://www.sqlabs.net/realsqlserver/>=20 + + + +_______________________________________________ +sqlite-dev mailing list +sqlite-dev@sqlite.org +http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev = +<http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev>=20 + + + +------_=_NextPart_001_01C8F630.0FC2EC1E +Content-Type: text/html; + charset="iso-8859-1" +Content-Transfer-Encoding: quoted-printable + +<HTML dir=3Dltr><HEAD><TITLE>[sqlite-dev] VM optimization inside = +sqlite3VdbeExec=0A= +=0A= +=0A= +=0A= +
=0A= +
Actually, = +almost every C compiler will already do what you suggest: if the range = +of case labels is compact, the switch will be compiled using a jump = +table. Only if the range is limited and/or sparse other techniques will = +be used, such as linear search and binary search.
=0A= +
 
=0A= +
I'm pretty sure, if you = +perform the tests suggested by Mihai, that you will find zero = +performance difference, neither better, nor worse.
=0A= +
 
=0A= +
Paul
=0A= +
 
=0A= +
=0A= +
=0A= +
=0A= +
From: = +sqlite-dev-bounces@sqlite.org on behalf of Marco Bambini
Sent: = +Mon 8/4/2008 11:40 AM
To: = +sqlite-dev@sqlite.org
Subject: [sqlite-dev] VM optimization = +inside sqlite3VdbeExec

=0A= +
=0A= +

Inside sqlite3VdbeExec there is a very = +big switch statement.
In order to increase performance with few = +modifications to the 
original code, why not use this technique = +?
= +http://docs.freebsd.org/info/gcc/gcc.info.Labels_as_Values.html<= +/FONT>

With a properly defined = +"instructions" array, instead of the switch 
statement you can = +use something like:
goto * = +instructions[pOp->opcode];
---
Marco Bambini
http://www.sqlabs.net
http://www.sqlabs.net/blog/
http://www.sqlabs.net/realsqlserver/



<= +FONT face=3DArial = +size=3D2>_______________________________________________
sqlite-dev = +mailing list
sqlite-dev@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev

+------_=_NextPart_001_01C8F630.0FC2EC1E-- + + +--===============1911358387== +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Content-Disposition: inline + +_______________________________________________ +sqlite-dev mailing list +sqlite-dev@sqlite.org +http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-dev + +--===============1911358387==-- + diff --git a/lib/testdir/tmp/1220863087.12663.ignore b/lib/testdir/tmp/1220863087.12663.ignore new file mode 100644 index 0000000..588ace1 --- /dev/null +++ b/lib/testdir/tmp/1220863087.12663.ignore @@ -0,0 +1,98 @@ +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime +X-Spam-Level: +X-Spam-Status: No, score=-3.6 required=3.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW, + SPF_PASS autolearn=ham version=3.2.5 +X-Original-To: xxxx@localhost +Delivered-To: xxxx@localhost +Received: from mindcrime (localhost [127.0.0.1]) + by mail.xxxxsoftware.nl (Postfix) with ESMTP id D68E769CB5 + for ; Fri, 8 Aug 2008 20:56:25 +0300 (EEST) +Delivered-To: xxxx.klub@gmail.com +Received: from gmail-imap.l.google.com [72.14.221.111] + by mindcrime with IMAP (fetchmail-6.3.8) + for (single-drop); Fri, 08 Aug 2008 20:56:25 +0300 (EEST) +Received: by 10.142.237.21 with SMTP id k21cs71287wfh; Fri, 8 Aug 2008 + 07:40:46 -0700 (PDT) +Received: by 10.100.122.8 with SMTP id u8mr3824321anc.77.1218206446062; Fri, + 08 Aug 2008 07:40:46 -0700 (PDT) +Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) by mx.google.com + with ESMTP id d35si2718351and.38.2008.08.08.07.40.45; Fri, 08 Aug 2008 + 07:40:46 -0700 (PDT) +Received-SPF: pass (google.com: domain of + help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 + as permitted sender) client-ip=199.232.76.165; +Authentication-Results: mx.google.com; spf=pass (google.com: domain of + help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 + as permitted sender) + smtp.mail=help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Received: from localhost ([127.0.0.1]:47349 helo=lists.gnu.org) by + lists.gnu.org with esmtp (Exim 4.43) id 1KRT93-0006Po-A3 for + xxxx.klub@gmail.com; Fri, 08 Aug 2008 10:40:45 -0400 +Path: news.stanford.edu!headwall.stanford.edu!newshub.sdsu.edu!news-out.readnews.com!news-xxxfer.readnews.com!panix!not-for-mail +From: anon@example.com +Newsgroups: gnu.emacs.help +Date: Fri, 08 Aug 2008 10:07:30 -0400 +Organization: PANIX Public Access Internet and UNIX, NYC +Message-ID: +References: + + <9bc17528-8ea9-49f7-8e9d-07f5ede91415@p31g2000prf.googlegroups.com> + <200808062238.15634.juanma_bellon@yahoo.es> + +NNTP-Posting-Host: panix5.panix.com +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +X-Trace: reader1.panix.com 1218204439 22850 166.84.1.5 (8 Aug 2008 14:07:19 + GMT) +X-Complaints-To: abuse@panix.com +NNTP-Posting-Date: Fri, 8 Aug 2008 14:07:19 +0000 (UTC) +User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.2 (windows-nt) +Cancel-Lock: sha1:Ckkp5oJPIMuAVgEHGnS/9MkZsEs= +Xref: news.stanford.edu gnu.emacs.help:160963 +To: help-gnu-emacs@gnu.org +Subject: Re: basic question: going back to dired +X-BeenThere: help-gnu-emacs@gnu.org +X-Mailman-Version: 2.1.5 +Precedence: list +List-Id: Users list for the GNU Emacs text editor +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +Sender: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Errors-To: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Content-Length: 710 +Lines: 27 + +I seem to remember from my early school days it was a campaign slogan +for someone nick-named Kinderhook that went something like + +Old Kinderhook is OK + +- Chris + +"Juanma Barranquero" writes: + +> On Wed, Aug 6, 2008 at 22:38, Juanma wrote: +> +>> For all I know, it comes from "0 Knock-outs" (from USA civil war times, +>> IIRC), i.e., all went really well. +> +> See http://en.wikipedia.org/wiki/Okay#Etymology +> +> "0 knock-outs" is among the "Improbable or refuted etymologies". +> +> Juanma +> +> + +-- + (. .) + =ooO=(_)=Ooo===================================== + Chris McMahan | first_initiallastname@one.dot.net + ================================================= + diff --git a/lib/testdir2/Foo/cur/arto.eml b/lib/testdir2/Foo/cur/arto.eml new file mode 100644 index 0000000..ffa0526 --- /dev/null +++ b/lib/testdir2/Foo/cur/arto.eml @@ -0,0 +1,448 @@ +Return-Path: <> +X-Original-To: f00f@localhost +Delivered-To: f00f@localhost +Received: from puppet (puppet [127.0.0.1]) + by f00fmachines.nl (Postfix) with ESMTP id A534D39C7F1 + for ; Mon, 23 May 2011 20:30:05 +0300 (EEST) +Delivered-To: diggler@gmail.com +Received: from ew-in-f109.1e100.net [174.15.27.101] + by puppet with POP3 (fetchmail-6.3.18) + for (single-drop); Mon, 23 May 2011 20:30:05 +0300 (EEST) +Received: by 10.142.147.13 with SMTP id u13cs87252wfd; + Mon, 23 May 2011 01:54:10 -0700 (PDT) +Received: by 10.204.7.74 with SMTP id c10mr1984197bkc.104.1306140849326; + Mon, 23 May 2011 01:54:09 -0700 (PDT) +Received: from MTX4.mbn1.net (mtx4.mbn1.net [213.188.129.252]) + by mx.google.com with ESMTP id e6si18117551bkw.39.2011.05.23.01.54.07; + Mon, 23 May 2011 01:54:08 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of MTX4.mbn1.net designates 213.188.129.252 as permitted sender) client-ip=213.188.129.252; +Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of MTX4.mbn1.net designates 213.188.129.252 as permitted sender) smtp.mail= +Resent-From: +X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=192.168.10.123; +From: ArtOlive +To: "f00f@f00fmachines.nl" +Reply-To: +Date: Mon, 23 May 2011 10:53:45 +0200 +Subject: NIEUWSBRIEF ART OLIVE | juni exposite in galerie ArtOlive +MIME-Version: 1.0 +Content-Type: multipart/alternative; + boundary="_=aspNetEmail=_5ed4592191214c7a99bd7f6a3a0f077d" +X-Mailer: aspNetEmail ver 3.5.2.10 +X-Sender: 87.93.13.24 +X-RemoteIP: 87.93.13.24 +Originating-IP: 87.93.13.24 +X-MAILINGLIJST-ID: <10374608.109906.11909.2011523105345.MSGID@mailinglijst.nl> +Message-ID: <10374608.109906.11909.2011523105345.MSGID@mailinglijst.nl> +X-Authenticated-User: guest@mailinglijst.eu +X-STA-Metric: 0 (engine=030) +X-STA-NotSpam: geinformeerd vormen spec:usig:3.8.2 twee samen +X-STA-Spam: 2011 &bull • e-mailing subject:juni +X-BTI-AntiSpam: score:0,sta:0/030,dnsbl:passed,sw:passed,bsn:10/passed,spf:off,bsctr:passed/1,dk:off,pbmf:none,ipr:0/3,trusted:no,ts:no,bs:no,ubl:passed +X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply +Resent-Message-Id: <19740414233016.EB6835A132F5FCF4@MTX4.mbn1.net> +Resent-Date: Mon, 23 May 2011 10:54:07 +0200 (CEST) + +--_=aspNetEmail=_5ed4592191214c7a99bd7f6a3a0f077d +Content-Type: text/plain; charset="iso-8859-15" +Content-Transfer-Encoding: quoted-printable + +ART-O-NEWS; juni 2011 Westergasfabriekterrein Polonceaukade 17 10= +14 DA Amsterdam tel: 020-6758504 info@artolive.nl www.artolive.nlJuni= + expositie bij ArtOlive: Peter van den Akker en Marinel Vieleers + + +Zondag 5 juni + Elke maand vindt er in de galerie van ArtOlive een expositie plaats. We = +lichten enkele kunstenaars uit (die je misschien al kent van onze website= +), waarbij we een spannende mix van materiaal en techniek presenteren. Ti= +jdens de expositie staan we klaar om elke vraag over ons kunstaanbod te b= +eantwoorden.=20 + +De exposities zijn te bezoeken van maandag t/m vrijdag, tussen 10:00 en 1= +7:00 uur. De opening is altijd op de eerste zondag van de maand. Dit valt= + samen met de Sunday Market die elke maand op het Cultuurpark Westergasfa= +briek georganiseerd wordt. De Sunday Market is gratis te bezoeken en staa= +t vol met kunst, design, mode en heerlijke hapjes, en er hangt altijd een= + vrolijke sfeer. Een ideaal moment dus om in te haken en deze maand twee = +kunstenaars te presenteren: Peter van den Akker en Marinel Vieleers. + +We verwelkomen je graag op zondag 5 juni 2011, van 12:00 t/m 17:00 uur op= + de Polonceaukade 17 van het Cultuurpark Westergasfabriek in Amsterdam!=20= + + + + bekijk meer werk op www.artolive.nl... Peter van den Akker + + +"In mijn beelden en schilderijen staat het mensbeeld centraal; niet als i= +ndividu maar als universele gestalte, waarbij ik op transparante wijze ti= +jdsbeelden en gelaagdheid in het menselijke handelen naar voren breng. Ve= +rhoudingen tussen mensen, verschuivingen in wereldculturen en verandering= +en in techniek, architectuur, natuur en mensbeeld vormen mijn inspiratieb= +ronnen. Het zijn allemaal beelden en sferen die naast en met elkaar besta= +an. Mijn werkwijze omvat vele technieken in verschillende materialen: sch= +ilderijen, gemengde technieken op papier/collages, zeefdrukken, beelden i= +n cortenstaal, keramische objecten." + +Peter van den Akker exposeert regelmatig in binnen- en buitenland bij gal= +erie=EBn en musea en is in verschillende kunstinstellingen en bedrijfscol= +lecties opgenomen. + + + lees meer over Peter... Marinel Vieleers + + +Marinel Vieleers probeert het menselijke in de bouwwerken - en ook vaak i= +ets van het karakter van de bouwer of bewoner - te laten zien. Het zijn m= +aar subtiele details die dat alles weergeven. + +De 'tand des tijds' of invloed van mensen op de gebouwen spelen vaak mee = +in het werk. Koper, cement, lood en andere materialen worden in haar nieu= +we werk gebruikt. Op deze manier kan ze gemakkelijker improviseren en nog= + directer op haar gevoel afgaan. + +Marinel is gefascineerd door de schoonheid van het imperfecte. De gelaagd= +heid van ouderdom, het verval. De imperfectie die ontstaat door toevallig= +e omstandigheden maakt een huis, een muur, een schutting, hout of steen b= +oeiend. Het is doorleefd en het toont een stukje van zijn geschiedenis. + + + lees meer over Marinel... =20 +ZONDAG 5 MEI - Juni expositie in de galerie van ArtOlive met Marinel Viel= +eers en Peter van den Akker + +Opening op zondag 5 mei, tijdens de Sunday Market op het Cultuurpark West= +ergasfabriek in Amsterdam. Je bent van harte uitgenodigd om tussen 12:00 = +en 17:00 uur langs te komen! + +Daarna is de expositie te zien op werkdagen (ma - vrij) tussen 10:00 en 1= +7:00. De expositie duurt tot 24 juni 2011. + wil je niet langer door artolive ge=EFnformeerd worden? Klik dan hier om= + je af te melden.=20 + kreeg je dit mailtje doorgestuurd en wil je voortaan zelf ook graag de n= +ieuwsbrief ontvangen?=20 + klik dan hier om je aan te melden.=20 + +Deze e-mailing is verzorgd met MailingLijst + +--_=aspNetEmail=_5ed4592191214c7a99bd7f6a3a0f077d +Content-Type: text/html; charset="iso-8859-15" +Content-Transfer-Encoding: quoted-printable + + + + + + Artolive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
3D"artolive"
ART-O-NEWS • juni 2011 +
Westergasfabriekterrein   Polonceau= +kade 17 1014 DA Amsterdam   tel: 020-6758504  info@artolive.nl<= +/a>  www.artolive.nl
+ + + + + + + +
Juni= + expositie bij ArtOlive: Peter van den Akker en Marinel Vieleers +

Zondag 5 juni
+ Elke maand vindt er in de galerie van Art= +Olive een expositie plaats. We lichten enkele kunstenaars uit (die je mis= +schien al kent van onze website), waarbij we een spannende mix van materi= +aal en techniek presenteren. Tijdens de expositie staan we klaar om elke = +vraag over ons kunstaanbod te beantwoorden.

+

De exposities zijn te bezoeken van maa= +ndag t/m vrijdag, tussen 10:00 en 17:00 uur. De opening is altijd op de e= +erste zondag van de maand. Dit valt samen met de Sunday Market die elke m= +aand op het Cultuurpark Westergasfabriek georganiseerd wordt. De Sunday M= +arket is gratis te bezoeken en staat vol met kunst, design, mode en heerl= +ijke hapjes, en er hangt altijd een vrolijke sfeer. Een ideaal moment dus= + om in te haken en deze maand twee kunstenaars te presenteren: Peter van = +den Akker en Marinel Vieleers.

+

We verwelkomen je graag op zondag 5 ju= +ni 2011, van 12:00 t/m 17:00 uur op de Polonceaukade 17 van het Cultuurpa= +rk Westergasfabriek in Amsterdam!

+
+

3D""  = +bekijk= + meer werk op www.artolive.nl...   

+
+
+ + + + = + + + + + + +
3D""
+ + + + + + + + + + +
<= +a target=3D"_blank" href=3D"http://www.mailinglijst.eu/redirect.aspx?l=3D= +154043&a=3D10374608&t=3DH"> <= +/td> + Peter van den Akker
+

"In mijn beelden en schild= +erijen staat het mensbeeld centraal; niet als individu maar als universel= +e gestalte, waarbij ik op transparante wijze tijdsbeelden en gelaagdheid = +in het menselijke handelen naar voren breng. Verhoudingen tussen mensen, = +verschuivingen in wereldculturen en veranderingen in techniek, architectu= +ur, natuur en mensbeeld vormen mijn inspiratiebronnen. Het zijn allemaal = +beelden en sferen die naast en met elkaar bestaan. Mijn werkwijze omvat v= +ele technieken in verschillende materialen: schilderijen, gemengde techni= +eken op papier/collages, zeefdrukken, beelden in cortenstaal, keramische = +objecten.”

+

Peter van den Akker expose= +ert regelmatig in binnen- en buitenland bij galerieën en musea en is= + in verschillende kunstinstellingen en bedrijfscollecties opgenomen.

+
+

3D""  = +lees meer over Peter...   

+
= + Marinel Vieleers
+

Marinel Vieleers probeert = +het menselijke in de bouwwerken - en ook vaak iets van het karakter van d= +e bouwer of bewoner - te laten zien. Het zijn maar subtiele details die d= +at alles weergeven.

+

De ‘tand des tijds&r= +squo; of invloed van mensen op de gebouwen spelen vaak mee in het werk. K= +oper, cement, lood en andere materialen worden in haar nieuwe werk gebrui= +kt. Op deze manier kan ze gemakkelijker improviseren en nog directer op h= +aar gevoel afgaan.

+

Marinel is gefascineerd do= +or de schoonheid van het imperfecte. De gelaagdheid van ouderdom, het ver= +val. De imperfectie die ontstaat door toevallige omstandigheden maakt een= + huis, een muur, een schutting, hout of steen boeiend. Het is doorleefd e= +n het toont een stukje van zijn geschiedenis.

+
+

3D""  = +lees meer ov= +er Marinel...   

+
+
+
+ + + + + + + + + +
3D""
+ + + + + + + + + + + +
+
+
+ + + + + + + + + +
3D""
+ + + + + + + + + + + + + + + +

+
ZONDAG 5 MEI - Juni expositie in de galerie van ArtOlive met = +Marinel Vieleers en Peter van den Akker
+

+
Opening op zondag 5 mei, = +tijdens de Sunday Market op het Cultuurpark Westergasfabriek in Amsterdam= +. Je bent van harte uitgenodigd om tussen 12:00 en 17:00 uur langs te kom= +en!
+

+
Daarna is de expositie te zien op werkdagen (ma - vrij= +) tussen 10:00 en 17:00. De expositie duurt tot 24 juni 2011.
+
+
+
3D"Kunst wil je niet langer door artolive geïnformeerd worden? Klik= + dan hier om je af te melden.
+ kreeg je dit mailtje doorgestuurd en wil je voortaan = +zelf ook graag de nieuwsbrief ontvangen?
+ klik dan hier om= + je aan te melden.
+

<= +HR SIZE=3D1 STYLE=3D"COLOR:#d3d3d3" SIZE=3D1>Deze e-mailing is verzorgd m= +et MailingLijst

+ + +--_=aspNetEmail=_5ed4592191214c7a99bd7f6a3a0f077d-- diff --git a/lib/testdir2/Foo/cur/fraiche.eml b/lib/testdir2/Foo/cur/fraiche.eml new file mode 100644 index 0000000..c0bf442 --- /dev/null +++ b/lib/testdir2/Foo/cur/fraiche.eml @@ -0,0 +1,10 @@ +From: Sender +To: Recip +Subject: search accents +Date: 2012-12-08 00:48 +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: 8bit + +line 1: Глокая куздра штеко будланула бокра и курдячит бокрёнка +line 2: crème fraîche diff --git a/lib/testdir2/Foo/cur/mail5 b/lib/testdir2/Foo/cur/mail5 new file mode 100644 index 0000000..b72195d --- /dev/null +++ b/lib/testdir2/Foo/cur/mail5 @@ -0,0 +1,625 @@ +From: Sitting Bull +To: George Custer +Subject: pics for you +Mail-Reply-To: djcb@djcbsoftware.nl +User-Agent: Hunkpapa/2.15.9 (Almost Unreal) +Message-Id: CAHSaMxZ9rk5ASjqsbXizjTQuSk583=M6TORHz=bfogtmbGGs5A@mail.gmail.com +Fcc: .sent +MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") +Content-Type: multipart/mixed; + boundary="Multipart_Sun_Oct_17_10:37:40_2010-1" + +--Multipart_Sun_Oct_17_10:37:40_2010-1 +Content-Type: text/plain; charset=US-ASCII + +Dude! Here are some pics! + + +--Multipart_Sun_Oct_17_10:37:40_2010-1 +Content-Type: image/jpeg +Content-Disposition: inline; filename="sittingbull.jpg" +Content-Transfer-Encoding: base64 + +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 +KD//2Q== + + + +--Multipart_Sun_Oct_17_10:37:40_2010-1 +Content-Type: image/jpeg +Content-Disposition: inline; filename="custer.jpg" +Content-Transfer-Encoding: base64 + +/9j/4AAQSkZJRgABAQAAAQABAAD/4Q1kRXhpZgAASUkqAAgAAAAIABIBCQABAAAAAQAAABoBCQAB +AAAAyAAAABsBBQABAAAAbgAAACgBAwABAAAAAgAAADEBAgAOAAAAdgAAADIBAgAUAAAAhAAAABMC +CQABAAAAAQAAAGmHBAABAAAAmAAAAOYAAADIAAAAAQAAAGd0aHVtYiAyLjExLjMAMjAwNTowMTox +MCAwMDo1NzowMwAGAACQBwAEAAAAMDIyMQGRBwAEAAAAAQIDAACgBwAEAAAAMDEwMAGgAwABAAAA +//8AAAKgCQABAAAAyAAAAAOgCQABAAAA9gAAAAAAAAAGAAMBAwABAAAABgAAABoBCQABAAAASAAA +ABsBCQABAAAASAAAACgBCQABAAAAAgAAAAECBAABAAAANAEAAAICBAABAAAAJwwAAAAAAAD/2P/g +ABBKRklGAAEBAAABAAEAAP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAk +LicgIiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIy +MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAIAAaAMBIgACEQED +EQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0B +AgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpD +REVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmq +srO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEB +AQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFR +B2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVW +V1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrC +w8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/ANNRzUiIfSlR +DmrUUfrXOajEiz2qZYPap0jqlrOr2+i2RkkZDMR+7jLYJPqfanYCd4OOlQGe2ibbLcQo/ozgGvPL +vxRqE6kSXsj+yfu1/JeT+dYsl55m7JUZ6kD+vWiwrnsAlgfG2eI/RxUhjrxlLhgMLKcdua0YPE2q +2mDHfSMB2c7h+tFgueqeVimmPiuO034hKWEepW4APHmw9vqK7G3ube9tlntZUliboymiwXECCgpU +oSnGPNIZEqgUVKIz3opAVUXDVajFV4/vVT8R6yNC0SW6THnsfLhB/vHv+AyaaApeKPF0WjK1nZ7Z +L0jk9RF9ff2rzC71Ge7naaeZpZWOSzHNVZriSaRndyzsdzMTkk1GFLHABP0qhEhnc5xWjpmg32q5 +8oY9M96hs7DzHG4MBjJJGK9j8HW1ta6ckqqHVunHQ0BY8wl8H6hDGWOcjttNYtxbzWxIcHivoXWN +X0nS7YzXh5I+WMDJNeY+KTb3umHUotOlhgkfYjkfqaLhY4ESZrb8Oa/caLqCMrFrZyBLH2I9fqKx +Y4mkcIilmJwABkk16R4V8BmDy9Q1dfnGGjtj292/woCx2qjIB9aftp+MUvFSMYFopxopDKCDDdK5 +L4i2V9dWdlJb28kkEJcylBnaTjBP68116ctWjanFUhHzpit7SLa0t1W7u5lCk4AxmvZbzwvoGoOZ +rnS7dpDyXUbCfrjFeZ3WkW0OuXEcMMbQK52RljtA9jTESWNvDqExntAJDu2YEf3R6/413Xhq7itb +IW88MgKMct2zmvN47h9C1WCS1uzGGbbIqnPynsexFelLMloUMjF4pVBEh75oAvX50q7+RIXknkwG +Pt6c9q0bu00e/wBEk0m/kht4pE2KrOAwPYjPcVmWlza2TSXTbWwMgep9K5zWdavNSmISzS4bOMjA +x6AUhm3pHhfRNFVZLG3EkmOLiQ72P0PQfhWnITUVjJNLYQPOmyUoN6+hxUjZzQAwr7UgWpKCMUgG +7RRRzmikxlGNavwDiqiDB6VegGQOKpCJygkhaM9GBBrzHxFp50+5la8tnO4DbIg6LnqP0r0S/v5L +K1MtvaS3bZKbYcHDDqD7+3WvONT1u+1W/jbUSVtY3yYEGAB396YjCtLQXt1mOBhAjZDPyT7V3GkX +bJbtp92pe1I+V8ZMf19qzta8T6dounx6dplhbySkbi/U4PIJP9K4y88Q6reYMk2yPOQiKFU/h3oA +73VLC6trFrmCVJ7dTn5X6fhWLo3ih31i2N3Bi1iYqWjHTPc+uKg0zxCb+2NrNaHj75hOFI9wKs6j +FF9hf7CotmjAZWTj659aAPUQVdA6EMpGQR0IpjCuJ8GeKVNtJYXshd4xuiKLyw7jH9K7SK4guGdI +nBePG9Dwy5GRkHkUDFA5HWnMBikIwaKkBo64FFAPNFIZVQVi+IvEk+mSJa2OVnxueQKDt9AM1uov +NedeIJkufENyySEAEIMHjgY/mKpCZaOri/hjg1G3jnhRtylB5LofVWXHP1zWpqF1pt1pg8+4jmlS +PbA6o32lj/02ydpGOMjr+lcsXliHOJF7jHNQSyAYmiPyA5I9DTEQnTVimMwywHOD6VoafJHp13Hc +pZW92gJIhnGUORiljcSJnqDUMTBQ0fdf5UAaFhANDj1STUbP7PJN+9EQHHlnJUKPTJNSW4G4jqCB +1qKKzu0EeoXV0k0N0CqiSXc4C5HI9OaSNsXCIvCg4oAzNbj1O01iDVXhS3km+dPKUKpHTOB61b0j +xNLYayl3JGBE6COWNOAQOhFMv7QGCa7N5E489kFuZCXTHOcdhWMGBJJ6CgD3BJEliSVTlXAZT7Gn +AA1xvgnXJrxX0+5fd5SAxEjnb0wf0rshjFSMTABopwxRSGVgDn615TNCTNMrctHIwP516xzuGK8z +1FBa+I7yJgNrynH48/1qkJleOZo0GMstMlDy5MKxsx6g8GpGUxSnb9084p5RZUyuFb06UxGfazPE +WicFWB4B9Kk3fv8Ad68VDOri4BaNt443D+tEchKsfegDQsVQy3DjJcR/d7dR+Va9lDGLR/NkLOzE +gAenTn6iudsJtmoMeoaMg+3IrbtpJVjXa+O/NAGK4Q3M5bG7ewz+NZqAZcdlY5q3bxXOrasba0QN +LNIxUFgo7nqa1PCPhttZ1a6S7Vha2rnz9p5Yj+EGgDLsZ7i0nS6t5WikU5BHp6V61o2pxatp8c6M +vmYxIgP3W9KI/Bukyu0stmgZkwkSsVWMepx1NcOss/h3Wp47K4WRUfa+4cSD6UmM9IGM0VQ0zVrf +VLbzImxIB88Z6r/9aipAn3ZNcB41tGj1gzKMGVFcH3HH9K7pDzXJeNCrTRuzHem1AueMNuOfzX9K +pAznLa7juUCSEJMvr3qZwydRx6isi4ty3zJw1TWksjrs3kOOoJpiL0twwXlCwHoKxri6WFj8pG/k +A1fe6vIODtKmu1+Gc9vcazNHeRxyZh+RXjVuc8nJ5oA4zwxp91rmpSW1nGGnZMZbgAZ5JP5V6Cvw +213Jb7TYgbcKPMbr/wB816pGsESARpGi+iqAKT7VCPlMi5+tAHisPwc8SLJk39hH/tpI+R/47XWe +FvBeqeGtHnhlENxO8hlYRSH5vQDIHP1xXoSzow4ZT9DSvIO1AHiepeMNUWaWCBPsgDFWDrl8jsc9 +PpXMajqdxe3BuLt90zAAsABkDp0rq/ixpTWeuwanbDC3kZDr/trwT+IIrziS6uUcJcqGWgDpPDOo +pb+ILctJxITGQffp+uKKyNFtjc67YxqdyNMrfgDk/wAqKljR64vB5rK8Q6DaapCtxI0qXC7I0Kth +eXAGR3+8fzrTDYNQavKRol465DpEZFI6gryP1FJMbPMEcqxRhytNkwrLInDDriqST/ay3z4lB3A+ +tSrIWQq3DjqDVEl9h9oiDIC2e1V4H1KxvEuIGe2KHPmZxtqkbuazYtC5FVJ767vG/eyEr6dKAPQr +P4k6tZRHcy3KKeGlXJI98VuQ+OdM1EB3nubN3IASWM4Y+gIzXksN4YcB49yjsank1L7Q4ZvlVfuj +3oC57To2vQX8jJBdJujO0hnCnP0ODXWxC6dBuLL6ZFeP2/izwp4hsIodejmtNREflvdRICjnszY5 +OepGOtcvc6vqeh3Ij0jXbnyifl8mZth+maLDPU/i9Cf+EOt53YB4rtcHvypBx+leILdgDbICwrqL +7TvHPiVo7fUTdTxp8y+dIAg9+uM/rXS6D8PbDTQs+pst5cjkJ/yzU/T+L8fyp3AyfAmiXHn/ANrz +I0duqkQhurk8Z+mM0V6BI+FCqAFHAA6CiobA/9kA/+EMRWh0dHA6Ly9ucy5hZG9iZS5jb20veGFw +LzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQi +Pz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUg +NC40LjAtRXhpdjIiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5 +LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgog +ICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgeG1sbnM6dGlm +Zj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczpleGlmPSJodHRwOi8v +bnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUu +Y29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50 +cy8xLjEvIgogICB4bXA6Q3JlYXRlRGF0ZT0iMjAwNS0wMS0xMFQwMDowNzoyNyswMTowMCIKICAg +eG1wOk1vZGlmeURhdGU9IjIwMDUtMDEtMTBUMDA6NTc6MDMrMDE6MDAiCiAgIHhtcDpNZXRhZGF0 +YURhdGU9IjIwMDUtMDEtMTBUMDA6NTc6MDMrMDE6MDAiCiAgIHhtcDpDcmVhdG9yVG9vbD0iQWRv +YmUgUGhvdG9zaG9wIENTIFdpbmRvd3MiCiAgIHRpZmY6T3JpZW50YXRpb249IjEiCiAgIHRpZmY6 +WFJlc29sdXRpb249IjIwMC8xIgogICB0aWZmOllSZXNvbHV0aW9uPSIyMDAvMSIKICAgdGlmZjpS +ZXNvbHV0aW9uVW5pdD0iMiIKICAgZXhpZjpDb2xvclNwYWNlPSI0Mjk0OTY3Mjk1IgogICBleGlm +OlBpeGVsWERpbWVuc2lvbj0iNzU1IgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iOTMwIgogICB4 +bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6Zjg2ZTcwZTQtNjI5OC0xMWQ5 +LTllM2YtZDQyZjM0NjM5ZGJiIgogICB4bXBNTTpJbnN0YW5jZUlEPSJ1dWlkOmY4NmU3MGU1LTYy +OTgtMTFkOS05ZTNmLWQ0MmYzNDYzOWRiYiIKICAgZGM6Zm9ybWF0PSJpbWFnZS9qcGVnIi8+CiA8 +L3JkZjpSREY+CjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAog +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAg +ICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz7/2wBDAAUDBAQEAwUEBAQFBQUG +BwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUF +BQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e +Hh4eHh7/wAARCAD2AMgDASIAAhEBAxEB/8QAHQAAAAcBAQEAAAAAAAAAAAAAAAIDBAUGBwEICf/E +AEIQAAIBAwIEBAQDBgUBCAMBAAECAwAEEQUhBhIxQQcTUWEicYGRFDKhI0JSscHRCBVicoLwFiQl +M5KissJDU9Lh/8QAGQEBAQEBAQEAAAAAAAAAAAAAAAECAwQF/8QAGhEBAQEBAQEBAAAAAAAAAAAA +AAERAjEhEv/aAAwDAQACEQMRAD8Am8Hl60dEGN+tAbnalEBIr5+PUIoGcmllXPSgkW9LxxntVBET +2pVY/Y0tFEe+KcpFRDYRDHSjrD/pp4sdHWIUwMHhwOlJcpXr0qVeEEd6aXCxxRtLK6xou7MxwB8z +TDSSpjelAtQFxxvwjaSmGXW7dnH/AOtWkH3UEUeLjjhGXATV0z7wyD/61cNTTDbG1AKcdKjBxXww +RznWbUA9Mkj+lSem3+n6lE0mnXtvdopwzQyBgp9DjpTDXGQ0mY6fFD6Vzy8DpTDTMR7UOT3p0U9q +KF3oaasm1F5PSnTr3pMAb1FJrGwGRRuX1o64xvRtqYG5X2oyp7UpgV1agCKAQSKFKZHLQozUEoNL +Rj3oBd+lLxJsKrTsaEmnccW+d65Ehz0pzGp9KuI5HHv0pdU7Yrsa+1LqmSBitSAsabdKrXiLxfb8 +IabG6xR3V/O4EVsXweXuxx2/maX4w410PhmJknlWe7A2gRhkf7j2/nWCaxxK9/qs+ohea6mbJuJd +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 + +Cheerio! + +--Multipart_Sun_Oct_17_10:37:40_2010-1-- diff --git a/lib/testdir2/Foo/new/.noindex b/lib/testdir2/Foo/new/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir2/Foo/tmp/.noindex b/lib/testdir2/Foo/tmp/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir2/bar/cur/181736.eml b/lib/testdir2/bar/cur/181736.eml new file mode 100644 index 0000000..56255c4 --- /dev/null +++ b/lib/testdir2/bar/cur/181736.eml @@ -0,0 +1,42 @@ +Path: uutiset.elisa.fi!feeder2.news.elisa.fi!feeder.erje.net!newsfeed.kamp.net!newsfeed0.kamp.net!nx02.iad01.newshosting.com!newshosting.com!post01.iad!not-for-mail +X-newsreader: xrn 9.03-beta-14-64bit +Sender: jimbo@lews (Jimbo Foobarcuux) +From: jimbo@slp53.sl.home (Jimbo Foobarcuux) +Reply-To: slp53@pacbell.net +Subject: Re: Are writes "atomic" to readers of the file? +Newsgroups: comp.unix.programmer +References: <87hbblwelr.fsf@sapphire.mobileactivedefense.com> <8762s0jreh.fsf@sapphire.mobileactivedefense.com> <87hbbjc5jt.fsf@sapphire.mobileactivedefense.com> <8ioh48-8mu.ln1@leafnode-msgid.gclare.org.uk> +Organization: UseNetServer - www.usenetserver.com +X-Complaints-To: abuse@usenetserver.com +Message-ID: +Date: 08 Mar 2011 17:04:20 GMT +Lines: 27 +Xref: uutiset.elisa.fi comp.unix.programmer:181736 + +John Denver writes: +>Eric the Red wrote: +> +>>> There _IS_ a requirement that all reads and writes to regular files +>>> be atomic. There is also an ordering guarantee. Any implementation +>>> that doesn't provide both atomicity and ordering guarantees is broken. +>> +>> But where is it specified? +> +>The place where it is stated most explicitly is in XSH7 2.9.7 +>Thread Interactions with Regular File Operations: +> +> All of the following functions shall be atomic with respect to each +> other in the effects specified in POSIX.1-2008 when they operate on +> regular files or symbolic links: +> +> [List of functions that includes read() and write()] +> +> If two threads each call one of these functions, each call shall +> either see all of the specified effects of the other call, or none +> of them. +> + +And, for the purposes of this paragraph, the two threads need not be +part of the same process. + +jimbo diff --git a/lib/testdir2/bar/cur/mail1 b/lib/testdir2/bar/cur/mail1 new file mode 100644 index 0000000..56808c6 --- /dev/null +++ b/lib/testdir2/bar/cur/mail1 @@ -0,0 +1,38 @@ +Date: Thu, 31 Jul 2008 14:57:25 -0400 +From: "John Milton" +Subject: Fere libenter homines id quod volunt credunt +To: "Julius Caesar" +Message-id: <3BE9E6535E3029448670913581E7A1A20D852173@emss35m06.us.lmco.com> +MIME-version: 1.0 +x-label: Paradise losT +X-Keywords: milton,john +Content-type: text/plain; charset=us-ascii +Content-transfer-encoding: 7BIT +Precedence: high + +OF Mans First Disobedience, and the Fruit +Of that Forbidden Tree, whose mortal tast +Brought Death into the World, and all our woe, +With loss of Eden, till one greater Man +Restore us, and regain the blissful Seat, [ 5 ] +Sing Heav'nly Muse,that on the secret top +Of Oreb, or of Sinai, didst inspire +That Shepherd, who first taught the chosen Seed, +In the Beginning how the Heav'ns and Earth +Rose out of Chaos: Or if Sion Hill [ 10 ] +Delight thee more, and Siloa's Brook that flow'd +Fast by the Oracle of God; I thence +Invoke thy aid to my adventrous Song, +That with no middle flight intends to soar +Above th' Aonian Mount, while it pursues [ 15 ] +Things unattempted yet in Prose or Rhime. +And chiefly Thou O Spirit, that dost prefer +Before all Temples th' upright heart and pure, +Instruct me, for Thou know'st; Thou from the first +Wast present, and with mighty wings outspread [ 20 ] +Dove-like satst brooding on the vast Abyss +And mad'st it pregnant: What in me is dark +Illumin, what is low raise and support; +That to the highth of this great Argument +I may assert Eternal Providence, [ 25 ] +And justifie the wayes of God to men. diff --git a/lib/testdir2/bar/cur/mail2 b/lib/testdir2/bar/cur/mail2 new file mode 100644 index 0000000..3799f30 --- /dev/null +++ b/lib/testdir2/bar/cur/mail2 @@ -0,0 +1,14 @@ +Date: Thu, 31 Jul 2008 14:57:25 -0400 +From: "Socrates" +Subject: cool stuff +To: "Alcibiades" +Message-id: <3BE9E6535E0D852173@emss35m06.us.lmco.com> +MIME-version: 1.0 +Content-type: text/plain; charset=us-ascii +Content-transfer-encoding: 7BIT +Precedence: high + +The hour of departure has arrived, and we go our ways—I to die, and you to +live. Which is better God only knows. + +http-emacs diff --git a/lib/testdir2/bar/cur/mail3 b/lib/testdir2/bar/cur/mail3 new file mode 100644 index 0000000..646365e --- /dev/null +++ b/lib/testdir2/bar/cur/mail3 @@ -0,0 +1,34 @@ +From: Napoleon Bonaparte +To: Edmond =?UTF-8?B?RGFudMOocw==?= +Subject: rock on dude +User-Agent: Wanderlust/2.15.9 (Almost Unreal) Emacs/24.0 Mule/6.0 (HANACHIRUSATO) +Fcc: .sent +MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Le 24 février 1815, la vigie de Notre-Dame de la Garde signala le trois-mâts +le Pharaon, venant de Smyrne, Trieste et Naples. + +Comme d'habitude, un pilote côtier partit aussitôt du port, rasa le château +d'If, et alla aborder le navire entre le cap de Morgion et l'île de Rion. + +Aussitôt, comme d'habitude encore, la plate-forme du fort Saint-Jean s'était +couverte de curieux; car c'est toujours une grande affaire à Marseille que +l'arrivée d'un bâtiment, surtout quand ce bâtiment, comme le Pharaon, a été +construit, gréé, arrimé sur les chantiers de la vieille Phocée, et appartient +à un armateur de la ville. + +Cependant ce bâtiment s'avançait; il avait heureusement franchi le détroit que +quelque secousse volcanique a creusé entre l'île de Calasareigne et l'île de +Jaros; il avait doublé Pomègue, et il s'avançait sous ses trois huniers, son +grand foc et sa brigantine, mais si lentement et d'une allure si triste, que +les curieux, avec cet instinct qui pressent un malheur, se demandaient quel +accident pouvait être arrivé à bord. Néanmoins les experts en navigation +reconnaissaient que si un accident était arrivé, ce ne pouvait être au +bâtiment lui-même; car il s'avançait dans toutes les conditions d'un navire +parfaitement gouverné: son ancre était en mouillage, ses haubans de beaupré +décrochés; et près du pilote, qui s'apprêtait à diriger le Pharaon par +l'étroite entrée du port de Marseille, était un jeune homme au geste rapide et +à l'œil actif, qui surveillait chaque mouvement du navire et répétait chaque +ordre du pilote. diff --git a/lib/testdir2/bar/cur/mail4 b/lib/testdir2/bar/cur/mail4 new file mode 100644 index 0000000..4d21a48 --- /dev/null +++ b/lib/testdir2/bar/cur/mail4 @@ -0,0 +1,29 @@ +Return-Path: +Delivered-To: foo@example.com +Received: from [128.88.204.56] by freemailng0304.web.de with HTTP; + Mon, 07 May 2005 00:27:52 +0200 +Date: Mon, 07 May 2005 00:27:52 +0200 +Message-Id: <293847329847@web.de> +MIME-Version: 1.0 +From: =?iso-8859-1?Q? "=F6tzi" ?= +To: foo@example.com +Subject: =?iso-8859-1?Q?Re:=20der=20b=E4r=20und=20das=20m=E4dchen?= +Precedence: fm-user +Organization: http://freemail.web.de/ +Content-Type: text/plain; charset="iso-8859-1" +Content-Transfer-Encoding: 8bit +X-MIME-Autoconverted: from quoted-printable to 8bit by mailhost6.ladot.com id j48MScQ30791 +X-Label: \backslash +X-UIDL: 93h!!\i + +123 diff --git a/lib/testdir2/bar/cur/mail6 b/lib/testdir2/bar/cur/mail6 new file mode 100644 index 0000000..c9b799b --- /dev/null +++ b/lib/testdir2/bar/cur/mail6 @@ -0,0 +1,18 @@ +Date: Thu, 31 Jul 2008 14:57:25 -0400 +From: "Geoff Tate" +Subject: eyes of a stranger +To: "Enrico Fermi" +Message-id: <3BE9E6535E302944823E7A1A20D852173@msg.id> +MIME-version: 1.0 +X-label: @NextActions operation:mindcrime Queensrÿche +Content-type: text/plain; charset=us-ascii +Content-transfer-encoding: 7BIT +Precedence: high + +And I raise my head and stare +Into the eyes of a stranger +I've always known that the mirror never lies +People always turn away +From the eyes of a stranger +Afraid to know what +Lies behind the stare diff --git a/lib/testdir2/bar/new/.noindex b/lib/testdir2/bar/new/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir2/bar/tmp/.noindex b/lib/testdir2/bar/tmp/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir2/wom_bat/cur/atomic b/lib/testdir2/wom_bat/cur/atomic new file mode 100644 index 0000000..c3c6792 --- /dev/null +++ b/lib/testdir2/wom_bat/cur/atomic @@ -0,0 +1,20 @@ +Date: Sat, 12 Nov 2011 12:06:23 -0400 +From: "Richard P. Feynman" +Subject: atoms +To: "Democritus" +Message-id: <3BE9E6535E302944823E7A1A20D852173@msg.id> +MIME-version: 1.0 +Content-type: text/plain; charset=us-ascii +Content-transfer-encoding: 7BIT +Precedence: high + +If, in some cataclysm, all scientific knowledge were to be destroyed, +and only one sentence passed on to the next generation of creatures, +what statement would contain the most information in the fewest words? +I believe it is the atomic hypothesis (or atomic fact, or whatever you +wish to call it) that all things are made of atoms — little particles +that move around in perpetual motion, attracting each other when they +are a little distance apart, but repelling upon being squeezed into +one another. In that one sentence you will see an enormous amount of +information about the world, if just a little imagination and thinking +are applied. diff --git a/lib/testdir2/wom_bat/cur/rfc822.1 b/lib/testdir2/wom_bat/cur/rfc822.1 new file mode 100644 index 0000000..71c3107 --- /dev/null +++ b/lib/testdir2/wom_bat/cur/rfc822.1 @@ -0,0 +1,44 @@ +Return-Path: +Subject: Fwd: rfc822 +From: foobar +To: martin +Content-Type: multipart/mixed; boundary="=-XHhVx/BCC6tJB87HLPqF" +Message-Id: <1077300332.871.27.camel@example.com> +Mime-Version: 1.0 +X-Mailer: Ximian Evolution 1.4.5 +Date: Fri, 20 Feb 2004 19:05:33 +0100 + +--=-XHhVx/BCC6tJB87HLPqF +Content-Type: text/plain +Content-Transfer-Encoding: 7bit + +Hello world, forwarding some RFC822 message + +--=-XHhVx/BCC6tJB87HLPqF +Content-Disposition: inline +Content-Type: message/rfc822 + +Return-Path: +Message-ID: <9A01B19D0D605D478E8B72E1367C66340141B9C5@example.com> +From: frob@example.com +To: foo@example.com +Subject: hopjesvla +Date: Sat, 13 Dec 2003 19:35:56 +0100 +MIME-Version: 1.0 +Content-Type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: 7bit + +The ship drew on and had safely passed the strait, which some volcanic shock +has made between the Calasareigne and Jaros islands; had doubled Pomegue, and +approached the harbor under topsails, jib, and spanker, but so slowly and +sedately that the idlers, with that instinct which is the forerunner of evil, +asked one another what misfortune could have happened on board. However, those +experienced in navigation saw plainly that if any accident had occurred, it was +not to the vessel herself, for she bore down with all the evidence of being +skilfully handled, the anchor a-cockbill, the jib-boom guys already eased off, +and standing by the side of the pilot, who was steering the Pharaon towards the +narrow entrance of the inner port, was a young man, who, with activity and +vigilant eye, watched every motion of the ship, and repeated each direction of +the pilot. + +--=-XHhVx/BCC6tJB87HLPqF-- diff --git a/lib/testdir2/wom_bat/cur/rfc822.2 b/lib/testdir2/wom_bat/cur/rfc822.2 new file mode 100644 index 0000000..316fa3f --- /dev/null +++ b/lib/testdir2/wom_bat/cur/rfc822.2 @@ -0,0 +1,44 @@ +From: dwarf@siblings.net +To: root@eruditorum.org +Subject: Fwd: test abc +References: <8639ddr9wu.fsf@cthulhu.djcbsoftware> +User-agent: mu 0.98pre; emacs 24.0.91.9 +Date: Thu, 24 Nov 2011 14:24:00 +0200 +Message-ID: <861usxr9nj.fsf@cthulhu.djcbsoftware> +Content-Type: multipart/mixed; boundary="=-=-=" +MIME-Version: 1.0 + +--=-=-= +Content-Type: text/plain + +Saw the website. Am willing to stipulate that you are not RIST 9E03. Suspect +that you are the Dentist, who yearns for honest exchange of views. Anonymous, +digitally signed e-mail is the only safe vehicle for same. + +If you want me to believe you are not the Dentist, provide plausible +explanation for your question regarding why we are building the Crypt. + +Yours truly, + +--=-=-= +Content-Type: message/rfc822 +Content-Disposition: inline; filename= + "1322137188_3.11919.foo:2,S" +Content-Description: rfc822 + +From: dwarf@siblings.net +To: root@eruditorum.org +Subject: test abc +User-agent: mu 0.98pre; emacs 24.0.91.9 +Date: Thu, 24 Nov 2011 14:18:25 +0200 +Message-ID: <8639ddr9wu.fsf@cthulhu.djcbsoftware> +Content-Type: text/plain +MIME-Version: 1.0 + +As I stepped on this unknown middle-aged Filipina's feet during an ill-advised +ballroom dancing foray, she leaned close to me and uttered some latitude and +longitude figures with a conspicuously large number of significant digits of +precision, implying a maximum positional error on the order of the size of a +dinner plate. Gosh, was I ever curious! + +--=-=-=-- diff --git a/lib/testdir3/cycle/cur/cycle0 b/lib/testdir3/cycle/cur/cycle0 new file mode 100644 index 0000000..67c08ee --- /dev/null +++ b/lib/testdir3/cycle/cur/cycle0 @@ -0,0 +1,7 @@ +From: foo@example.com +To: bar@example.com +Subject: cycle0 +Message-Id: +Date: Tue, 21 Jun 2011 11:00 +0000 + +def diff --git a/lib/testdir3/cycle/cur/cycle0.0 b/lib/testdir3/cycle/cur/cycle0.0 new file mode 100644 index 0000000..3222a2c --- /dev/null +++ b/lib/testdir3/cycle/cur/cycle0.0 @@ -0,0 +1,8 @@ +From: foo@example.com +To: bar@example.com +Subject: cycle0.0 +Message-Id: +References: +Date: Tue, 21 Jun 2011 12:00 +0000 + +def diff --git a/lib/testdir3/cycle/cur/cycle0.0.0 b/lib/testdir3/cycle/cur/cycle0.0.0 new file mode 100644 index 0000000..907f342 --- /dev/null +++ b/lib/testdir3/cycle/cur/cycle0.0.0 @@ -0,0 +1,8 @@ +From: foo@example.com +To: bar@example.com +Subject: cycle0.0.0 +Message-Id: +References: +Date: Tue, 21 Jun 2011 13:00 +0000 + +def diff --git a/lib/testdir3/cycle/cur/rogue0 b/lib/testdir3/cycle/cur/rogue0 new file mode 100644 index 0000000..2691070 --- /dev/null +++ b/lib/testdir3/cycle/cur/rogue0 @@ -0,0 +1,8 @@ +From: foo@example.com +To: bar@example.com +Subject: rogue0 +Message-Id: +References: +Date: Tue, 21 Jun 2011 15:00 +0000 + +def diff --git a/lib/testdir3/cycle/new/.noindex b/lib/testdir3/cycle/new/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir3/cycle/tmp/.noindex b/lib/testdir3/cycle/tmp/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir3/sort/1st-child-promotes-thread/cur/A b/lib/testdir3/sort/1st-child-promotes-thread/cur/A new file mode 100644 index 0000000..85130e8 --- /dev/null +++ b/lib/testdir3/sort/1st-child-promotes-thread/cur/A @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: A +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +A diff --git a/lib/testdir3/sort/1st-child-promotes-thread/cur/B b/lib/testdir3/sort/1st-child-promotes-thread/cur/B new file mode 100644 index 0000000..254aeb7 --- /dev/null +++ b/lib/testdir3/sort/1st-child-promotes-thread/cur/B @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: B +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +B diff --git a/lib/testdir3/sort/1st-child-promotes-thread/cur/C b/lib/testdir3/sort/1st-child-promotes-thread/cur/C new file mode 100644 index 0000000..60b7db5 --- /dev/null +++ b/lib/testdir3/sort/1st-child-promotes-thread/cur/C @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: C +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +C diff --git a/lib/testdir3/sort/1st-child-promotes-thread/cur/D b/lib/testdir3/sort/1st-child-promotes-thread/cur/D new file mode 100644 index 0000000..1e4861d --- /dev/null +++ b/lib/testdir3/sort/1st-child-promotes-thread/cur/D @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: D +Message-Id: +References: +In-reply-to: +Date: Sat, 17 May 2014 10:00:00 +0000 + +D diff --git a/lib/testdir3/sort/1st-child-promotes-thread/new/.noindex b/lib/testdir3/sort/1st-child-promotes-thread/new/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir3/sort/1st-child-promotes-thread/tmp/.noindex b/lib/testdir3/sort/1st-child-promotes-thread/tmp/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir3/sort/2nd-child-promotes-thread/cur/A b/lib/testdir3/sort/2nd-child-promotes-thread/cur/A new file mode 100644 index 0000000..85130e8 --- /dev/null +++ b/lib/testdir3/sort/2nd-child-promotes-thread/cur/A @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: A +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +A diff --git a/lib/testdir3/sort/2nd-child-promotes-thread/cur/B b/lib/testdir3/sort/2nd-child-promotes-thread/cur/B new file mode 100644 index 0000000..254aeb7 --- /dev/null +++ b/lib/testdir3/sort/2nd-child-promotes-thread/cur/B @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: B +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +B diff --git a/lib/testdir3/sort/2nd-child-promotes-thread/cur/C b/lib/testdir3/sort/2nd-child-promotes-thread/cur/C new file mode 100644 index 0000000..6d1e19a --- /dev/null +++ b/lib/testdir3/sort/2nd-child-promotes-thread/cur/C @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: C +Message-Id: +References: +In-reply-to: +Date: Sat, 17 May 2014 10:00:00 +0000 + +C diff --git a/lib/testdir3/sort/2nd-child-promotes-thread/cur/D b/lib/testdir3/sort/2nd-child-promotes-thread/cur/D new file mode 100644 index 0000000..de61bc1 --- /dev/null +++ b/lib/testdir3/sort/2nd-child-promotes-thread/cur/D @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: D +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +D diff --git a/lib/testdir3/sort/2nd-child-promotes-thread/cur/E b/lib/testdir3/sort/2nd-child-promotes-thread/cur/E new file mode 100644 index 0000000..bb7f5f3 --- /dev/null +++ b/lib/testdir3/sort/2nd-child-promotes-thread/cur/E @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: E +Message-Id: +References: +In-reply-to: +Date: Sat, 17 May 2014 10:00:00 +0000 + +E diff --git a/lib/testdir3/sort/2nd-child-promotes-thread/new/.noindex b/lib/testdir3/sort/2nd-child-promotes-thread/new/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir3/sort/2nd-child-promotes-thread/tmp/.noindex b/lib/testdir3/sort/2nd-child-promotes-thread/tmp/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir3/sort/child-does-not-promote-thread/cur/A b/lib/testdir3/sort/child-does-not-promote-thread/cur/A new file mode 100644 index 0000000..c59c42f --- /dev/null +++ b/lib/testdir3/sort/child-does-not-promote-thread/cur/A @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: A +Message-Id: +References: +In-reply-to: +Aate: Sat, 17 May 2014 10:00:00 +0000 + +A diff --git a/lib/testdir3/sort/child-does-not-promote-thread/cur/X b/lib/testdir3/sort/child-does-not-promote-thread/cur/X new file mode 100644 index 0000000..c8ac3aa --- /dev/null +++ b/lib/testdir3/sort/child-does-not-promote-thread/cur/X @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: X +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +X diff --git a/lib/testdir3/sort/child-does-not-promote-thread/cur/Y b/lib/testdir3/sort/child-does-not-promote-thread/cur/Y new file mode 100644 index 0000000..ceadc20 --- /dev/null +++ b/lib/testdir3/sort/child-does-not-promote-thread/cur/Y @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: Y +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +Y diff --git a/lib/testdir3/sort/child-does-not-promote-thread/cur/Z b/lib/testdir3/sort/child-does-not-promote-thread/cur/Z new file mode 100644 index 0000000..365775b --- /dev/null +++ b/lib/testdir3/sort/child-does-not-promote-thread/cur/Z @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: Z +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +Z diff --git a/lib/testdir3/sort/child-does-not-promote-thread/new/.noindex b/lib/testdir3/sort/child-does-not-promote-thread/new/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir3/sort/child-does-not-promote-thread/tmp/.noindex b/lib/testdir3/sort/child-does-not-promote-thread/tmp/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/A b/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/A new file mode 100644 index 0000000..85130e8 --- /dev/null +++ b/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/A @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: A +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +A diff --git a/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/B b/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/B new file mode 100644 index 0000000..254aeb7 --- /dev/null +++ b/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/B @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: B +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +B diff --git a/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/C b/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/C new file mode 100644 index 0000000..6d1e19a --- /dev/null +++ b/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/C @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: C +Message-Id: +References: +In-reply-to: +Date: Sat, 17 May 2014 10:00:00 +0000 + +C diff --git a/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/D b/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/D new file mode 100644 index 0000000..1e4861d --- /dev/null +++ b/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/D @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: D +Message-Id: +References: +In-reply-to: +Date: Sat, 17 May 2014 10:00:00 +0000 + +D diff --git a/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/E b/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/E new file mode 100644 index 0000000..bb7f5f3 --- /dev/null +++ b/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/E @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: E +Message-Id: +References: +In-reply-to: +Date: Sat, 17 May 2014 10:00:00 +0000 + +E diff --git a/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/F b/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/F new file mode 100644 index 0000000..7c4275d --- /dev/null +++ b/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/F @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: F +Message-Id: +References: +In-reply-to: +Date: Sat, 17 May 2014 10:00:00 +0000 + +F diff --git a/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/G b/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/G new file mode 100644 index 0000000..4849455 --- /dev/null +++ b/lib/testdir3/sort/grandchild-promotes-only-subthread/cur/G @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: G +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +G diff --git a/lib/testdir3/sort/grandchild-promotes-only-subthread/new/.noindex b/lib/testdir3/sort/grandchild-promotes-only-subthread/new/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir3/sort/grandchild-promotes-only-subthread/tmp/.noindex b/lib/testdir3/sort/grandchild-promotes-only-subthread/tmp/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir3/sort/grandchild-promotes-thread/cur/A b/lib/testdir3/sort/grandchild-promotes-thread/cur/A new file mode 100644 index 0000000..85130e8 --- /dev/null +++ b/lib/testdir3/sort/grandchild-promotes-thread/cur/A @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: A +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +A diff --git a/lib/testdir3/sort/grandchild-promotes-thread/cur/B b/lib/testdir3/sort/grandchild-promotes-thread/cur/B new file mode 100644 index 0000000..254aeb7 --- /dev/null +++ b/lib/testdir3/sort/grandchild-promotes-thread/cur/B @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: B +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +B diff --git a/lib/testdir3/sort/grandchild-promotes-thread/cur/C b/lib/testdir3/sort/grandchild-promotes-thread/cur/C new file mode 100644 index 0000000..6d1e19a --- /dev/null +++ b/lib/testdir3/sort/grandchild-promotes-thread/cur/C @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: C +Message-Id: +References: +In-reply-to: +Date: Sat, 17 May 2014 10:00:00 +0000 + +C diff --git a/lib/testdir3/sort/grandchild-promotes-thread/cur/D b/lib/testdir3/sort/grandchild-promotes-thread/cur/D new file mode 100644 index 0000000..de61bc1 --- /dev/null +++ b/lib/testdir3/sort/grandchild-promotes-thread/cur/D @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: D +Message-Id: +Date: Sat, 17 May 2014 10:00:00 +0000 + +D diff --git a/lib/testdir3/sort/grandchild-promotes-thread/cur/E b/lib/testdir3/sort/grandchild-promotes-thread/cur/E new file mode 100644 index 0000000..d605b4b --- /dev/null +++ b/lib/testdir3/sort/grandchild-promotes-thread/cur/E @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: E +Message-Id: +References: +In-reply-to: +Date: Sat, 17 May 2014 10:00:00 +0000 + +E diff --git a/lib/testdir3/sort/grandchild-promotes-thread/new/.noindex b/lib/testdir3/sort/grandchild-promotes-thread/new/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir3/sort/grandchild-promotes-thread/tmp/.noindex b/lib/testdir3/sort/grandchild-promotes-thread/tmp/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir3/tree/cur/child0.0 b/lib/testdir3/tree/cur/child0.0 new file mode 100644 index 0000000..58da7d6 --- /dev/null +++ b/lib/testdir3/tree/cur/child0.0 @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: Re: child 0.0 +Message-Id: +References: +In-reply-to: +Date: Tue, 21 Jun 2011 11:10 +0000 + +abc diff --git a/lib/testdir3/tree/cur/child0.1 b/lib/testdir3/tree/cur/child0.1 new file mode 100644 index 0000000..163fadb --- /dev/null +++ b/lib/testdir3/tree/cur/child0.1 @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: Re: child 0.1 +Message-Id: +References: +In-reply-to: +Date: Tue, 21 Jun 2011 11:20 +0000 + +abc diff --git a/lib/testdir3/tree/cur/child0.1.0 b/lib/testdir3/tree/cur/child0.1.0 new file mode 100644 index 0000000..40a9eb2 --- /dev/null +++ b/lib/testdir3/tree/cur/child0.1.0 @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: Re: child 0.1.0 +Message-Id: +References: +In-Reply-To: +Date: Tue, 21 Jun 2011 11:22 +0000 + +abc diff --git a/lib/testdir3/tree/cur/child2.0.0 b/lib/testdir3/tree/cur/child2.0.0 new file mode 100644 index 0000000..4e4446e --- /dev/null +++ b/lib/testdir3/tree/cur/child2.0.0 @@ -0,0 +1,12 @@ +From: testfrom@example.com +To: testto@example.com +Subject: Re: child 2.0.0 +Message-Id: +References: +In-Reply-To: +Date: Tue, 21 Jun 2011 15:02 +0000 + +abc + +note, there's no message for 'nonexistant@msg.id', so this msg should +be promoted to level 2.0 diff --git a/lib/testdir3/tree/cur/child3.0.0.0.0 b/lib/testdir3/tree/cur/child3.0.0.0.0 new file mode 100644 index 0000000..1e2f4ab --- /dev/null +++ b/lib/testdir3/tree/cur/child3.0.0.0.0 @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: Re: child 3.0.0.0 +Message-Id: +References: +1n-Reply-To: +Date: Wed, 22 Jun 2011 16:33 +0000 + +abc diff --git a/lib/testdir3/tree/cur/child4.0 b/lib/testdir3/tree/cur/child4.0 new file mode 100644 index 0000000..7d0ed79 --- /dev/null +++ b/lib/testdir3/tree/cur/child4.0 @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: Re: child 4.0 +Message-Id: +References: +In-reply-to: +Date: Tue, 24 Jun 2011 11:10 +0000 + +abc diff --git a/lib/testdir3/tree/cur/child4.1 b/lib/testdir3/tree/cur/child4.1 new file mode 100644 index 0000000..295d1b1 --- /dev/null +++ b/lib/testdir3/tree/cur/child4.1 @@ -0,0 +1,9 @@ +From: testfrom@example.com +To: testto@example.com +Subject: Re: child 4.1 +Message-Id: +References: +In-reply-to: +Date: Tue, 24 Jun 2011 11:20 +0000 + +abc diff --git a/lib/testdir3/tree/cur/root0 b/lib/testdir3/tree/cur/root0 new file mode 100644 index 0000000..deb64bb --- /dev/null +++ b/lib/testdir3/tree/cur/root0 @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: root0 +Message-Id: +Date: Tue, 21 Jun 2011 11:00 +0000 + +abc diff --git a/lib/testdir3/tree/cur/root1 b/lib/testdir3/tree/cur/root1 new file mode 100644 index 0000000..fc3efd8 --- /dev/null +++ b/lib/testdir3/tree/cur/root1 @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: root1 +Message-Id: +Date: Tue, 21 Jun 2011 12:00 +0000 + +abc diff --git a/lib/testdir3/tree/cur/root2 b/lib/testdir3/tree/cur/root2 new file mode 100644 index 0000000..6ba2451 --- /dev/null +++ b/lib/testdir3/tree/cur/root2 @@ -0,0 +1,7 @@ +From: testfrom@example.com +To: testto@example.com +Subject: root2 +Message-Id: +Date: Tue, 21 Jun 2011 13:00 +0000 + +abc diff --git a/lib/testdir3/tree/new/.noindex b/lib/testdir3/tree/new/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir3/tree/tmp/.noindex b/lib/testdir3/tree/tmp/.noindex new file mode 100644 index 0000000..e69de29 diff --git a/lib/testdir4/1220863042.12663_1.mindcrime!2,S b/lib/testdir4/1220863042.12663_1.mindcrime!2,S new file mode 100644 index 0000000..ab1500f --- /dev/null +++ b/lib/testdir4/1220863042.12663_1.mindcrime!2,S @@ -0,0 +1,146 @@ +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime +X-Spam-Level: +X-Spam-Status: No, score=-4.9 required=3.0 tests=BAYES_00,DATE_IN_PAST_96_XX, + RCVD_IN_DNSWL_MED autolearn=ham version=3.2.5 +X-Original-To: xxxx@localhost +Delivered-To: xxxx@localhost +Received: from mindcrime (localhost [127.0.0.1]) + by mail.xxxxsoftware.nl (Postfix) with ESMTP id 5123469CB3 + for ; Thu, 7 Aug 2008 08:10:19 +0300 (EEST) +Delivered-To: xxxx.klub@gmail.com +Received: from gmail-imap.l.google.com [66.249.91.109] + by mindcrime with IMAP (fetchmail-6.3.8) + for (single-drop); Thu, 07 Aug 2008 08:10:19 +0300 (EEST) +Received: by 10.142.237.21 with SMTP id k21cs39272wfh; Wed, 6 Aug 2008 + 20:15:17 -0700 (PDT) +Received: by 10.65.133.8 with SMTP id k8mr2071878qbn.7.1218078916289; Wed, 06 + Aug 2008 20:15:16 -0700 (PDT) +Received: from sourceware.org (sourceware.org [209.132.176.174]) by + mx.google.com with SMTP id 28si7904461qbw.0.2008.08.06.20.15.15; Wed, 06 Aug + 2008 20:15:16 -0700 (PDT) +Received-SPF: neutral (google.com: 209.132.176.174 is neither permitted nor + denied by domain of gcc-help-return-33661-xxxx.klub=gmail.com@gcc.gnu.org) + client-ip=209.132.176.174; +Authentication-Results: mx.google.com; spf=neutral (google.com: + 209.132.176.174 is neither permitted nor denied by domain of + gcc-help-return-33661-xxxx.klub=gmail.com@gcc.gnu.org) + smtp.mail=gcc-help-return-33661-xxxx.klub=gmail.com@gcc.gnu.org +Received: (qmail 13493 invoked by alias); 7 Aug 2008 03:15:13 -0000 +Received: (qmail 13485 invoked by uid 22791); 7 Aug 2008 03:15:12 -0000 +Received: from mailgw1a.lmco.com (HELO mailgw1a.lmco.com) (192.31.106.7) + by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 07 Aug 2008 03:14:27 +0000 +Received: from emss07g01.ems.lmco.com (relay5.ems.lmco.com [166.29.2.16])by + mailgw1a.lmco.com (LM-6) with ESMTP id m773EPZH014730for + ; Wed, 6 Aug 2008 21:14:25 -0600 (MDT) +Received: from CONVERSION2-DAEMON.lmco.com by lmco.com (PMDF V6.3-x14 #31428) + id <0K5700601NO18J@lmco.com> for gcc-help@gcc.gnu.org; Wed, 06 Aug 2008 + 21:14:25 -0600 (MDT) +Received: from EMSS04I00.us.lmco.com ([166.17.13.135]) by lmco.com (PMDF + V6.3-x14 #31428) with ESMTP id <0K5700H5MNNWGX@lmco.com> for + gcc-help@gcc.gnu.org; Wed, 06 Aug 2008 21:14:20 -0600 (MDT) +Received: from EMSS35M06.us.lmco.com ([158.187.107.143]) by + EMSS04I00.us.lmco.com with Microsoft SMTPSVC(5.0.2195.6713); Wed, 06 Aug + 2008 23:14:20 -0400 +Date: Thu, 31 Jul 2008 14:57:25 -0400 +From: "Mickey Mouse" +Subject: gcc include search order +To: "Donald Duck" +Message-id: <3BE9E6535E3029448670913581E7A1A20D852173@emss35m06.us.lmco.com> +MIME-version: 1.0 +Content-type: text/plain; charset=us-ascii +Content-transfer-encoding: 7BIT +Content-class: urn:content-classes:message +Mailing-List: contact gcc-help-help@gcc.gnu.org; run by ezmlm +Precedence: klub +List-Id: +List-Unsubscribe: +List-Archive: +List-Post: +List-Help: +Sender: gcc-help-owner@gcc.gnu.org +Delivered-To: mailing list gcc-help@gcc.gnu.org +Content-Length: 3024 + + +Hi. +In my unit testing I need to change some header files (target is +vxWorks, which supports some things that the sun does not). +So, what I do is fetch the development tree, and then in a new unit test +directory I attempt to compile the unit under test. Since this is NOT +vxworks, I use sed to change some of the .h files and put them in a +./changed directory. + +When I try to compile the file, it is still using the .h file from the +original location, even though I have listed the include path for +./changed before the include path for the development tree. + +Here is a partial output from gcc using the -v option + +GNU CPP version 3.1 (cpplib) (sparc ELF) +GNU C++ version 3.1 (sparc-sun-solaris2.8) + compiled by GNU C version 3.1. +ignoring nonexistent directory "NONE/include" +#include "..." search starts here: +#include <...> search starts here: + . + changed + /export/home4/xxx/yyyy/builds/int_rel5_latest/src/mp/interface + /export/home4/xxx/yyyy/builds/int_rel5_latest/src/ap/app + /export/home4/xxx/yyyy/builds/int_rel5_latest/src/shared/common + /export/home4/xxx/yyyy/builds/int_rel5_latest/src/shared/interface + /usr/local/include/g++-v3 + /usr/local/include/g++-v3/sparc-sun-solaris2.8 + /usr/local/include/g++-v3/backward + /usr/local/include + /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/3.1/include + /usr/local/sparc-sun-solaris2.8/include + /usr/include +End of search list. + +I know the changed file is correct and that the include is not working +as expected, because when I copy the file from ./changed, back into the +development tree, the compilation works as expected. + +One more bit of information. The source that I cam compiling is in +/export/home4/xxx/yyyy/builds/int_rel5_latest/src/ap/app +And it is including files from +/export/home4/xxx/yyyy/builds/int_rel5_latest/src/shared/common +These include files should be including the files from ./changed (when +they exist) but they are ignoring the .h files in the ./changed +directory and are instead using other, unchanged files in the +/export/home4/xxx/yyyy/builds/int_rel5_latest/src/shared/common +directory. + +The gcc command line is something like + + TEST_DIR="." + + CHANGED_DIR_NAME=changed + CHANGED_FILES_DIR=${TEST_DIR}/${CHANGED_DIR_NAME} + + CICU_HEADER_FILES="-I ${AP_INTERFACE_FILES} -I ${AP_APP_FILES} -I +${SHARED_COMMON_FILES} -I ${SHARED_INTERFACE_FILES}" + + HEADERS="-I ./ -I ${CHANGED_FILES_DIR} ${CICU_HEADER_FILES}" + DEFINES="-DSUNRUN -DA10_DEBUG -DJOETEST" + + CFLAGS="-v -c -g -O1 -pipe -Wformat -Wunused -Wuninitialized -Wshadow +-Wmissing-prototypes -Wmissing-declarations" + + printf "Compiling the UUT File\n" + gcc -fprofile-arcs -ftest-coverage ${CFLAGS} ${HEADERS} ${DEFINES} +${AP_APP_FILES}/unitUnderTest.cpp + + +I hope this explanation is clear. If anyone knows how to fix the command +line so that it gets the .h files in the "changed" directory are used +instead of files in the other include directories. + +Thanks +Joe + +---------------------------------------------------- +Time Flies like an Arrow. Fruit Flies like a Banana + + diff --git a/lib/testdir4/1220863087.12663_19.mindcrime!2,S b/lib/testdir4/1220863087.12663_19.mindcrime!2,S new file mode 100644 index 0000000..78efa2a --- /dev/null +++ b/lib/testdir4/1220863087.12663_19.mindcrime!2,S @@ -0,0 +1,77 @@ +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mindcrime +X-Spam-Level: +X-Spam-Status: No, score=-2.6 required=3.0 tests=BAYES_00 autolearn=ham + version=3.2.5 +X-Original-To: xxxx@localhost +Delivered-To: xxxx@localhost +Received: from mindcrime (localhost [127.0.0.1]) + by mail.xxxxsoftware.nl (Postfix) with ESMTP id C4D6569CB3 + for ; Thu, 7 Aug 2008 08:10:08 +0300 (EEST) +Delivered-To: xxxx.klub@gmail.com +Received: from gmail-imap.l.google.com [66.249.91.109] + by mindcrime with IMAP (fetchmail-6.3.8) + for (single-drop); Thu, 07 Aug 2008 08:10:08 +0300 (EEST) +Received: by 10.142.237.21 with SMTP id k21cs34794wfh; Wed, 6 Aug 2008 + 13:40:29 -0700 (PDT) +Received: by 10.100.33.13 with SMTP id g13mr1093301ang.79.1218055228418; Wed, + 06 Aug 2008 13:40:28 -0700 (PDT) +Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) by mx.google.com + with ESMTP id d19si15908789and.17.2008.08.06.13.40.27; Wed, 06 Aug 2008 + 13:40:28 -0700 (PDT) +Received-SPF: pass (google.com: domain of + help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 + as permitted sender) client-ip=199.232.76.165; +Authentication-Results: mx.google.com; spf=pass (google.com: domain of + help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org designates 199.232.76.165 + as permitted sender) + smtp.mail=help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Received: from localhost ([127.0.0.1]:56316 helo=lists.gnu.org) by + lists.gnu.org with esmtp (Exim 4.43) id 1KQpo3-0007Pc-Qk for + xxxx.klub@gmail.com; Wed, 06 Aug 2008 16:40:27 -0400 +From: anon@example.com +Newsgroups: gnu.emacs.help +Date: Wed, 6 Aug 2008 20:38:35 +0100 +Message-ID: +References: <55dbm5-qcl.ln1@news.ducksburg.com> + +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +X-Trace: individual.net bABVU1hcJwWAuRwe/097AAoOXnGGeYR8G1In635iFGIyfDLPUv +X-Orig-Path: news.ducksburg.com!news +Cancel-Lock: sha1:wK7dsPRpNiVxpL/SfvmNzlvUR94= + sha1:oepBoM0tJBLN52DotWmBBvW5wbg= +User-Agent: slrn/pre0.9.9-120/mm/ao (Ubuntu Hardy) +Path: news.stanford.edu!headwall.stanford.edu!newshub.sdsu.edu!feeder.erje.net!proxad.net!feeder1-2.proxad.net!feed.ac-versailles.fr!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail +Xref: news.stanford.edu gnu.emacs.help:160868 +To: help-gnu-emacs@gnu.org +Subject: Re: Learning LISP; Scheme vs elisp. +X-BeenThere: help-gnu-emacs@gnu.org +X-Mailman-Version: 2.1.5 +Precedence: list +List-Id: Users list for the GNU Emacs text editor +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +Sender: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Errors-To: help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org +Content-Length: 417 +Lines: 11 + +On 2008-08-01, Thien-Thi Nguyen wrote: + +> warriors attack, felling foe after foe, +> few growing old til they realize: to know +> what deceit is worth deflection; +> such receipt reversed rejection! +> then their heavy arms, e'er transformed to shields: +> balanced hooked charms, ploughed deep, rich yields. + +Aha: the exercise for the reader is to place the parens correctly. +Might take me a while to solve this puzzle. + diff --git a/lib/testdir4/1252168370_3.14675.cthulhu!2,S b/lib/testdir4/1252168370_3.14675.cthulhu!2,S new file mode 100644 index 0000000..1e69622 --- /dev/null +++ b/lib/testdir4/1252168370_3.14675.cthulhu!2,S @@ -0,0 +1,22 @@ +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.1.0 (2005-09-13) on mindcrime +X-Spam-Level: +Delivered-To: dfgh@floppydisk.nl +Message-ID: <43A09C49.9040902@euler.org> +Date: Wed, 14 Dec 2005 23:27:21 +0100 +From: Fred Flintstone +User-Agent: Mozilla Thunderbird 1.0.7 (X11/20051010) +X-Accept-Language: nl-NL, nl, en +MIME-Version: 1.0 +To: dfgh@floppydisk.nl +List-Id: =?utf-8?q?Example_of_List_Id?= +Subject: Re: xyz +References: <439C1136.90504@euler.org> <4399DD94.5070309@euler.org> <20051209233303.GA13812@gauss.org> <439B41ED.2080402@euler.org> <4399DD94.5070309@euler.org> <20051209233303.GA13812@gauss.org> <439A1E03.3090604@euler.org> <20051211184308.GB13513@gauss.org> +In-Reply-To: <20051211184308.GB13513@gauss.org> +X-Enigmail-Version: 0.92.0.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 7bit +X-UIDL: T +To: Bilbo Baggins +Subject: Greetings from =?UTF-8?B?TG90aGzDs3JpZW4=?= +User-Agent: Wanderlust/2.15.9 (Almost Unreal) Emacs/24.0 Mule/6.0 (HANACHIRUSATO) +Fcc: .sent +Organization: The Fellowship of the Ring +MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + +Let's write some fünkÿ text +using umlauts. + +Foo. diff --git a/lib/testdir4/1305664394.2171_402.cthulhu!2, b/lib/testdir4/1305664394.2171_402.cthulhu!2, new file mode 100644 index 0000000..863f714 --- /dev/null +++ b/lib/testdir4/1305664394.2171_402.cthulhu!2, @@ -0,0 +1,17 @@ +From: =?UTF-8?B?TcO8?= +To: Helmut =?UTF-8?B?S3LDtmdlcg==?= +Subject: =?UTF-8?B?TW90w7ZyaGVhZA==?= +User-Agent: Wanderlust/2.15.9 (Almost Unreal) Emacs/24.0 Mule/6.0 (HANACHIRUSATO) +References: +1n-Reply-To: +MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + +Test for issue #38, where apparently searching for accented words in subject, +to etc. fails. + +What about here? Queensrÿche. Mötley Crüe. + + diff --git a/lib/testdir4/181736.eml b/lib/testdir4/181736.eml new file mode 100644 index 0000000..56255c4 --- /dev/null +++ b/lib/testdir4/181736.eml @@ -0,0 +1,42 @@ +Path: uutiset.elisa.fi!feeder2.news.elisa.fi!feeder.erje.net!newsfeed.kamp.net!newsfeed0.kamp.net!nx02.iad01.newshosting.com!newshosting.com!post01.iad!not-for-mail +X-newsreader: xrn 9.03-beta-14-64bit +Sender: jimbo@lews (Jimbo Foobarcuux) +From: jimbo@slp53.sl.home (Jimbo Foobarcuux) +Reply-To: slp53@pacbell.net +Subject: Re: Are writes "atomic" to readers of the file? +Newsgroups: comp.unix.programmer +References: <87hbblwelr.fsf@sapphire.mobileactivedefense.com> <8762s0jreh.fsf@sapphire.mobileactivedefense.com> <87hbbjc5jt.fsf@sapphire.mobileactivedefense.com> <8ioh48-8mu.ln1@leafnode-msgid.gclare.org.uk> +Organization: UseNetServer - www.usenetserver.com +X-Complaints-To: abuse@usenetserver.com +Message-ID: +Date: 08 Mar 2011 17:04:20 GMT +Lines: 27 +Xref: uutiset.elisa.fi comp.unix.programmer:181736 + +John Denver writes: +>Eric the Red wrote: +> +>>> There _IS_ a requirement that all reads and writes to regular files +>>> be atomic. There is also an ordering guarantee. Any implementation +>>> that doesn't provide both atomicity and ordering guarantees is broken. +>> +>> But where is it specified? +> +>The place where it is stated most explicitly is in XSH7 2.9.7 +>Thread Interactions with Regular File Operations: +> +> All of the following functions shall be atomic with respect to each +> other in the effects specified in POSIX.1-2008 when they operate on +> regular files or symbolic links: +> +> [List of functions that includes read() and write()] +> +> If two threads each call one of these functions, each call shall +> either see all of the specified effects of the other call, or none +> of them. +> + +And, for the purposes of this paragraph, the two threads need not be +part of the same process. + +jimbo diff --git a/lib/testdir4/encrypted!2,S b/lib/testdir4/encrypted!2,S new file mode 100644 index 0000000..b6470e7 --- /dev/null +++ b/lib/testdir4/encrypted!2,S @@ -0,0 +1,57 @@ +Return-path: <> +Envelope-to: peter@example.com +Delivery-date: Fri, 11 May 2012 16:22:03 +0300 +Received: from localhost.example.com ([127.0.0.1] helo=borealis) + by borealis with esmtp (Exim 4.77) + id 1SSpnB-00038a-Ux + for djcb@localhost; Fri, 11 May 2012 16:21:58 +0300 +Delivered-To: peter@example.com +From: Brian +To: Peter +Subject: encrypted +User-agent: mu4e 0.9.8.5-dev1; emacs 24.1.50.8 +Date: Fri, 11 May 2012 16:21:42 +0300 +Message-ID: <877gwi97kp.fsf@example.com> +MIME-Version: 1.0 +Content-Type: multipart/encrypted; boundary="=-=-="; + protocol="application/pgp-encrypted" + +--=-=-= +Content-Type: application/pgp-encrypted + +Version: 1 + +--=-=-= +Content-Type: application/octet-stream + +-----BEGIN PGP MESSAGE----- +Version: GnuPG v1.4.12 (GNU/Linux) + +hQQOA1T38TPQrHD6EA//YXkUB4Dy09ngCRyHWbXmV3XBjuKTr8xrak5ML1kwurav +gyagOHKLMU+5CKvObChiKtXhtgU0od7IC8o+ALlHevQ0XXcqNYA2KUfX8R7akq7d +Xx9mA6D8P7Y/P8juUCLBpfrCi2GC42DtvPZSUu3bL/ctUJ3InPHIfHibKF2HMm7/ +gUHAKY8VPJF39dLP8GLcfki6qFdeWbxgtzmuyzHfCBCLnDL0J9vpEQBpGDFMcc4v +cCbmMJaiPOmRb6U4WOuRVnuXuTztLiIn0jMslzOSFDcLTVBAsrC01r71O+XZKfN4 +mIfcpcWJYKM2NQW8Jwf+8Hr84uznBqs8uTTlrmppjkAHZGqGMjiQDxLhDVaCQzMy +O8PSV4xT6HPlKXOwV1OLc+vm0A0RAdSBctgZg40oFn4XdB1ur8edwAkLvc0hJKaz +gyTQiPaXm2Uh2cDeEx4xNgXmwCKasqc9jAlnDC2QwA33+pw3OqgZT5h1obn0fAeR +mgB+iW1503DIi/96p8HLZcr2EswLEH9ViHIEaFj/vlR5BaOncsLB0SsNV/MHRvym +Xg5GUjzPIiyBZ3KaR9OIBiZ5eXw+bSrPAo/CAs0Zwxag7W3CH//oK39Qo1GnkYpc +4IQxhx4IwkzqtCnripltV/kfpGu0yA/OdK8lOjkUqCwvL97o73utXIxm21Zd3mEP +/iLNrduZjMCq+goz1pDAQa9Dez6VjwRuRPTqeAac8Fx/nzrVzIoIEAt36hpuaH1l +KpbmHpKgsUWcrE5iYT0RRlRRtRF4PfJg8PUmP1hvw8TaEmNfT+0HgzcJB/gRsVdy +gTzkzUDzGZLhRcpmM5eW4BkuUmIO7625pM6Jd3HOGyfCGSXyEZGYYeVKzv8xbzYf +QM6YYKooRN9Ya2jdcWguW0sCSJO/RZ9eaORpTeOba2+Fp6w5L7lga+XM9GLfgref +Cf39XX1RsmRBsrJTw0z5COf4bT8G3/IfQP0QyKWIFITiFjGmpZhLsKQ3KT4vSe/d +gTY1xViVhkjvMFn3cgSOSrvktQpAhsXx0IRazN0T7pTU33a5K0SrZajY9ynFDIw9 +we7XYyVwZzYEXjGih5mTH1PhWYK5fZZEKKqaz5TyYv9SeWJ+8FrHeXUKD38SQEHM +qkpl9Iv17RF4Qy9uASWwRoobhKO+GykTaBSTyw8R8ctG/hfAlnaZxQ3TwNyHWyvU +9SVJsp27ulv/W9MLZtGpEMK0ckAR164Vyou1KOn200BqxbC2tJpegNeD2TP5ZtdY +HIcxkgKr0haYcDnVEf1ulSxv23pZWIexbgvVCG7dRL0eB+6O28f9CWehle10MDyM +0AYyw8Da2cu7PONMovqt4nayScyGTacFBp7c2KXR9DGZ0mcBwOjL/mGRKcVWN3MG +2auCrwn2KVWmKZI3Jp0T8KhfGBnFs9lUElpDTOiED1/2bKz6Yoc385QtWx99DFMZ +IWiH5wMxkWFpzjE+GHiJ09vSbTTL4JY9eu2n5nxQmtjYMBVxQm7S7qwH +=0Paa +-----END PGP MESSAGE----- +--=-=-=-- + diff --git a/lib/testdir4/mail1 b/lib/testdir4/mail1 new file mode 100644 index 0000000..a4e19c1 --- /dev/null +++ b/lib/testdir4/mail1 @@ -0,0 +1,38 @@ +Date: Thu, 31 Jul 2008 14:57:25 -0400 +From: "John Milton" +Subject: Fere libenter homines id quod volunt credunt +To: "Julius Caesar" +Message-id: <3BE9E6535E3029448670913581E7A1A20D852173@emss35m06.us.lmco.com> +MIME-version: 1.0 +x-label: Paradise losT +X-keywords: john, milton +Content-type: text/plain; charset=us-ascii +Content-transfer-encoding: 7BIT +Precedence: high + +OF Mans First Disobedience, and the Fruit +Of that Forbidden Tree, whose mortal tast +Brought Death into the World, and all our woe, +With loss of Eden, till one greater Man +Restore us, and regain the blissful Seat, [ 5 ] +Sing Heav'nly Muse,that on the secret top +Of Oreb, or of Sinai, didst inspire +That Shepherd, who first taught the chosen Seed, +In the Beginning how the Heav'ns and Earth +Rose out of Chaos: Or if Sion Hill [ 10 ] +Delight thee more, and Siloa's Brook that flow'd +Fast by the Oracle of God; I thence +Invoke thy aid to my adventrous Song, +That with no middle flight intends to soar +Above th' Aonian Mount, while it pursues [ 15 ] +Things unattempted yet in Prose or Rhime. +And chiefly Thou O Spirit, that dost prefer +Before all Temples th' upright heart and pure, +Instruct me, for Thou know'st; Thou from the first +Wast present, and with mighty wings outspread [ 20 ] +Dove-like satst brooding on the vast Abyss +And mad'st it pregnant: What in me is dark +Illumin, what is low raise and support; +That to the highth of this great Argument +I may assert Eternal Providence, [ 25 ] +And justifie the wayes of God to men. diff --git a/lib/testdir4/mail5 b/lib/testdir4/mail5 new file mode 100644 index 0000000..b12387a --- /dev/null +++ b/lib/testdir4/mail5 @@ -0,0 +1,624 @@ +From: Sitting Bull +To: George Custer +Subject: pics for you +Mail-Reply-To: djcb@djcbsoftware.nl +User-Agent: Hunkpapa/2.15.9 (Almost Unreal) +Fcc: .sent +MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") +Content-Type: multipart/mixed; + boundary="Multipart_Sun_Oct_17_10:37:40_2010-1" + +--Multipart_Sun_Oct_17_10:37:40_2010-1 +Content-Type: text/plain; charset=US-ASCII + +Dude! Here are some pics! + + +--Multipart_Sun_Oct_17_10:37:40_2010-1 +Content-Type: image/jpeg +Content-Disposition: inline; filename="sittingbull.jpg" +Content-Transfer-Encoding: base64 + +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 +KD//2Q== + + + +--Multipart_Sun_Oct_17_10:37:40_2010-1 +Content-Type: image/jpeg +Content-Disposition: inline; filename="custer.jpg" +Content-Transfer-Encoding: base64 + +/9j/4AAQSkZJRgABAQAAAQABAAD/4Q1kRXhpZgAASUkqAAgAAAAIABIBCQABAAAAAQAAABoBCQAB +AAAAyAAAABsBBQABAAAAbgAAACgBAwABAAAAAgAAADEBAgAOAAAAdgAAADIBAgAUAAAAhAAAABMC +CQABAAAAAQAAAGmHBAABAAAAmAAAAOYAAADIAAAAAQAAAGd0aHVtYiAyLjExLjMAMjAwNTowMTox +MCAwMDo1NzowMwAGAACQBwAEAAAAMDIyMQGRBwAEAAAAAQIDAACgBwAEAAAAMDEwMAGgAwABAAAA +//8AAAKgCQABAAAAyAAAAAOgCQABAAAA9gAAAAAAAAAGAAMBAwABAAAABgAAABoBCQABAAAASAAA +ABsBCQABAAAASAAAACgBCQABAAAAAgAAAAECBAABAAAANAEAAAICBAABAAAAJwwAAAAAAAD/2P/g +ABBKRklGAAEBAAABAAEAAP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAk +LicgIiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIy +MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAIAAaAMBIgACEQED +EQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0B +AgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpD +REVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmq +srO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEB +AQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFR +B2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVW +V1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrC +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 +pAznLa7juUCSEJMvr3qZwydRx6isi4ty3zJw1TWksjrs3kOOoJpiL0twwXlCwHoKxri6WFj8pG/k +A1fe6vIODtKmu1+Gc9vcazNHeRxyZh+RXjVuc8nJ5oA4zwxp91rmpSW1nGGnZMZbgAZ5JP5V6Cvw +213Jb7TYgbcKPMbr/wB816pGsESARpGi+iqAKT7VCPlMi5+tAHisPwc8SLJk39hH/tpI+R/47XWe +FvBeqeGtHnhlENxO8hlYRSH5vQDIHP1xXoSzow4ZT9DSvIO1AHiepeMNUWaWCBPsgDFWDrl8jsc9 +PpXMajqdxe3BuLt90zAAsABkDp0rq/ixpTWeuwanbDC3kZDr/trwT+IIrziS6uUcJcqGWgDpPDOo +pb+ILctJxITGQffp+uKKyNFtjc67YxqdyNMrfgDk/wAqKljR64vB5rK8Q6DaapCtxI0qXC7I0Kth +eXAGR3+8fzrTDYNQavKRol465DpEZFI6gryP1FJMbPMEcqxRhytNkwrLInDDriqST/ay3z4lB3A+ +tSrIWQq3DjqDVEl9h9oiDIC2e1V4H1KxvEuIGe2KHPmZxtqkbuazYtC5FVJ767vG/eyEr6dKAPQr +P4k6tZRHcy3KKeGlXJI98VuQ+OdM1EB3nubN3IASWM4Y+gIzXksN4YcB49yjsank1L7Q4ZvlVfuj +3oC57To2vQX8jJBdJujO0hnCnP0ODXWxC6dBuLL6ZFeP2/izwp4hsIodejmtNREflvdRICjnszY5 +OepGOtcvc6vqeh3Ij0jXbnyifl8mZth+maLDPU/i9Cf+EOt53YB4rtcHvypBx+leILdgDbICwrqL +7TvHPiVo7fUTdTxp8y+dIAg9+uM/rXS6D8PbDTQs+pst5cjkJ/yzU/T+L8fyp3AyfAmiXHn/ANrz +I0duqkQhurk8Z+mM0V6BI+FCqAFHAA6CiobA/9kA/+EMRWh0dHA6Ly9ucy5hZG9iZS5jb20veGFw +LzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQi +Pz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUg +NC40LjAtRXhpdjIiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5 +LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgog +ICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgeG1sbnM6dGlm +Zj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczpleGlmPSJodHRwOi8v +bnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUu +Y29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50 +cy8xLjEvIgogICB4bXA6Q3JlYXRlRGF0ZT0iMjAwNS0wMS0xMFQwMDowNzoyNyswMTowMCIKICAg +eG1wOk1vZGlmeURhdGU9IjIwMDUtMDEtMTBUMDA6NTc6MDMrMDE6MDAiCiAgIHhtcDpNZXRhZGF0 +YURhdGU9IjIwMDUtMDEtMTBUMDA6NTc6MDMrMDE6MDAiCiAgIHhtcDpDcmVhdG9yVG9vbD0iQWRv +YmUgUGhvdG9zaG9wIENTIFdpbmRvd3MiCiAgIHRpZmY6T3JpZW50YXRpb249IjEiCiAgIHRpZmY6 +WFJlc29sdXRpb249IjIwMC8xIgogICB0aWZmOllSZXNvbHV0aW9uPSIyMDAvMSIKICAgdGlmZjpS +ZXNvbHV0aW9uVW5pdD0iMiIKICAgZXhpZjpDb2xvclNwYWNlPSI0Mjk0OTY3Mjk1IgogICBleGlm +OlBpeGVsWERpbWVuc2lvbj0iNzU1IgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iOTMwIgogICB4 +bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6Zjg2ZTcwZTQtNjI5OC0xMWQ5 +LTllM2YtZDQyZjM0NjM5ZGJiIgogICB4bXBNTTpJbnN0YW5jZUlEPSJ1dWlkOmY4NmU3MGU1LTYy +OTgtMTFkOS05ZTNmLWQ0MmYzNDYzOWRiYiIKICAgZGM6Zm9ybWF0PSJpbWFnZS9qcGVnIi8+CiA8 +L3JkZjpSREY+CjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAog +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAg +ICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz7/2wBDAAUDBAQEAwUEBAQFBQUG +BwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUF +BQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e +Hh4eHh7/wAARCAD2AMgDASIAAhEBAxEB/8QAHQAAAAcBAQEAAAAAAAAAAAAAAAIDBAUGBwEICf/E +AEIQAAIBAwIEBAQDBgUBCAMBAAECAwAEEQUhBhIxQQcTUWEicYGRFDKhI0JSscHRCBVicoLwFiQl +M5KissJDU9Lh/8QAGQEBAQEBAQEAAAAAAAAAAAAAAAECAwQF/8QAGhEBAQEBAQEBAAAAAAAAAAAA +AAERAjEhEv/aAAwDAQACEQMRAD8Am8Hl60dEGN+tAbnalEBIr5+PUIoGcmllXPSgkW9LxxntVBET +2pVY/Y0tFEe+KcpFRDYRDHSjrD/pp4sdHWIUwMHhwOlJcpXr0qVeEEd6aXCxxRtLK6xou7MxwB8z +TDSSpjelAtQFxxvwjaSmGXW7dnH/AOtWkH3UEUeLjjhGXATV0z7wyD/61cNTTDbG1AKcdKjBxXww +RznWbUA9Mkj+lSem3+n6lE0mnXtvdopwzQyBgp9DjpTDXGQ0mY6fFD6Vzy8DpTDTMR7UOT3p0U9q +KF3oaasm1F5PSnTr3pMAb1FJrGwGRRuX1o64xvRtqYG5X2oyp7UpgV1agCKAQSKFKZHLQozUEoNL +Rj3oBd+lLxJsKrTsaEmnccW+d65Ehz0pzGp9KuI5HHv0pdU7Yrsa+1LqmSBitSAsabdKrXiLxfb8 +IabG6xR3V/O4EVsXweXuxx2/maX4w410PhmJknlWe7A2gRhkf7j2/nWCaxxK9/qs+ohea6mbJuJd +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 + +Cheerio! + +--Multipart_Sun_Oct_17_10:37:40_2010-1-- diff --git a/lib/testdir4/multimime!2,FS b/lib/testdir4/multimime!2,FS new file mode 100644 index 0000000..84f85aa --- /dev/null +++ b/lib/testdir4/multimime!2,FS @@ -0,0 +1,27 @@ +Return-path: <> +Envelope-to: djcb@localhost +Delivery-date: Sun, 20 May 2012 09:59:51 +0300 +From: Steve Jobs +To: Bill Gates +Subject: multimime +User-agent: mu4e 0.9.8.4; emacs 23.3.1 +Date: Sat, 19 May 2012 20:57:56 +0100 +Message-ID: +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="=-=-=" + +--=-=-= +Content-Type: text/plain + +abc +--=-=-= +Content-Type: application/octet-stream +Content-Disposition: attachment; filename="test1.C" +Content-Transfer-Encoding: base64 + +aGVyZSBpcyBhIHNpbXBsZSB0ZXN0IGZpbGUuCg== +--=-=-= +Content-Type: text/plain + +def +--=-=-=-- diff --git a/lib/testdir4/signed!2,S b/lib/testdir4/signed!2,S new file mode 100644 index 0000000..7e1319a --- /dev/null +++ b/lib/testdir4/signed!2,S @@ -0,0 +1,36 @@ +User-agent: mu4e 1.1.0; emacs 27.0.50 +From: Skipio +To: Hannibal +Subject: test 123 +Date: Sun, 24 Mar 2019 11:50:42 +0200 +Message-ID: <87zhpky51p.fsf@djcbsoftware.nl> +MIME-Version: 1.0 +Content-Type: multipart/signed; boundary="=-=-="; + micalg=pgp-sha256; protocol="application/pgp-signature" + +--=-=-= +Content-Type: text/plain + + +I am signed! + +--=-=-= +Content-Type: application/pgp-signature; name="signature.asc" + +-----BEGIN PGP SIGNATURE----- + +iQIzBAEBCAAdFiEEaYec7RdFk3UPFNqYEd3+qdzEoDYFAlyXUwAACgkQEd3+qdzE +oDbjdw//dAosaEyqSfyUMXjS++iJEeDIwKwO6AjEI0xCbJjHmxq93PA61ApE/BS3 +d/sKa1dsfN+plRS+Fh3NNGSA7evar9dXtMBUr6hwL0VTmm5NDwedaPeuW6mgyVcB +VNUn5x1e/QdnSClapnGd156sryfcM1pg/667fTHT6WC01Xe0sezpkV9l0j4pslYt +y6ud/Hejszax+NcwQY7vkCcVWfB9K4zbiapdoCjHi78S4YAcsbd//KmePOqn04Sa +Tg1XsmMzIh7L/3njkJdIOd9XctTwYEcN5geY1QKrHQ/3+gBeaEYvwsvrnqnVKqMY +WCg/aYibuXl+xNkPMcKHIj1dXA3m5MkL77RrxODiAYz0YkiQx1/DLZs8PV3IVoB4 +f0GGDqyiOwSmSDa4iuCottwO4yG1WM1i7r6pir22qAekIt43wSdwakOrT1IkS8q2 +o0VGiQtEPy27D+ufiw06t02Ryf20Q7i2YcueZxYeRBq41m11M41DJ4wH7LQcJsww +qG5iBOdwQFCTWpi1UrbbFjlxXXWvKMuIU+4k7nsamrEL4SDXmq1v13vtlcgJ6vnn +v7c9+MF7laqdfI+BYnlD1v/9LosPbFTm0hPdvK4yIOORp8Iwj/1PGzTOz6SCUxzA +kDu+Y+NN9/SM1ppStg1OikYPcfEXF8igWhuORwqcmpgHxVkIQ9I= +=wnkU +-----END PGP SIGNATURE----- +--=-=-=-- diff --git a/lib/testdir4/signed-bad!2,S b/lib/testdir4/signed-bad!2,S new file mode 100644 index 0000000..7a37ba9 --- /dev/null +++ b/lib/testdir4/signed-bad!2,S @@ -0,0 +1,35 @@ +Return-path: <> +Envelope-to: skipio@localhost +Delivery-date: Fri, 11 May 2012 16:21:57 +0300 +Received: from localhost.roma.net([127.0.0.1] helo=borealis) + by borealis with esmtp (Exim 4.77) + id 1SSpnB-00038a-55 + for djcb@localhost; Fri, 11 May 2012 16:21:57 +0300 +From: Skipio +To: Hannibal +Subject: signed +User-agent: mu4e 0.9.8.5-dev1; emacs 24.1.50.8 +Date: Fri, 11 May 2012 16:20:45 +0300 +Message-ID: <878vgy97ma.fsf@roma.net> +MIME-Version: 1.0 +Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha1; + protocol="application/pgp-signature" + +--=-=-= +Content-Type: text/plain + + +I am signed! But it's not good because I added this later + +--=-=-= +Content-Type: application/pgp-signature + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.12 (GNU/Linux) + +iEYEARECAAYFAk+tEi0ACgkQ6WrHoQF92jxTzACeKd/XxY+P7bpymWL3JBRHaW9p +DpwAoKw7PDW4z/lNTkWjndVTjoO9jGhs +=blXz +-----END PGP SIGNATURE----- +--=-=-=-- + diff --git a/lib/testdir4/signed-encrypted!2,S b/lib/testdir4/signed-encrypted!2,S new file mode 100644 index 0000000..a3910e6 --- /dev/null +++ b/lib/testdir4/signed-encrypted!2,S @@ -0,0 +1,54 @@ +Return-path: <> +Envelope-to: karjala@localhost +Delivery-date: Fri, 11 May 2012 16:37:57 +0300 +From: karjala@example.com +To: lapinkulta@example.com +Subject: signed + encrypted +User-agent: mu4e 0.9.8.5-dev1; emacs 24.1.50.8 +Date: Fri, 11 May 2012 16:36:08 +0300 +Message-ID: <874nrm96wn.fsf@example.com> +MIME-Version: 1.0 +Content-Type: multipart/encrypted; boundary="=-=-="; + protocol="application/pgp-encrypted" + +--=-=-= +Content-Type: application/pgp-encrypted + +Version: 1 + +--=-=-= +Content-Type: application/octet-stream + +-----BEGIN PGP MESSAGE----- +Version: GnuPG v1.4.12 (GNU/Linux) + +hQQOA1T38TPQrHD6EA/+K4kSpMa7zk+qihUkQnHSq28xYxisNQx6X5DVNjA/Qx16 +uZj/40ae+PoSMTVfklP+B2S/IomuTW6dwVqS7aQ3u4MTzi+YOi11k1lEMD7hR0Wb +L0i48o3/iCPuCTpnOsaLZvRL06g+oTi0BF2pgz/YdsgsBTGrTb3pkDGSlLIhvh/J +P8eE3OuzkXS6d8ymJKx2S2wQJrc1AFf1BgJfgc5T0iAvcV+zIMG+PIYcVd04zVpj +cORFEfvGgfxWkeX+Ks3tu/l5PA1EesnoqFdNFZm+RKBg3RFsOm8tBlJ46xJjfeHg +zLgifeSLy3tOX7CvWYs9torrx7s7UOI2gV8kzBqz+a7diyCMezceeQ9l0nIRybwW +C9Egp8Bpfb02iXTOGdE/vRiNItQH14GKmXf4nCSwdtQUm3yzaqY9yL3xBxAlW53e +YOFfPMESt+E7IlPn0c7llWGrcdrhJbUEoGOIPezES7kdeNPzi8G1lLtvT04/SSZJ +QxPH5FNzSFaYFAQSdI7TR69P7L7vtLL8ndkjY49HfLFXochQQzsqrzVxzRCruHxA +zbZSRptNf9SuXEaX9buO1vlFHheGvrCKzEWa6O7JD/DiyrE/zqy4jdlh9abMCouQ +GWGSbn8jk6SMTQQ2Yv/VOyFqifHZp0UJD59tyIdenpxoYu5M0lwHLNVDlRjLEwUQ +AIDz1tbLoM7lxs2FOKGr8QqbKIeMfL+NUmbvVIDc4mJrOlRnHh+cZYm4Z49iTl1v +bYNMYgR5nY7W6rqh0ae7ZOW0h2NzpkAwTzuf1YrSjNavd9KBwOCFtAoZhRwfwFVx +ju+ByHFNnf7g/R6DekHS0pSiatM0cPDJT05atEZb+13CRHHznonmLHi+VahXjrpg +cIUA8Lhjdfm6Fsabo7gNZnTTRxNBqUXKK2vJF/XLbNrH5K2BH2dCCmUNtm3yFWiM +DOzaw3665Y3S6MvZdyKpatbNrVoJdBpRgPxJ1YCSEituFUqHJBStay+aRb5fVkQR +w3+9hWw+Ob0+2EumKbgfQ7iMwTZBCZP4VOxkoqdHvs9aWm4N7wHtXsyCew3icbJx +lyUWsDx/FI+HlQRfOqeAMxmp8kKybmHNw8oGiw+uPPUHSD1NFYVm2DtwhYll3Fvs +YY7r5s3yP1ZnwxMqWI3OsExVUXs8MS4UTAgO+cggO7YidPcANbBDihBFP8mTXtni +Oo5n5v+/eRoLfHmnsGcaK8EkKsfFHpbqn4gxXGcBuHaTTJ/ZhbW6bi1WWZA9ExaJ +IeTDtp5Bks1pJvTjCDacvgwl3rEBM6yaeIvB7575Y/GPMTOZhawhfOxV1smMmTKI +JOWYb3+PuN2cvWetkjFgH8re4sRXq22DKBZHJEWYU8sH0sACAePnIr+pkrOtGeJB +t1zBqZUnrupH6ptk9n/AjbQ+XSMTEKu55gSjYLAYx1EHApx52QLkdh+ej5xCIVeY +6wS1Iipkoc6/r6F7CKctupXurNY2AlD4uQIOfD6kQgkqK4PY3hsRHQA+Zqj6oRfr +kxysFJZvhgt26IeBVapFs10WuYt9iHfpbPUBQUIZCLyPAh08UdVW64Uc2DvUPy+I +C+3RrmTHQPP/YNKgDQaZ3ySVEDkqjaDPmXr5K0Ibaib2dtPCLcA= +=pv03 +-----END PGP MESSAGE----- +--=-=-=-- + diff --git a/lib/testdir4/special!2,Sabc b/lib/testdir4/special!2,Sabc new file mode 100644 index 0000000..7f1de8e --- /dev/null +++ b/lib/testdir4/special!2,Sabc @@ -0,0 +1,10 @@ +Date: Thu, 1 Jun 2012 14:57:25 -0200 +From: "Rocky Balboa" +To: "Ivan Drago" +Subject: currying and tail optimization +Message-id: <3BE9E653ef345@emss35m06.us.lmco.com> +MIME-version: 1.0 +Content-type: text/plain; charset=us-ascii +Content-transfer-encoding: 7BIT + +Test 123. I'm a special message with special flags. diff --git a/lib/utils/Makefile.am b/lib/utils/Makefile.am new file mode 100644 index 0000000..5a638ac --- /dev/null +++ b/lib/utils/Makefile.am @@ -0,0 +1,109 @@ +## Copyright (C) 2020 Dirk-Jan C. Binnema +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +AM_CFLAGS= \ + $(WARN_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(ASAN_CFLAGS) \ + $(CODE_COVERAGE_CFLAGS) \ + -DMU_TESTMAILDIR=\"${abs_top_srcdir}/lib/testdir\" \ + -DMU_TESTMAILDIR2=\"${abs_top_srcdir}/lib/testdir2\" \ + -Wno-format-nonliteral \ + -Wno-switch-enum \ + -Wno-deprecated-declarations \ + -Wno-inline \ + -I${top_srcdir}/lib + +AM_CPPFLAGS= \ + $(CODE_COVERAGE_CPPFLAGS) + +AM_CXXFLAGS= \ + $(WARN_CXXFLAGS) \ + $(GLIB_CFLAGS) \ + $(ASAN_CXXFLAGS) \ + $(CODE_COVERAGE_CFLAGS) \ + -I${top_srcdir}/lib + +AM_LDFLAGS= \ + $(ASAN_LDFLAGS) + +noinst_LTLIBRARIES= \ + libmu-utils.la + +libmu_utils_la_SOURCES= \ + mu-date.c \ + mu-date.h \ + mu-error.hh \ + mu-log.c \ + mu-log.h \ + mu-command-parser.cc \ + mu-command-parser.hh \ + mu-sexp-parser.cc \ + mu-sexp-parser.hh \ + mu-str.c \ + mu-str.h \ + mu-util.c \ + mu-util.h \ + mu-utils.cc \ + mu-utils.hh + +libmu_utils_la_LIBADD= \ + $(GLIB_LIBS) \ + $(CODE_COVERAGE_LIBS) + +noinst_PROGRAMS= \ + $(TEST_PROGS) + +TEST_PROGS+= \ + test-mu-util +test_mu_util_SOURCES= \ + test-mu-util.c +test_mu_util_LDADD= \ + libmu-utils.la + +TEST_PROGS+= \ + test-mu-utils +test_mu_utils_SOURCES= \ + test-utils.cc +test_mu_utils_LDADD= \ + libmu-utils.la + +TEST_PROGS+= \ + test-mu-str +test_mu_str_SOURCES= \ + test-mu-str.c +test_mu_str_LDADD= \ + libmu-utils.la + +TEST_PROGS+= \ + test-sexp-parser +test_sexp_parser_SOURCES= \ + test-sexp-parser.cc +test_sexp_parser_LDADD= \ + libmu-utils.la + +TEST_PROGS+= \ + test-command-parser +test_command_parser_SOURCES= \ + test-command-parser.cc +test_command_parser_LDADD= \ + libmu-utils.la + +TESTS=$(TEST_PROGS) + +include $(top_srcdir)/aminclude_static.am diff --git a/lib/utils/mu-command-parser.cc b/lib/utils/mu-command-parser.cc new file mode 100644 index 0000000..7c4aa4a --- /dev/null +++ b/lib/utils/mu-command-parser.cc @@ -0,0 +1,196 @@ +/* +** Copyright (C) 2020 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include "mu-command-parser.hh" +#include "mu-utils.hh" + +#include +#include + +using namespace Mu; +using namespace Command; +using namespace Sexp; + +static Mu::Error +command_error(const std::string& msg) +{ + return Mu::Error(Error::Code::Command, msg); +} + + +void +Command::invoke(const Command::CommandMap& cmap, const Node& call) +{ + if (call.type != Type::List || call.children.empty() || + call.children[0].type != Type::Symbol) + throw command_error("call must be a list starting with a symbol"); + + const auto& params{call.children}; + const auto cmd_it = cmap.find(params[0].value); + if (cmd_it == cmap.end()) + throw command_error("unknown command '" + params[0].value + "'"); + + const auto& cinfo{cmd_it->second}; + + // all required parameters must be present + for (auto&& arg: cinfo.args) { + const auto& argname{arg.first}; + const auto& arginfo{arg.second}; + + // calls used keyword-parameters, e.g. + // (my-function :bar 1 :cuux "fnorb") + // so, we're looking for the odd-numbered parameters. + const auto param_it = [&]() { + for (size_t i = 1; i < params.size(); i += 2) + if (params[i].type == Type::Symbol && + params[i].value == ':' + argname) + return params.begin() + i + 1; + + return params.end(); + + }(); + + // it's an error when a required parameter is missing. + if (param_it == params.end()) { + if (arginfo.required) + throw command_error("missing required parameter '" + argname + "'"); + continue; // not required + } + + // the types must match, but the 'nil' symbol is acceptable as + // "no value" + if (param_it->type != arginfo.type && + !(param_it->type == Type::Symbol && param_it->value == "nil")) + throw command_error("parameter '" + argname + "' expects type " + + to_string(arginfo.type) + + " but got " + to_string(param_it->type)); + } + + // all passed parameters must be known + for (size_t i = 1; i < params.size(); i += 2) { + if (std::none_of(cinfo.args.begin(), cinfo.args.end(), + [&](auto&& arg) {return params[i].value == ":" + arg.first;})) + throw command_error("unknown parameter '" + params[i].value + "'"); + } + + if (cinfo.handler) + cinfo.handler(params); +} + +static Parameters::const_iterator +find_param_node (const Parameters& params, const std::string& argname) +{ + for (size_t i = 1; i < params.size(); i += 2) { + if (i + 1 != params.size() && + params[i].type == Type::Symbol && + params[i].value == ':' + argname) + return params.begin() + i + 1; + } + + return params.end(); +} + +constexpr auto Nil = "nil"; + +static bool +is_nil(const Node& node) +{ + return node.type == Type::Symbol && node.value == Nil; +} + +const std::string& +Command::get_string_or (const Parameters& params, const std::string& argname, + const std::string& alt) +{ + const auto it = find_param_node (params, argname); + if (it == params.end() || is_nil(*it)) + return alt; + else if (it->type != Type::String) + throw Error(Error::Code::InvalidArgument, "expected but got %s (value: '%s')", + to_string(it->type).c_str(), + it->value.c_str()); + + return it->value; +} + +const std::string& +Command::get_symbol_or (const Parameters& params, const std::string& argname, + const std::string& alt) +{ + const auto it = find_param_node (params, argname); + if (it == params.end() || is_nil(*it)) + return alt; + else if (it->type != Type::Symbol) + throw Error(Error::Code::InvalidArgument, "expected but got %s (value: '%s')", + to_string(it->type).c_str(), + it->value.c_str()); + + return it->value; +} + + +int +Command::get_int_or (const Parameters& params, const std::string& argname, + int alt) +{ + const auto it = find_param_node (params, argname); + if (it == params.end() || is_nil(*it)) + return alt; + else if (it->type != Type::Integer) + throw Error(Error::Code::InvalidArgument, "expected but got %s", + to_string(it->type).c_str()); + else + return ::atoi(it->value.c_str()); +} + +bool +Command::get_bool_or (const Parameters& params, const std::string& argname, + bool alt) +{ + const auto it = find_param_node (params, argname); + if (it == params.end()) + return alt; + else if (it->type != Type::Symbol) + throw Error(Error::Code::InvalidArgument, "expected but got %s", + to_string(it->type).c_str()); + else + return it->value != Nil; +} + +std::vector +Command::get_string_vec (const Parameters& params, const std::string& argname) +{ + const auto it = find_param_node (params, argname); + if (it == params.end() || is_nil(*it)) + return {}; + else if (it->type != Type::List) + throw Error(Error::Code::InvalidArgument, "expected but got %s", + to_string(it->type).c_str()); + + std::vector vec; + for (const auto& n: it->children) { + if (n.type != Type::String) + throw Error(Error::Code::InvalidArgument, + "expected string element but got %s", + to_string(n.type).c_str()); + vec.emplace_back (n.value); + } + + return vec; +} diff --git a/lib/utils/mu-command-parser.hh b/lib/utils/mu-command-parser.hh new file mode 100644 index 0000000..58c2f11 --- /dev/null +++ b/lib/utils/mu-command-parser.hh @@ -0,0 +1,157 @@ +/* +** Copyright (C) 2020 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ +#ifndef MU_COMMAND_PARSER_HH__ +#define MU_COMMAND_PARSER_HH__ + +#include +#include +#include +#include +#include +#include +#include + +#include "utils/mu-error.hh" +#include "utils/mu-sexp-parser.hh" + + +namespace Mu { +namespace Command { + +/// +/// Commands are s-expressions with the follow properties: + +/// 1) a command is a list with a command-name as its first argument +/// 2) the rest of the parameters are pairs of colon-prefixed symbol and a value of some +/// type (ie. 'keyword arguments') +/// 3) each command is described by its CommandInfo structure, which defines the type +/// 4) calls to the command must include all required parameters +/// 5) all parameters must be of the specified type; however the symbol 'nil' is allowed +/// for specify a non-required parameter to be absent; this is for convenience on the +/// call side. + + +/// Information about a function argument +struct ArgInfo { + ArgInfo (Sexp::Type typearg, bool requiredarg, std::string&& docarg): + type{typearg}, required{requiredarg},docstring{std::move(docarg)} + {} + const Sexp::Type type; /**< Sexp::Type of the argument */ + const bool required; /**< Is this argument required? */ + const std::string docstring; /**< Documentation */ +}; + +/// The arguments for a function, which maps their names to the information. +using ArgMap = std::unordered_map; +// The parameters to a Handler. +using Parameters = std::vector; + +int get_int_or (const Parameters& parms, const std::string& argname, int alt=0); +bool get_bool_or (const Parameters& parms, const std::string& argname, bool alt=false); +const std::string& get_string_or (const Parameters& parms, const std::string& argname, const std::string& alt=""); +const std::string& get_symbol_or (const Parameters& parms, const std::string& argname, const std::string& alt="nil"); + + +std::vector get_string_vec (const Parameters& params, const std::string& argname); + + +// A handler function +using Handler = std::function; + +/// Information about some command +struct CommandInfo { + CommandInfo(ArgMap&& argmaparg, std::string&& docarg, Handler&& handlerarg): + args{std::move(argmaparg)}, docstring{std::move(docarg)}, handler{std::move(handlerarg)} + {} + const ArgMap args; + const std::string docstring; + const Handler handler; + + /** + * Get a sorted list of argument names, for display. Required args come + * first, then alphabetical. + * + * @return vec with the sorted names. + */ + std::vector sorted_argnames() const { // sort args -- by required, then alphabetical. + std::vector names; + for (auto&& arg: args) + names.emplace_back(arg.first); + std::sort(names.begin(), names.end(), [&](const auto& name1, const auto& name2) { + const auto& arg1{args.find(name1)->second}; + const auto& arg2{args.find(name2)->second}; + if (arg1.required != arg2.required) + return arg1.required; + else + return name1 < name2; + }); + return names; + } +}; +/// All commands, mapping their name to information about them. +using CommandMap = std::unordered_map; + +/** + * Validate that the call (a Sexp::Node) specifies a valid call, then invoke it. + * + * A call uses keyword arguments, e.g. something like: + * (foo :bar 1 :cuux "fnorb") + * + * On error, throw Error. + * + * @param cmap map of commands + * @param call node describing a call. + */ +void invoke(const Command::CommandMap& cmap, const Sexp::Node& call); + + +static inline std::ostream& +operator<<(std::ostream& os, const Command::ArgInfo& info) +{ + os << info.type + << " (" << ( info.required ? "required" : "optional" ) << ")"; + + return os; +} + +static inline std::ostream& +operator<<(std::ostream& os, const Command::CommandInfo& info) +{ + for (auto&& arg: info.args) + os << " " << arg.first << ": " << arg.second << '\n' + << " " << arg.second.docstring << "\n"; + + return os; +} + +static inline std::ostream& +operator<<(std::ostream& os, const Command::CommandMap& map) +{ + for (auto&& c: map) + os << c.first << '\n' << c.second; + + return os; +} + + +} // namespace Command +} // namespace Mu + + +#endif /* MU_COMMAND_PARSER_HH__ */ diff --git a/lib/utils/mu-date.c b/lib/utils/mu-date.c new file mode 100644 index 0000000..4d46397 --- /dev/null +++ b/lib/utils/mu-date.c @@ -0,0 +1,87 @@ +/* +** Copyright (C) 2012 +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include +#include +#include + +#include "mu-util.h" +#include "mu-date.h" +#include "mu-str.h" + +const char* +mu_date_str_s (const char* frm, time_t t) +{ + struct tm *tmbuf; + static char buf[128]; + static int is_utf8 = -1; + size_t len; + + if (G_UNLIKELY(is_utf8 == -1)) + is_utf8 = mu_util_locale_is_utf8 () ? 1 : 0; + + g_return_val_if_fail (frm, NULL); + + tmbuf = localtime(&t); + len = strftime (buf, sizeof(buf) - 1, frm, tmbuf); + if (len == 0) + return ""; /* not necessarily an error... */ + + if (!is_utf8) { + /* charset is _not_ utf8, so we need to convert it, so + * the date could contain locale-specific characters*/ + gchar *conv; + GError *err; + err = NULL; + conv = g_locale_to_utf8 (buf, -1, NULL, NULL, &err); + if (err) { + g_warning ("conversion failed: %s", err->message); + g_error_free (err); + strcpy (buf, ""); + } else { + strncpy (buf, conv, sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; + } + + g_free (conv); + } + + return buf; +} + +char* +mu_date_str (const char *frm, time_t t) +{ + return g_strdup (mu_date_str_s(frm, t)); +} + + +const char* +mu_date_display_s (time_t t) +{ + time_t now; + static const time_t SECS_IN_DAY = 24 * 60 * 60; + + now = time (NULL); + + if (ABS(now - t) > SECS_IN_DAY) + return mu_date_str_s ("%x", t); + else + return mu_date_str_s ("%X", t); +} diff --git a/lib/utils/mu-date.h b/lib/utils/mu-date.h new file mode 100644 index 0000000..c7cf6c7 --- /dev/null +++ b/lib/utils/mu-date.h @@ -0,0 +1,67 @@ +/* +** Copyright (C) 2012-2013 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include + +#ifndef __MU_DATE_H__ +#define __MU_DATE_H__ + +G_BEGIN_DECLS + + +/** + * @addtogroup MuDate + * Date-related functions + * @{ + */ + +/** + * get a string for a given time_t + * + * mu_date_str_s returns a ptr to a static buffer, + * while mu_date_str returns dynamically allocated + * memory that must be freed after use. + * + * @param frm the format of the string (in strftime(3) format) + * @param t the time as time_t + * + * @return a string representation of the time; see above for what to + * do with it. Length is max. 128 bytes, inc. the ending \0. if the + * format is too long, the value will be truncated. in practice this + * should not happen. + */ +const char* mu_date_str_s (const char* frm, time_t t) G_GNUC_CONST; +char* mu_date_str (const char* frm, time_t t) G_GNUC_WARN_UNUSED_RESULT; + +/** + * get a display string for a given time_t; if the given is less than + * 24h from the current time, we display the time, otherwise the date, + * using the preferred date/time for the current locale + * + * mu_str_display_date_s returns a ptr to a static buffer, + * + * @param t the time as time_t + * + * @return a string representation of the time/date + */ +const char* mu_date_display_s (time_t t); + +G_END_DECLS + +#endif /*__MU_DATE_H__*/ diff --git a/lib/utils/mu-error.hh b/lib/utils/mu-error.hh new file mode 100644 index 0000000..b2d6ed2 --- /dev/null +++ b/lib/utils/mu-error.hh @@ -0,0 +1,137 @@ +/* +** Copyright (C) 2019 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + + +#ifndef MU_ERROR_HH__ +#define MU_ERROR_HH__ + +#include +#include "mu-utils.hh" +#include + +namespace Mu { + +struct Error final: public std::exception { + + enum struct Code { + AccessDenied, + Command, + File, + Index, + Internal, + InvalidArgument, + Message, + NotFound, + Parsing, + Query, + SchemaMismatch, + Store, + }; + + /** + * Construct an error + * + * @param codearg error-code + * #param msgarg the error diecription + */ + Error(Code codearg, const std::string& msgarg): + code_{codearg}, what_{msgarg} + {} + + /** + * Build an error from an error-code and a format string + * + * @param code error-code + * @param frm format string + * @param ... format parameters + * + * @return an Error object + */ + __attribute__((format(printf, 3, 0))) + Error(Code codearg, const char *frm, ...): code_{codearg} { + va_list args; + va_start(args, frm); + what_ = format(frm, args); + va_end(args); + } + + Error(Error&& rhs) = default; + Error(const Error& rhs) = delete; + + /** + * Build an error from a GError an error-code and a format string + * + * @param code error-code + * @param gerr a GError or {}, which is consumed + * @param frm format string + * @param ... format parameters + * + * @return an Error object + */ + __attribute__((format(printf, 4, 0))) + Error(Code codearg, GError **err, const char *frm, ...): code_{codearg} { + + va_list args; + va_start(args, frm); + what_ = format(frm, args); + va_end(args); + + if (err && *err) + what_ += format (": %s", (*err)->message); + else + what_ += ": something went wrong"; + + g_clear_error(err); + } + + /** + * DTOR + * + */ + virtual ~Error() = default; + + /** + * Get the descriptiove message. + * + * @return + */ + virtual const char* what() const noexcept override { + return what_.c_str(); + } + + /** + * Get the error-code for this error + * + * @return the error-code + */ + Code code() const { return code_; } + + + +private: + const Code code_; + std::string what_; + +}; + + +} // namespace Mu + + +#endif /* MU_ERROR_HH__ */ diff --git a/lib/utils/mu-log.c b/lib/utils/mu-log.c new file mode 100644 index 0000000..92ea188 --- /dev/null +++ b/lib/utils/mu-log.c @@ -0,0 +1,319 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2008-2016 Dirk-Jan C. Binnema +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ + +#include "mu-log.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mu-util.h" + +#define MU_MAX_LOG_FILE_SIZE 1000 * 1000 /* 1 MB (SI units) */ +#define MU_LOG_FILE "mu.log" + +struct _MuLog { + int _fd; /* log file descriptor */ + + MuLogOptions _opts; + + gboolean _color_stdout; /* whether to use color */ + gboolean _color_stderr; + + GLogFunc _old_log_func; +}; +typedef struct _MuLog MuLog; + +/* we use globals, because logging is a global operation as it + * globally modifies the behaviour of g_warning and friends + */ +static MuLog* MU_LOG = NULL; +static void log_write (const char* domain, GLogLevelFlags level, + const gchar *msg); + +static void +try_close (int fd) +{ + if (fd < 0) + return; + + if (close (fd) < 0) + g_printerr ("%s: close() of fd %d failed: %s\n", + __func__, fd, strerror(errno)); +} + +static void +silence (void) +{ + return; +} + +gboolean +mu_log_init_silence (void) +{ + g_return_val_if_fail (!MU_LOG, FALSE); + + MU_LOG = g_new0 (MuLog, 1); + MU_LOG->_fd = -1; + + mu_log_options_set (MU_LOG_OPTIONS_NONE); + + MU_LOG->_old_log_func = + g_log_set_default_handler ((GLogFunc)silence, NULL); + + return TRUE; +} + +static void +log_handler (const gchar* log_domain, GLogLevelFlags log_level, + const gchar* msg) +{ + if ((log_level & G_LOG_LEVEL_DEBUG) && + !(MU_LOG->_opts & MU_LOG_OPTIONS_DEBUG)) + return; + + log_write (log_domain ? log_domain : "mu", log_level, msg); +} + + +void +mu_log_options_set (MuLogOptions opts) +{ + g_return_if_fail (MU_LOG); + + MU_LOG->_opts = opts; + + /* when color is, only enable it when output is to a tty */ + if (MU_LOG->_opts & MU_LOG_OPTIONS_COLOR) { + MU_LOG->_color_stdout = isatty(fileno(stdout)); + MU_LOG->_color_stderr = isatty(fileno(stderr)); + + } +} + + +MuLogOptions +mu_log_options_get (void) +{ + g_return_val_if_fail (MU_LOG, MU_LOG_OPTIONS_NONE); + + return MU_LOG->_opts; +} + + +static gboolean +move_log_file (const char *logfile) +{ + gchar *logfile_old; + int rv; + + logfile_old = g_strdup_printf ("%s.old", logfile); + rv = rename (logfile, logfile_old); + g_free (logfile_old); + + if (rv != 0) { + g_warning ("failed to move %s to %s.old: %s", + logfile, logfile, strerror(rv)); + return FALSE; + } else + return TRUE; + +} + + +static gboolean +log_file_backup_maybe (const char *logfile) +{ + struct stat statbuf; + + if (stat (logfile, &statbuf) != 0) { + if (errno == ENOENT) + return TRUE; /* it did not exist yet, no problem */ + else { + g_warning ("failed to stat(2) %s: %s", + logfile, strerror(errno)); + return FALSE; + } + } + + /* log file is still below the max size? */ + if (statbuf.st_size <= MU_MAX_LOG_FILE_SIZE) + return TRUE; + + /* log file is too big!; we move it to .old, overwriting */ + return move_log_file (logfile); +} + + +gboolean +mu_log_init (const char* logfile, MuLogOptions opts) +{ + int fd; + + /* only init once... */ + g_return_val_if_fail (!MU_LOG, FALSE); + g_return_val_if_fail (logfile, FALSE); + + if (opts & MU_LOG_OPTIONS_BACKUP) + if (!log_file_backup_maybe(logfile)) { + g_warning ("failed to backup log file"); + return FALSE; + } + + fd = open (logfile, O_WRONLY|O_CREAT|O_APPEND, 00600); + if (fd < 0) { + g_warning ("%s: open() of '%s' failed: %s", __func__, + logfile, strerror(errno)); + return FALSE; + } + + MU_LOG = g_new0 (MuLog, 1); + MU_LOG->_fd = fd; + + mu_log_options_set (opts); + + MU_LOG->_old_log_func = + g_log_set_default_handler ((GLogFunc)log_handler, NULL); + + MU_WRITE_LOG ("logging started"); + + return TRUE; +} + +void +mu_log_uninit (void) +{ + if (!MU_LOG) + return; + + MU_WRITE_LOG ("logging stopped"); + + try_close (MU_LOG->_fd); + g_free (MU_LOG); + + MU_LOG = NULL; +} + + +static const char* +levelstr (GLogLevelFlags level) +{ + switch (level) { + case G_LOG_LEVEL_WARNING: return " [WARN] "; + case G_LOG_LEVEL_ERROR : return " [ERR ] "; + case G_LOG_LEVEL_DEBUG: return " [DBG ] "; + case G_LOG_LEVEL_CRITICAL: return " [CRIT] "; + case G_LOG_LEVEL_MESSAGE: return " [MSG ] "; + case G_LOG_LEVEL_INFO : return " [INFO] "; + default: return " [LOG ] "; + } +} + + + +#define color_stdout_maybe(C) \ + do{if (MU_LOG->_color_stdout) fputs ((C),stdout);} while (0) +#define color_stderr_maybe(C) \ + do{if (MU_LOG->_color_stderr) fputs ((C),stderr);} while (0) + + + +static void +log_write_fd (GLogLevelFlags level, const gchar *msg) +{ + time_t now; + char timebuf [22]; + const char *mylevel; + + /* get the time/date string */ + now = time(NULL); + strftime (timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", + localtime(&now)); + + if (write (MU_LOG->_fd, timebuf, strlen (timebuf)) < 0) + goto err; + + mylevel = levelstr (level); + if (write (MU_LOG->_fd, mylevel, strlen (mylevel)) < 0) + goto err; + + if (write (MU_LOG->_fd, msg, strlen (msg)) < 0) + goto err; + + if (write (MU_LOG->_fd, "\n", strlen ("\n")) < 0) + goto err; + + return; /* all went well */ + +err: + fprintf (stderr, "%s: failed to write to log: %s\n", + __func__, strerror(errno)); +} + + +static void +log_write_stdout_stderr (GLogLevelFlags level, const gchar *msg) +{ + const char *mu; + + mu = MU_LOG->_opts & MU_LOG_OPTIONS_NEWLINE ? + "\nmu: " : "mu: "; + + if (!(MU_LOG->_opts & MU_LOG_OPTIONS_QUIET) && + (level & G_LOG_LEVEL_MESSAGE)) { + color_stdout_maybe (MU_COLOR_GREEN); + fputs (mu, stdout); + fputs (msg, stdout); + fputs ("\n", stdout); + color_stdout_maybe (MU_COLOR_DEFAULT); + } + + /* for errors, log them to stderr as well */ + if (level & G_LOG_LEVEL_ERROR || + level & G_LOG_LEVEL_CRITICAL || + level & G_LOG_LEVEL_WARNING) { + color_stderr_maybe (MU_COLOR_RED); + fputs (mu, stderr); + fputs (msg, stderr); + fputs ("\n", stderr); + color_stderr_maybe (MU_COLOR_DEFAULT); + } +} + + +static void +log_write (const char* domain, GLogLevelFlags level, const gchar *msg) +{ + g_return_if_fail (MU_LOG); + + log_write_fd (level, msg); + log_write_stdout_stderr (level, msg); +} diff --git a/lib/utils/mu-log.h b/lib/utils/mu-log.h new file mode 100644 index 0000000..fc05d0b --- /dev/null +++ b/lib/utils/mu-log.h @@ -0,0 +1,99 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: + 8 -*-*/ +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_LOG_H__ +#define __MU_LOG_H__ + +#include + +/* mu log is the global logging system */ + +G_BEGIN_DECLS + +enum _MuLogOptions { + MU_LOG_OPTIONS_NONE = 0, + + /* when size of log file > MU_MAX_LOG_FILE_SIZE, move the log + * file to .old and start a new one. The .old file will + * overwrite existing files of that name */ + MU_LOG_OPTIONS_BACKUP = 1 << 1, + + /* quiet: don't log non-errors to stdout/stderr */ + MU_LOG_OPTIONS_QUIET = 1 << 2, + + /* should lines be preceded by \n? useful when errors come + * during indexing */ + MU_LOG_OPTIONS_NEWLINE = 1 << 3, + + /* color in output (iff output is to a tty) */ + MU_LOG_OPTIONS_COLOR = 1 << 4, + + /* log everything to stderr */ + MU_LOG_OPTIONS_STDERR = 1 << 5, + + /* debug: debug include debug-level information */ + MU_LOG_OPTIONS_DEBUG = 1 << 6 +}; +typedef enum _MuLogOptions MuLogOptions; + + +/** + * write logging information to a log file + * + * @param full path to the log file (does not have to exist yet, but + * it's directory must) + * @param opts logging options + * + * @return TRUE if initialization succeeds, FALSE otherwise + */ +gboolean mu_log_init (const char *logfile, MuLogOptions opts) + G_GNUC_WARN_UNUSED_RESULT; + +/** + * be silent except for runtime errors, which will be written to + * stderr. + * + * @return TRUE if initialization succeeds, FALSE otherwise + */ +gboolean mu_log_init_silence (void) G_GNUC_WARN_UNUSED_RESULT; + +/** + * uninitialize the logging system, and free all resources + */ +void mu_log_uninit (void); + +/** + * set logging options, a logical-OR'd value of MuLogOptions + * + * @param opts the options (logically OR'd) + */ +void mu_log_options_set (MuLogOptions opts); + +/** + * get logging options, a logical-OR'd value of MuLogOptions + * + * @param opts the options (logically OR'd) + */ +MuLogOptions mu_log_options_get (void); + +G_END_DECLS + +#endif /*__MU_LOG_H__*/ diff --git a/lib/utils/mu-sexp-parser.cc b/lib/utils/mu-sexp-parser.cc new file mode 100644 index 0000000..52f418a --- /dev/null +++ b/lib/utils/mu-sexp-parser.cc @@ -0,0 +1,175 @@ +/* +** Copyright (C) 2020 djcb +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + + +#include "mu-sexp-parser.hh" +#include "mu-utils.hh" + +using namespace Mu; +using namespace Sexp; + +__attribute__((format(printf, 2, 0))) static Mu::Error +parsing_error(size_t pos, const char* frm, ...) +{ + va_list args; + va_start(args, frm); + auto msg = format(frm, args); + va_end(args); + + if (pos == 0) + return Mu::Error(Error::Code::Parsing, "%s", msg.c_str()); + else + return Mu::Error(Error::Code::Parsing, "%zu: %s", pos, msg.c_str()); +} +static size_t +skip_whitespace (const std::string& s, size_t pos) +{ + while (pos != s.size()) { + if (s[pos] == ' ' || s[pos] == '\t' || s[pos] == '\n') + ++pos; + else + break; + } + + return pos; +} + +static Node parse (const std::string& expr, size_t& pos); + +static Node +parse_list (const std::string& expr, size_t& pos) +{ + if (expr[pos] != '(') // sanity check. + throw parsing_error(pos, "expected: '(' but got '%c", expr[pos]); + + std::vector children; + + ++pos; + while (expr[pos] != ')' && pos != expr.size()) + children.emplace_back(parse(expr, pos)); + + if (expr[pos] != ')') + throw parsing_error(pos, "expected: ')' but got '%c'", expr[pos]); + ++pos; + return Node{std::move(children)}; +} + +// parse string +static Node +parse_string (const std::string& expr, size_t& pos) +{ + if (expr[pos] != '"') // sanity check. + throw parsing_error(pos, "expected: '\"'' but got '%c", expr[pos]); + + bool escape{}; + std::string str; + for (++pos; pos != expr.size(); ++pos) { + + auto kar = expr[pos]; + if (escape && (kar == '"' || kar == '\\')) { + str += kar; + escape = false; + continue; + } + + if (kar == '"') + break; + else if (kar == '\\') + escape = true; + else + str += kar; + } + + if (escape || expr[pos] != '"') + throw parsing_error(pos, "unterminated string '%s'", str.c_str()); + + ++pos; + return Node{Type::String, std::move(str)}; +} + +static Node +parse_integer (const std::string& expr, size_t& pos) +{ + if (!isdigit(expr[pos]) && expr[pos] != '-') // sanity check. + throw parsing_error(pos, "expected: but got '%c", expr[pos]); + + std::string num; // negative number? + if (expr[pos] == '-') { + num = "-"; + ++pos; + } + + for (; isdigit(expr[pos]); ++pos) + num += expr[pos]; + + return Node {Type::Integer, std::move(num)}; +} + +static Node +parse_symbol (const std::string& expr, size_t& pos) +{ + if (!isalpha(expr[pos]) && expr[pos] != ':') // sanity check. + throw parsing_error(pos, "expected: |: but got '%c", expr[pos]); + + std::string symbol(1, expr[pos]); + for (++pos; isalnum(expr[pos]) || expr[pos] == '-'; ++pos) + symbol += expr[pos]; + + return Node { Type::Symbol, std::move(symbol)}; +} + + +static Node +parse (const std::string& expr, size_t& pos) +{ + pos = skip_whitespace(expr, pos); + + if (pos == expr.size()) + throw parsing_error(pos, "expected: character '%c", expr[pos]); + + const auto kar = expr[pos]; + const auto node =[&]() -> Node { + if (kar == '(') + return parse_list (expr, pos); + else if (kar == '"') + return parse_string(expr, pos); + else if (isdigit(kar) || kar == '-') + return parse_integer(expr, pos); + else if (isalpha(kar) || kar == ':') + return parse_symbol(expr, pos); + else + throw parsing_error(pos, "unexpected character '%c", kar); + }(); + + pos = skip_whitespace(expr, pos); + + return node; +} + +Node +Sexp::parse (const std::string& expr) +{ + size_t pos{}; + auto node{::parse (expr, pos)}; + + if (pos != expr.size()) + throw parsing_error(pos, "trailing data starting with '%c'", expr[pos]); + + return node; +} diff --git a/lib/utils/mu-sexp-parser.hh b/lib/utils/mu-sexp-parser.hh new file mode 100644 index 0000000..ecb97f2 --- /dev/null +++ b/lib/utils/mu-sexp-parser.hh @@ -0,0 +1,115 @@ +/* +** Copyright (C) 2020 djcb +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef MU_SEXP_PARSER_HH__ +#define MU_SEXP_PARSER_HH__ + +#include +#include + +#include "utils/mu-error.hh" + +namespace Mu { +namespace Sexp { + +/// Simple s-expression parser that parses lists () and atoms (strings +/// ("-quoted), (positive) integers ([0..9]+) and symbol starting with alpha or +/// ':', then alphanum and '-') +/// +/// (:foo (1234 "bar" nil) :quux (a b c)) + +/// Node type +enum struct Type { List, String, Integer, Symbol }; + +/// Parse node +struct Node { + /** + * Construct a new non-list node + * + * @param typearg the type of node + * @param valuearg the value + */ + Node(Type typearg, std::string&& valuearg): + type{typearg}, value{std::move(valuearg)} { + if (typearg == Type::List) + throw Error(Error::Code::Parsing, + "atomic type cannot be a "); + } + + /** + * Construct a list node + + * @param childrenarg the list children + * + * @return + */ + explicit Node(std::vector&& childrenarg): + type{Type::List}, children{std::move(childrenarg)} + {} + + const Type type; /**< Type of node */ + const std::string value; /**< String value of node (only for non-Type::List)*/ + const std::vector children; /**< Chiidren of node (only for Type::List) */ +}; + +/** + * Parse the string as an s-expressi9on. + * + * @param expr an s-expression string + * + * @return the parsed s-expression, or throw Error. + */ +Node parse(const std::string& expr); + +static inline std::ostream& +operator<<(std::ostream& os, Sexp::Type id) +{ + switch (id) { + case Sexp::Type::List: os << ""; break; + case Sexp::Type::String: os << ""; break; + case Sexp::Type::Integer: os << ""; break; + case Sexp::Type::Symbol: os << ""; break; + default: throw std::runtime_error ("unknown node type"); + } + + return os; +} + +static inline std::ostream& +operator<<(std::ostream& os, const Sexp::Node& node) +{ + os << node.type; + if (node.type == Sexp::Type::List) { + os << '('; + for (auto&& elm: node.children) + os << elm; + os << ')'; + } else + os << '{' << node.value << '}'; + + return os; +} + + +} // Sexp + + +} // Mu + +#endif /* MU_SEXP_PARSER_HH__ */ diff --git a/lib/utils/mu-str.c b/lib/utils/mu-str.c new file mode 100644 index 0000000..607d322 --- /dev/null +++ b/lib/utils/mu-str.c @@ -0,0 +1,453 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + + +#include +#include +#include +#include +#include + +#include "mu-util.h" /* PATH_MAX */ +#include "mu-str.h" + +const char* +mu_str_size_s (size_t s) +{ + static char buf[32]; + char *tmp; + + tmp = g_format_size_for_display ((goffset)s); + strncpy (buf, tmp, sizeof(buf)); + buf[sizeof(buf) -1] = '\0'; /* just in case */ + g_free (tmp); + + return buf; +} + +char* +mu_str_size (size_t s) +{ + return g_strdup (mu_str_size_s(s)); +} + + +char* +mu_str_summarize (const char* str, size_t max_lines) +{ + char *summary; + size_t nl_seen; + unsigned i,j; + gboolean last_was_blank; + + g_return_val_if_fail (str, NULL); + g_return_val_if_fail (max_lines > 0, NULL); + + /* len for summary <= original len */ + summary = g_new (gchar, strlen(str) + 1); + + /* copy the string up to max_lines lines, replace CR/LF/tab with + * single space */ + for (i = j = 0, nl_seen = 0, last_was_blank = TRUE; + nl_seen < max_lines && str[i] != '\0'; ++i) { + + if (str[i] == '\n' || str[i] == '\r' || + str[i] == '\t' || str[i] == ' ' ) { + + if (str[i] == '\n') + ++nl_seen; + + /* no double-blanks or blank at end of str */ + if (!last_was_blank && str[i+1] != '\0') + summary[j++] = ' '; + + last_was_blank = TRUE; + } else { + + summary[j++] = str[i]; + last_was_blank = FALSE; + } + } + + summary[j] = '\0'; + return summary; +} + + + + +char* +mu_str_replace (const char *str, const char *substr, const char *repl) +{ + GString *gstr; + const char *cur; + + g_return_val_if_fail (str, NULL); + g_return_val_if_fail (substr, NULL); + g_return_val_if_fail (repl, NULL); + + gstr = g_string_sized_new (2 * strlen (str)); + + for (cur = str; *cur; ++cur) { + if (g_str_has_prefix (cur, substr)) { + g_string_append (gstr, repl); + cur += strlen (substr) - 1; + } else + g_string_append_c (gstr, *cur); + } + + return g_string_free (gstr, FALSE); +} + + + +char* +mu_str_from_list (const GSList *lst, char sepa) +{ + const GSList *cur; + char *str; + + g_return_val_if_fail (sepa, NULL); + + for (cur = lst, str = NULL; cur; cur = g_slist_next(cur)) { + + char *tmp; + /* two extra dummy '\0' so -Wstack-protector won't complain */ + char sep[4] = { '\0', '\0', '\0', '\0' }; + sep[0] = cur->next ? sepa : '\0'; + + tmp = g_strdup_printf ("%s%s%s", + str ? str : "", + (gchar*)cur->data, + sep); + g_free (str); + str = tmp; + } + + return str; +} + +GSList* +mu_str_to_list (const char *str, char sepa, gboolean strip) +{ + GSList *lst; + gchar **strs, **cur; + /* two extra dummy '\0' so -Wstack-protector won't complain */ + char sep[4] = { '\0', '\0', '\0', '\0' }; + + g_return_val_if_fail (sepa, NULL); + + if (!str) + return NULL; + + sep[0] = sepa; + strs = g_strsplit (str, sep, -1); + + for (cur = strs, lst = NULL; cur && *cur; ++cur) { + char *elm; + elm = g_strdup(*cur); + if (strip) + elm = g_strstrip (elm); + + lst = g_slist_prepend (lst, elm); + } + + lst = g_slist_reverse (lst); + g_strfreev (strs); + + return lst; +} + +GSList* +mu_str_esc_to_list (const char *strings) +{ + GSList *lst; + GString *part; + unsigned u; + gboolean quoted, escaped; + + g_return_val_if_fail (strings, NULL); + + part = g_string_new (NULL); + + for (u = 0, lst = NULL, quoted = FALSE, escaped = FALSE; + u != strlen (strings); ++u) { + + char kar; + kar = strings[u]; + + if (kar == '\\') { + if (escaped) + g_string_append_c (part, '\\'); + escaped = !escaped; + continue; + } + + if (quoted && kar != '"') { + g_string_append_c (part, kar); + continue; + } + + switch (kar) { + case '"': + if (!escaped) + quoted = !quoted; + else + g_string_append_c (part, kar); + continue; + case ' ': + if (part->len > 0) { + lst = g_slist_prepend + (lst, g_string_free (part, FALSE)); + part = g_string_new (NULL); + } + continue; + default: + g_string_append_c (part, kar); + } + } + + if (part->len) + lst = g_slist_prepend (lst, g_string_free (part, FALSE)); + + return g_slist_reverse (lst); +} + + +void +mu_str_free_list (GSList *lst) +{ + g_slist_foreach (lst, (GFunc)g_free, NULL); + g_slist_free (lst); +} + + +/* this function is critical for sorting performance; therefore, no + * regexps, but just some good old c pointer magic */ +const gchar* +mu_str_subject_normalize (const gchar* str) +{ + const char* cur; + + g_return_val_if_fail (str, NULL); + + cur = str; + while (isspace(*cur)) ++cur; /* skip space */ + + /* starts with Re:? */ + if (tolower(cur[0]) == 'r' && tolower(cur[1]) == 'e') + cur += 2; + /* starts with Fwd:? */ + else if (tolower(cur[0]) == 'f' && tolower(cur[1]) == 'w' && + tolower(cur[2]) == 'd') + cur += 3; + else /* nope, different string */ + return str; + + /* we're now past either 'Re' or 'Fwd'. Maybe there's a [] now? + * ie., the Re[3]: foo case */ + if (cur[0] == '[') { /* handle the Re[3]: case */ + if (isdigit(cur[1])) { + do { ++cur; } while (isdigit(*cur)); + if ( cur[0] != ']') { + return str; /* nope: no ending ']' */ + } else /* skip ']' and space */ + do { ++cur; } while (isspace(*cur)); + } else /* nope: no number after '[' */ + return str; + } + + /* now, cur points past either 're' or 'fwd', possibly with + * []; check if it's really a prefix -- after re or fwd + * there should either a ':' and possibly some space */ + if (cur[0] == ':') { + do { ++cur; } while (isspace(*cur)); + /* note: there may still be another prefix, such as + * Re[2]: Fwd: foo */ + return mu_str_subject_normalize (cur); + } else + return str; /* nope, it was not a prefix */ +} + + +/* note: this function is *not* re-entrant, it returns a static buffer */ +const char* +mu_str_fullpath_s (const char* path, const char* name) +{ + static char buf[PATH_MAX + 1]; + + g_return_val_if_fail (path, NULL); + + g_snprintf (buf, sizeof(buf), "%s%c%s", path, G_DIR_SEPARATOR, + name ? name : ""); + + return buf; +} + + +char* +mu_str_escape_c_literal (const gchar* str, gboolean in_quotes) +{ + const char* cur; + GString *tmp; + + g_return_val_if_fail (str, NULL); + + tmp = g_string_sized_new (2 * strlen(str)); + + if (in_quotes) + g_string_append_c (tmp, '"'); + + for (cur = str; *cur; ++cur) + switch (*cur) { + case '\\': tmp = g_string_append (tmp, "\\\\"); break; + case '"': tmp = g_string_append (tmp, "\\\""); break; + default: tmp = g_string_append_c (tmp, *cur); + } + + if (in_quotes) + g_string_append_c (tmp, '"'); + + return g_string_free (tmp, FALSE); +} + + + +/* turn \0-terminated buf into ascii (which is a utf8 subset); convert + * any non-ascii into '.' + */ +char* +mu_str_asciify_in_place (char *buf) +{ + char *c; + + g_return_val_if_fail (buf, NULL); + + for (c = buf; c && *c; ++c) { + if ((!isprint(*c) && !isspace (*c)) || !isascii(*c)) + *c = '.'; + } + + return buf; +} + +char* +mu_str_utf8ify (const char *buf) +{ + char *utf8; + + g_return_val_if_fail (buf, NULL); + + utf8 = g_strdup (buf); + + if (!g_utf8_validate (buf, -1, NULL)) + mu_str_asciify_in_place (utf8); + + return utf8; +} + + + +gchar* +mu_str_convert_to_utf8 (const char* buffer, const char *charset) +{ + GError *err; + gchar * utf8; + + g_return_val_if_fail (buffer, NULL); + g_return_val_if_fail (charset, NULL ); + + err = NULL; + utf8 = g_convert_with_fallback (buffer, -1, "UTF-8", + charset, NULL, + NULL, NULL, &err); + if (!utf8) /* maybe the charset lied; try 8859-15 */ + utf8 = g_convert_with_fallback (buffer, -1, "UTF-8", + "ISO8859-15", NULL, + NULL, NULL, &err); + /* final attempt, maybe it was utf-8 already */ + if (!utf8 && g_utf8_validate (buffer, -1, NULL)) + utf8 = g_strdup (buffer); + + if (!utf8) { + g_warning ("%s: conversion failed from %s: %s", + __func__, charset, err ? err->message : ""); + } + + g_clear_error (&err); + + return utf8; +} + + +gchar* +mu_str_quoted_from_strv (const gchar **params) +{ + GString *str; + int i; + + g_return_val_if_fail (params, NULL); + + if (!params[0]) + return g_strdup (""); + + str = g_string_sized_new (64); /* just a guess */ + + for (i = 0; params[i]; ++i) { + + if (i > 0) + g_string_append_c (str, ' '); + + g_string_append_c (str, '"'); + g_string_append (str, params[i]); + g_string_append_c (str, '"'); + } + + return g_string_free (str, FALSE); +} + + +char* +mu_str_remove_ctrl_in_place (char *str) +{ + char *orig, *cur; + + g_return_val_if_fail (str, NULL); + + orig = str; + + for (cur = orig; *cur; ++cur) { + if (isspace(*cur)) { + /* squash special white space into a simple space */ + *orig++ = ' '; + } else if (iscntrl(*cur)) { + /* eat it */ + } else + *orig++ = *cur; + } + + *orig = '\0'; /* ensure the updated string has a NULL */ + + return str; +} diff --git a/lib/utils/mu-str.h b/lib/utils/mu-str.h new file mode 100644 index 0000000..f009a11 --- /dev/null +++ b/lib/utils/mu-str.h @@ -0,0 +1,221 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2008-2017 Dirk-Jan C. Binnema +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_STR_H__ +#define __MU_STR_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/** + * @addtogroup MuStr + * Various string utilities + * @{ + */ + +/** + * get a display size for a given size_t; uses M for sizes > + * 1000*1000, k for smaller sizes. Note: this function use the + * 10-based SI units, _not_ the powers-of-2 based ones. + * + * mu_str_size_s returns a ptr to a static buffer, + * while mu_str_size returns dynamically allocated + * memory that must be freed after use. + * + * @param t the size as an size_t + * + * @return a string representation of the size; see above + * for what to do with it + */ +const char* mu_str_size_s (size_t s); +char* mu_str_size (size_t s) G_GNUC_WARN_UNUSED_RESULT; + + +/** + * Replace all occurrences of substr in str with repl + * + * @param str a string + * @param substr some string to replace + * @param repl a replacement string + * + * @return a newly allocated string with the substr replaced by repl; free with g_free + */ +char *mu_str_replace (const char *str, const char *substr, const char *repl); + + +/** + * get a 'summary' of the string, ie. the first /n/ lines of the + * strings, with all newlines removed, replaced by single spaces + * + * @param str the source string + * @param max_lines the maximum number of lines to include in the summary + * + * @return a newly allocated string with the summary. use g_free to free it. + */ +char* mu_str_summarize (const char* str, size_t max_lines) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +/** + * create a full path from a path + a filename. function is _not_ + * reentrant. + * + * @param path a path (!= NULL) + * @param name a name (may be NULL) + * + * @return the path as a statically allocated buffer. don't free. + */ +const char* mu_str_fullpath_s (const char* path, const char* name); + +/** + * escape a string like a string literal in C; ie. replace \ with \\, + * and " with \" + * + * @param str a non-NULL str + * @param in_quotes whether the result should be enclosed in "" + * + * @return the escaped string, newly allocated (free with g_free) + */ +char* mu_str_escape_c_literal (const gchar* str, gboolean in_quotes) + G_GNUC_WARN_UNUSED_RESULT; + +/** + * turn a string into plain ascii by replacing each non-ascii + * character with a dot ('.'). Replacement is done in-place. + * + * @param buf a buffer to asciify + * + * @return the buf ptr (as to allow for function composition) + */ +char* mu_str_asciify_in_place (char *buf); + +/** + * turn string in buf into valid utf8. If this string is not valid + * utf8 already, the function massages the offending characters. + * + * @param buf a buffer to utf8ify + * + * @return a newly allocated utf8 string + */ +char* mu_str_utf8ify (const char *buf); + +/** + * convert a string in a certain charset into utf8 + * + * @param buffer a buffer to convert + * @param charset source character set. + * + * @return a UTF8 string (which you need to g_free when done with it), + * or NULL in case of error + */ +gchar* mu_str_convert_to_utf8 (const char* buffer, const char *charset); + + +/** + * macro to check whether the string is empty, ie. if it's NULL or + * it's length is 0 + * + * @param S a string + * + * @return TRUE if the string is empty, FALSE otherwise + */ +#define mu_str_is_empty(S) ((!(S)||!(*S))?TRUE:FALSE) + +/** + * convert a GSList of strings to a #sepa-separated list + * + * @param lst a GSList + * @param the separator character + * + * @return a newly allocated string + */ +char* mu_str_from_list (const GSList *lst, char sepa); + +/** + * convert a #sepa-separated list of strings in to a GSList + * + * @param str a #sepa-separated list of strings + * @param the separator character + * @param remove leading/trailing whitespace from the string + * + * @return a newly allocated GSList (free with mu_str_free_list) + */ +GSList* mu_str_to_list (const char *str, char sepa, gboolean strip); + +/** + * convert a string (with possible escaping) to a list. list items are + * separated by one or more spaces. list items can be quoted (using + * '"'). + * + * @param str a string + * + * @return a list of elements or NULL in case of error, free with + * mu_str_free_list + */ +GSList* mu_str_esc_to_list (const char *str); + +/** + * free a GSList consisting of allocated strings + * + * @param lst a GSList + */ +void mu_str_free_list (GSList *lst); + +/** + * strip the subject of Re:, Fwd: etc. + * + * @param str a subject string + * + * @return a new string -- this is pointing somewhere inside the @str; + * no copy is made, don't free + */ +const gchar* mu_str_subject_normalize (const gchar* str); + + +/** + * take a list of strings, and return the concatenation of their + * quoted forms + * + * @param params NULL-terminated array of strings + * + * @return the quoted concatenation of the strings + */ +gchar* mu_str_quoted_from_strv (const gchar **params); + + + +/** + * Remove control characters from a string + * + * @param str a string + * + * @return the str with control characters removed + */ +char* mu_str_remove_ctrl_in_place (char *str); + + +/** @} */ + +G_END_DECLS + +#endif /*__MU_STR_H__*/ diff --git a/lib/utils/mu-util.c b/lib/utils/mu-util.c new file mode 100644 index 0000000..9f76c3a --- /dev/null +++ b/lib/utils/mu-util.c @@ -0,0 +1,495 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ +/* +** +** Copyright (C) 2008-2016 Dirk-Jan C. Binnema +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ + +#include "mu-util.h" +#define _XOPEN_SOURCE 500 + +#ifdef HAVE_WORDEXP_H +#include /* for shell-style globbing */ +#endif /*HAVE_WORDEXP_H*/ + +#include + +#include +#include /* for setlocale() */ + +#include +#include +#include +#include + +#include +#include +#include + +#include + + +static char* +do_wordexp (const char *path) +{ +#ifdef HAVE_WORDEXP_H + wordexp_t wexp; + char *dir; + + if (!path) { + /* g_debug ("%s: path is empty", __func__); */ + return NULL; + } + + if (wordexp (path, &wexp, 0) != 0) { + /* g_debug ("%s: expansion failed for %s", __func__, path); */ + return NULL; + } + + /* we just pick the first one */ + dir = g_strdup (wexp.we_wordv[0]); + + /* strangely, below seems to lead to a crash on MacOS (BSD); + so we have to allow for a tiny leak here on that + platform... maybe instead of __APPLE__ it should be + __BSD__? + + Hmmm., cannot reproduce that crash anymore, so commenting + it out for now... + */ +/* #ifndef __APPLE__ */ + wordfree (&wexp); +/* #endif /\*__APPLE__*\/ */ + return dir; + +# else /*!HAVE_WORDEXP_H*/ +/* E.g. OpenBSD does not have wordexp.h, so we ignore it */ + return path ? g_strdup (path) : NULL; +#endif /*HAVE_WORDEXP_H*/ +} + + +/* note, the g_debugs are commented out because this function may be + * called before the log handler is installed. */ +char* +mu_util_dir_expand (const char *path) +{ + char *dir; + char resolved[PATH_MAX + 1]; + + g_return_val_if_fail (path, NULL); + + dir = do_wordexp (path); + if (!dir) + return NULL; /* error */ + + /* don't try realpath if the dir does not exist */ + if (access (dir, F_OK) != 0) + return dir; + + /* now resolve any symlinks, .. etc. */ + if (realpath (dir, resolved) == NULL) { + /* g_debug ("%s: could not get realpath for '%s': %s", */ + /* __func__, dir, strerror(errno)); */ + g_free (dir); + return NULL; + } else + g_free (dir); + + return g_strdup (resolved); +} + +GQuark +mu_util_error_quark (void) +{ + static GQuark error_domain = 0; + + if (G_UNLIKELY(error_domain == 0)) + error_domain = g_quark_from_static_string + ("mu-error-quark"); + + return error_domain; +} + + +const char* +mu_util_cache_dir (void) +{ + static char cachedir [PATH_MAX]; + + g_snprintf (cachedir, sizeof(cachedir), "%s%cmu-%u", + g_get_tmp_dir(), G_DIR_SEPARATOR, + getuid()); + + return cachedir; +} + + +gboolean +mu_util_check_dir (const gchar* path, gboolean readable, gboolean writeable) +{ + int mode; + struct stat statbuf; + + if (!path) + return FALSE; + + mode = F_OK | (readable ? R_OK : 0) | (writeable ? W_OK : 0); + + if (access (path, mode) != 0) { + /* g_debug ("Cannot access %s: %s", path, strerror (errno)); */ + return FALSE; + } + + if (stat (path, &statbuf) != 0) { + /* g_debug ("Cannot stat %s: %s", path, strerror (errno)); */ + return FALSE; + } + + return S_ISDIR(statbuf.st_mode) ? TRUE: FALSE; +} + + +gchar* +mu_util_guess_maildir (void) +{ + const gchar *mdir1, *home; + + /* first, try MAILDIR */ + mdir1 = g_getenv ("MAILDIR"); + + if (mdir1 && mu_util_check_dir (mdir1, TRUE, FALSE)) + return g_strdup (mdir1); + + /* then, try /Maildir */ + home = g_get_home_dir(); + if (home) { + char *mdir2; + mdir2 = g_strdup_printf ("%s%cMaildir", + home, G_DIR_SEPARATOR); + if (mu_util_check_dir (mdir2, TRUE, FALSE)) + return mdir2; + g_free (mdir2); + } + + /* nope; nothing found */ + return NULL; +} + +gboolean +mu_util_create_dir_maybe (const gchar *path, mode_t mode, gboolean nowarn) +{ + struct stat statbuf; + + g_return_val_if_fail (path, FALSE); + + /* if it exists, it must be a readable dir */ + if (stat (path, &statbuf) == 0) { + if ((!S_ISDIR(statbuf.st_mode)) || + (access (path, W_OK|R_OK) != 0)) { + if (!nowarn) + g_warning ("not a read-writable" + "directory: %s", path); + return FALSE; + } + } + + if (g_mkdir_with_parents (path, mode) != 0) { + if (!nowarn) + g_warning ("failed to create %s: %s", + path, strerror(errno)); + return FALSE; + } + + return TRUE; +} + + +int +mu_util_create_writeable_fd (const char* path, mode_t mode, + gboolean overwrite) +{ + errno = 0; /* clear! */ + g_return_val_if_fail (path, -1); + + if (overwrite) + return open (path, O_WRONLY|O_CREAT|O_TRUNC, mode); + else + return open (path, O_WRONLY|O_CREAT|O_EXCL, mode); +} + + +gboolean +mu_util_is_local_file (const char* path) +{ + /* if it starts with file:// it's a local file (for the + * purposes of this function -- if it's on a remote FS it's + * still considered local) */ + if (g_ascii_strncasecmp ("file://", path, strlen("file://")) == 0) + return TRUE; + + if (access (path, R_OK) == 0) + return TRUE; + + return FALSE; +} + + +gboolean +mu_util_supports (MuFeature feature) +{ + + /* check for Guile support */ +#ifndef BUILD_GUILE + if (feature & MU_FEATURE_GUILE) + return FALSE; +#endif /*BUILD_GUILE*/ + + /* check for Gnuplot */ + if (feature & MU_FEATURE_GNUPLOT) + if (!mu_util_program_in_path ("gnuplot")) + return FALSE; + + return TRUE; +} + + +gboolean +mu_util_program_in_path (const char *prog) +{ + gchar *path; + + g_return_val_if_fail (prog, FALSE); + + path = g_find_program_in_path (prog); + g_free (path); + + return (path != NULL) ? TRUE : FALSE; +} + + +/* + * Set the child to a group leader to avoid being killed when the + * parent group is killed. + */ +static void +maybe_setsid (G_GNUC_UNUSED gpointer user_data) +{ +#if HAVE_SETSID + setsid(); +#endif /*HAVE_SETSID*/ +} + +gboolean +mu_util_play (const char *path, gboolean allow_local, gboolean allow_remote, + GError **err) +{ + gboolean rv; + const gchar *argv[3]; + const char *prog; + + g_return_val_if_fail (path, FALSE); + g_return_val_if_fail (mu_util_is_local_file (path) || allow_remote, + FALSE); + g_return_val_if_fail (!mu_util_is_local_file (path) || allow_local, + FALSE); + + prog = g_getenv ("MU_PLAY_PROGRAM"); + if (!prog) { +#ifdef __APPLE__ + prog = "open"; +#else + prog = "xdg-open"; +#endif /*!__APPLE__*/ + } + + if (!mu_util_program_in_path (prog)) { + mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_EXECUTE, + "cannot find '%s' in path", prog); + return FALSE; + } + + argv[0] = prog; + argv[1] = path; + argv[2] = NULL; + + err = NULL; + rv = g_spawn_async (NULL, (gchar**)&argv, NULL, + G_SPAWN_SEARCH_PATH, maybe_setsid, + NULL, NULL, err); + return rv; +} + + +unsigned char +mu_util_get_dtype_with_lstat (const char *path) +{ + struct stat statbuf; + + g_return_val_if_fail (path, DT_UNKNOWN); + + if (lstat (path, &statbuf) != 0) { + g_warning ("stat failed on %s: %s", path, strerror(errno)); + return DT_UNKNOWN; + } + + /* we only care about dirs, regular files and links */ + if (S_ISREG (statbuf.st_mode)) + return DT_REG; + else if (S_ISDIR (statbuf.st_mode)) + return DT_DIR; + else if (S_ISLNK (statbuf.st_mode)) + return DT_LNK; + + return DT_UNKNOWN; +} + + +gboolean +mu_util_locale_is_utf8 (void) +{ + const gchar *dummy; + static int is_utf8 = -1; + + if (G_UNLIKELY(is_utf8 == -1)) + is_utf8 = g_get_charset(&dummy) ? 1 : 0; + + return is_utf8 ? TRUE : FALSE; +} + +gboolean +mu_util_fputs_encoded (const char *str, FILE *stream) +{ + int rv; + char *conv; + + g_return_val_if_fail (stream, FALSE); + + /* g_get_charset return TRUE when the locale is UTF8 */ + if (mu_util_locale_is_utf8()) + return fputs (str, stream) == EOF ? FALSE : TRUE; + + /* charset is _not_ utf8, so we need to convert it */ + conv = NULL; + if (g_utf8_validate (str, -1, NULL)) + conv = g_locale_from_utf8 (str, -1, NULL, NULL, NULL); + + /* conversion failed; this happens because is some cases GMime may gives + * us non-UTF-8 strings from e.g. wrongly encoded message-subjects; if + * so, we escape the string */ + conv = conv ? conv : g_strescape (str, "\n\t"); + rv = conv ? fputs (conv, stream) : EOF; + g_free (conv); + + return (rv == EOF) ? FALSE : TRUE; +} + + + +gboolean +mu_util_g_set_error (GError **err, MuError errcode, const char *frm, ...) +{ + va_list ap; + char *msg; + + /* don't bother with NULL errors, or errors already set */ + if (!err || *err) + return FALSE; + + msg = NULL; + va_start (ap, frm); + g_vasprintf (&msg, frm, ap); + va_end (ap); + + g_set_error (err, MU_ERROR_DOMAIN, errcode, "%s", msg); + + g_free (msg); + + return FALSE; +} + + + +__attribute__((format(printf, 2, 0))) static gboolean +print_args (FILE *stream, const char *frm, va_list args) +{ + gchar *str; + gboolean rv; + + str = g_strdup_vprintf (frm, args); + + rv = mu_util_fputs_encoded (str, stream); + + g_free (str); + + return rv; +} + + +gboolean +mu_util_print_encoded (const char *frm, ...) +{ + va_list args; + gboolean rv; + + g_return_val_if_fail (frm, FALSE); + + va_start (args, frm); + rv = print_args (stdout, frm, args); + va_end (args); + + return rv; +} + +gboolean +mu_util_printerr_encoded (const char *frm, ...) +{ + va_list args; + gboolean rv; + + g_return_val_if_fail (frm, FALSE); + + va_start (args, frm); + rv = print_args (stderr, frm, args); + va_end (args); + + return rv; +} + + +char* +mu_util_read_password (const char *prompt) +{ + char *pass; + + g_return_val_if_fail (prompt, NULL); + + /* note: getpass is obsolete; replace with something better */ + + pass = getpass (prompt); /* returns static mem, don't free */ + if (!pass) { + if (errno) + g_warning ("error: %s", strerror(errno)); + return NULL; + } + + return g_strdup (pass); +} diff --git a/lib/utils/mu-util.h b/lib/utils/mu-util.h new file mode 100644 index 0000000..72be341 --- /dev/null +++ b/lib/utils/mu-util.h @@ -0,0 +1,444 @@ +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema +** +** 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 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_UTIL_H__ +#define __MU_UTIL_H__ + +#include +#include +#include +#include /* for mode_t */ + +/* hopefully, this should get us a sane PATH_MAX */ +#include +/* not all systems provide PATH_MAX in limits.h */ +#ifndef PATH_MAX +#include +#ifndef PATH_MAX +#define PATH_MAX MAXPATHLEN +#endif /*!PATH_MAX*/ +#endif /*PATH_MAX*/ + +G_BEGIN_DECLS + +/** + * get the expanded path; ie. perform shell expansion on the path. the + * path does not have to exist + * + * @param path path to expand + * + * @return the expanded path as a newly allocated string, or NULL in + * case of error + */ +char* mu_util_dir_expand (const char* path) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +/** + * guess the maildir; first try $MAILDIR; if it is unset or + * non-existent, try ~/Maildir if both fail, return NULL + * + * @return full path of the guessed Maildir, or NULL; must be freed (gfree) + */ +char* mu_util_guess_maildir (void) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +/** + * if path exists, check that's a read/writeable dir; otherwise try to + * create it (with perms 0700) + * + * @param path path to the dir + * @param mode to set for the dir (as per chmod(1)) + * @param nowarn, if TRUE, don't write warnings (if any) to stderr + * + * @return TRUE if a read/writeable directory `path' exists after + * leaving this function, FALSE otherwise + */ +gboolean mu_util_create_dir_maybe (const gchar *path, mode_t mode, + gboolean nowarn) G_GNUC_WARN_UNUSED_RESULT; + +/** + * check whether path is a directory, and optionally, if it's readable + * and/or writeable + * + * @param path dir path + * @param readable check for readability + * @param writeable check for writability + * + * @return TRUE if dir exist and has the specified properties + */ +gboolean mu_util_check_dir (const gchar* path, gboolean readable, + gboolean writeable) + G_GNUC_WARN_UNUSED_RESULT; + + +/** + * get our the cache directory, typically, /tmp/mu-/ + * + * @return the cache directory; don't free + */ +const char* mu_util_cache_dir (void) G_GNUC_CONST; + +/** + * create a writeable file and return its file descriptor (which + * you'll need to close(2) when done with it.) + * + * @param path the full path of the file to create + * @param the mode to open (ie. 0644 or 0600 etc., see chmod(3) + * @param overwrite should we allow for overwriting existing files? + * + * @return a file descriptor, or -1 in case of error. If it's a file + * system error, 'errno' may contain more info. use 'close()' when done + * with the file descriptor + */ +int mu_util_create_writeable_fd (const char* path, mode_t mode, + gboolean overwrite) + G_GNUC_WARN_UNUSED_RESULT; + + +/** + * check if file is local, ie. on the local file system. this means + * that it's either having a file URI, *or* that it's an existing file + * + * @param path a path + * + * @return TRUE if the file is local, FALSE otherwise + */ +gboolean mu_util_is_local_file (const char* path); + + +/** + * is the current locale utf-8 compatible? + * + * @return TRUE if it's utf8 compatible, FALSE otherwise + */ +gboolean mu_util_locale_is_utf8 (void) G_GNUC_CONST; + +/** + * write a string (assumed to be in utf8-format) to a stream, + * converted to the current locale + * + * @param str a string + * @param stream a stream + * + * @return TRUE if printing worked, FALSE otherwise + */ +gboolean mu_util_fputs_encoded (const char *str, FILE *stream); + +/** + * print a formatted string (assumed to be in utf8-format) to stdout, + * converted to the current locale + * + * @param a standard printf() format string, followed by a parameter list + * + * @return TRUE if printing worked, FALSE otherwise + */ +gboolean mu_util_print_encoded (const char *frm, ...) G_GNUC_PRINTF(1,2); + +/** + * print a formatted string (assumed to be in utf8-format) to stderr, + * converted to the current locale + * + * @param a standard printf() format string, followed by a parameter list + * + * @return TRUE if printing worked, FALSE otherwise + */ +gboolean mu_util_printerr_encoded (const char *frm, ...) G_GNUC_PRINTF(1,2); + + +/** + * read a password from stdin (without echoing), and return it. + * + * @param prompt the prompt text before the password + * + * @return the password (free with g_free), or NULL + */ +char* mu_util_read_password (const char *prompt) + G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +/** + * Try to 'play' (ie., open with it's associated program) a file. On + * MacOS, the the program 'open' is used for this; on other platforms + * 'xdg-open' to do the actual opening. In addition you can set it to another program + * by setting the MU_PLAY_PROGRAM environment variable + * + * @param path full path of the file to open + * @param allow_local allow local files (ie. with file:// prefix or fs paths) + * @param allow_remote allow URIs (ie., http, mailto) + * @param err receives error information, if any + * + * @return TRUE if it succeeded, FALSE otherwise + */ +gboolean mu_util_play (const char *path, gboolean allow_local, + gboolean allow_remote, GError **err); + +/** + * Check whether program prog exists in PATH + * + * @param prog a program (executable) + * + * @return TRUE if it exists and is executable, FALSE otherwise + */ +gboolean mu_util_program_in_path (const char *prog); + + + +enum _MuFeature { + MU_FEATURE_GUILE = 1 << 0, /* do we support Guile 2.0? */ + MU_FEATURE_GNUPLOT = 1 << 1, /* do we have gnuplot installed? */ + MU_FEATURE_CRYPTO = 1 << 2 /* do we support crypto (Gmime >= 2.6) */ +}; +typedef enum _MuFeature MuFeature; + + +/** + * Check whether mu supports some particular feature + * + * @param feature a feature (multiple features can be logical-or'd together) + * + * @return TRUE if the feature is supported, FALSE otherwise + */ +gboolean mu_util_supports (MuFeature feature); + + + +/** + * Get an error-query for mu, to be used in `g_set_error'. Recent + * version of Glib warn when using 0 for the error-domain in + * g_set_error. + * + * + * @return an error quark for mu + */ +GQuark mu_util_error_quark (void) G_GNUC_CONST; +#define MU_ERROR_DOMAIN (mu_util_error_quark()) + + +/* + * for OSs with out support for direntry->d_type, like Solaris + */ +#ifndef DT_UNKNOWN +enum { + DT_UNKNOWN = 0, +#define DT_UNKNOWN DT_UNKNOWN + DT_FIFO = 1, +#define DT_FIFO DT_FIFO + DT_CHR = 2, +#define DT_CHR DT_CHR + DT_DIR = 4, +#define DT_DIR DT_DIR + DT_BLK = 6, +#define DT_BLK DT_BLK + DT_REG = 8, +#define DT_REG DT_REG + DT_LNK = 10, +#define DT_LNK DT_LNK + DT_SOCK = 12, +#define DT_SOCK DT_SOCK + DT_WHT = 14 +#define DT_WHT DT_WHT +}; +#endif /*DT_UNKNOWN*/ + + +/** + * get the d_type (as in direntry->d_type) for the file at path, using +* lstat(3) + * + * @param path full path + * + * @return DT_REG, DT_DIR, DT_LNK, or DT_UNKNOWN (other values are not + * supported currently ) + */ +unsigned char mu_util_get_dtype_with_lstat (const char *path); + + +/** + * we need this when using Xapian::Document* from C + * + */ +typedef gpointer XapianDocument; + +/** + * we need this when using Xapian::Enquire* from C + * + */ +typedef gpointer XapianEnquire; + + +/* print a warning for a GError, and free it */ +#define MU_HANDLE_G_ERROR(GE) \ + do { \ + if (!(GE)) \ + g_warning ("%s:%u: an error occurred in %s", \ + __FILE__, __LINE__, __func__); \ + else { \ + g_warning ("error %u: %s", (GE)->code, (GE)->message); \ + g_error_free ((GE)); \ + } \ + } while (0) + + + +/** + * log something in the log file; note, we use G_LOG_LEVEL_INFO + * for such messages + */ +#define MU_WRITE_LOG(...) \ + G_STMT_START { \ + g_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_INFO, \ + __VA_ARGS__); \ + } G_STMT_END + + + +#define MU_G_ERROR_CODE(GE) ((GE)&&(*(GE))?(*(GE))->code:MU_ERROR) + + +enum _MuError { + /* no error at all! */ + MU_OK = 0, + + /* generic error */ + MU_ERROR = 1, + MU_ERROR_IN_PARAMETERS = 2, + MU_ERROR_INTERNAL = 3, + MU_ERROR_NO_MATCHES = 4, + + /* not really an error; for callbacks */ + MU_IGNORE = 5, + + MU_ERROR_SCRIPT_NOT_FOUND = 8, + + /* general xapian related error */ + MU_ERROR_XAPIAN = 11, + + /* (parsing) error in the query */ + MU_ERROR_XAPIAN_QUERY = 13, + + /* missing data for a document */ + MU_ERROR_XAPIAN_MISSING_DATA = 17, + /* can't get write lock */ + MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK = 19, + /* could not write */ + MU_ERROR_XAPIAN_STORE_FAILED = 21, + /* could not remove */ + MU_ERROR_XAPIAN_REMOVE_FAILED = 22, + /* database was modified; reload */ + MU_ERROR_XAPIAN_MODIFIED = 23, + /* database was modified; reload */ + MU_ERROR_XAPIAN_NEEDS_REINDEX = 24, + /* database schema version doesn't match */ + MU_ERROR_XAPIAN_SCHEMA_MISMATCH = 25, + /* failed to open the database */ + MU_ERROR_XAPIAN_CANNOT_OPEN = 26, + + /* GMime related errors */ + + /* gmime parsing related error */ + MU_ERROR_GMIME = 30, + + /* contacts related errors */ + MU_ERROR_CONTACTS = 50, + MU_ERROR_CONTACTS_CANNOT_RETRIEVE = 51, + + /* crypto related errors */ + MU_ERROR_CRYPTO = 60, + + + /* File errors */ + /* generic file-related error */ + MU_ERROR_FILE = 70, + MU_ERROR_FILE_INVALID_NAME = 71, + MU_ERROR_FILE_CANNOT_LINK = 72, + MU_ERROR_FILE_CANNOT_OPEN = 73, + MU_ERROR_FILE_CANNOT_READ = 74, + MU_ERROR_FILE_CANNOT_EXECUTE = 75, + MU_ERROR_FILE_CANNOT_CREATE = 76, + MU_ERROR_FILE_CANNOT_MKDIR = 77, + MU_ERROR_FILE_STAT_FAILED = 78, + MU_ERROR_FILE_READDIR_FAILED = 79, + MU_ERROR_FILE_INVALID_SOURCE = 80, + MU_ERROR_FILE_TARGET_EQUALS_SOURCE = 81, + MU_ERROR_FILE_CANNOT_WRITE = 82, + MU_ERROR_FILE_CANNOT_UNLINK = 83, + + /* not really an error, used in callbacks */ + MU_STOP = 99 +}; +typedef enum _MuError MuError; + + +/** + * set an error if it's not already set, and return FALSE + * + * @param err errptr, or NULL + * @param errcode error code + * @param frm printf-style format, followed by parameters + * + * @return FALSE + */ +gboolean mu_util_g_set_error (GError **err, MuError errcode, const char *frm, ...) + G_GNUC_PRINTF(3,4); + +/** + * calculate a 64-bit hash for the given string, based on a combination of the + * DJB and BKDR hash functions. + * + * @param a string + * + * @return the hash + */ +static inline guint64 +mu_util_get_hash (const char* str) +{ + guint32 djbhash; + guint32 bkdrhash; + guint32 bkdrseed; + guint64 hash; + + djbhash = 5381; + bkdrhash = 0; + bkdrseed = 1313; + + for(unsigned u = 0U; str[u]; ++u) { + djbhash = ((djbhash << 5) + djbhash) + str[u]; + bkdrhash = bkdrhash * bkdrseed + str[u]; + } + + hash = djbhash; + return (hash<<32) | bkdrhash; +} + + + + + + +#define MU_COLOR_RED "\x1b[31m" +#define MU_COLOR_GREEN "\x1b[32m" +#define MU_COLOR_YELLOW "\x1b[33m" +#define MU_COLOR_BLUE "\x1b[34m" +#define MU_COLOR_MAGENTA "\x1b[35m" +#define MU_COLOR_CYAN "\x1b[36m" +#define MU_COLOR_DEFAULT "\x1b[0m" + +G_END_DECLS + +#endif /*__MU_UTIL_H__*/ diff --git a/lib/utils/mu-utils.cc b/lib/utils/mu-utils.cc new file mode 100644 index 0000000..2354c0c --- /dev/null +++ b/lib/utils/mu-utils.cc @@ -0,0 +1,471 @@ +/* +** Copyright (C) 2017 Dirk-Jan C. Binnema +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + + +#define _XOPEN_SOURCE +#include + +#define GNU_SOURCE +#include +#include + +#include +#include +#include + +#include +#include + +#include "mu-utils.hh" + + +using namespace Mu; + +namespace { + +static gunichar +unichar_tolower (gunichar uc) +{ + if (!g_unichar_isalpha(uc)) + return uc; + + if (g_unichar_get_script (uc) != G_UNICODE_SCRIPT_LATIN) + return g_unichar_tolower (uc); + + switch (uc) + { + case 0x00e6: + case 0x00c6: return 'e'; /* æ */ + case 0x00f8: return 'o'; /* ø */ + case 0x0110: + case 0x0111: return 'd'; /* đ */ + /* todo: many more */ + default: return g_unichar_tolower (uc); + } +} + +/** + * gx_utf8_flatten: + * @str: a UTF-8 string + * @len: the length of @str, or -1 if it is %NULL-terminated + * + * Flatten some UTF-8 string; that is, downcase it and remove any diacritics. + * + * Returns: (transfer full): a flattened string, free with g_free(). + */ +static char* +gx_utf8_flatten (const gchar *str, gssize len) +{ + GString *gstr; + char *norm, *cur; + + g_return_val_if_fail (str, NULL); + + norm = g_utf8_normalize (str, len, G_NORMALIZE_ALL); + if (!norm) + return NULL; + + gstr = g_string_sized_new (strlen (norm)); + + for (cur = norm; cur && *cur; cur = g_utf8_next_char (cur)) + { + gunichar uc; + + uc = g_utf8_get_char (cur); + if (g_unichar_combining_class (uc) != 0) + continue; + + g_string_append_unichar (gstr, unichar_tolower(uc)); + } + + g_free (norm); + + return g_string_free (gstr, FALSE); +} + +} // namespace + +std::string // gx_utf8_flatten +Mu::utf8_flatten (const char *str) +{ + if (!str) + return {}; + + // the pure-ascii case + if (g_str_is_ascii(str)) { + auto l = g_ascii_strdown (str, -1); + std::string s{l}; + g_free (l); + return s; + } + + // seems we need the big guns + char *flat = gx_utf8_flatten (str, -1); + if (!flat) + return {}; + + std::string s{flat}; + g_free (flat); + + return s; +} + +std::string +Mu::utf8_clean (const std::string& dirty) +{ + GString *gstr = g_string_sized_new (dirty.length()); + + for (auto cur = dirty.c_str(); cur && *cur; cur = g_utf8_next_char (cur)) { + + const gunichar uc = g_utf8_get_char (cur); + if (g_unichar_iscntrl (uc)) + g_string_append_c (gstr, ' '); + else + g_string_append_unichar (gstr, uc); + } + + std::string clean(gstr->str, gstr->len); + g_string_free (gstr, TRUE); + + clean.erase (0, clean.find_first_not_of(" ")); + clean.erase (clean.find_last_not_of(" ") + 1); // remove trailing space + + return clean; +} + +std::vector +Mu::split (const std::string& str, const std::string& sepa) +{ + char **parts = g_strsplit(str.c_str(), sepa.c_str(), -1); + std::vector vec; + for (auto part = parts; part && *part; ++part) + vec.push_back (*part); + + g_strfreev(parts); + + return vec; +} + +std::string +Mu::quote (const std::string& str) +{ + char *s = g_strescape (str.c_str(), NULL); + if (!s) + return {}; + + std::string res (s); + g_free (s); + + return "\"" + res + "\""; +} + + std::string + Mu::format (const char *frm, ...) + { + va_list args; + + va_start (args, frm); + auto str = format(frm, args); + va_end (args); + + return str; + } + +std::string +Mu::format (const char *frm, va_list args) +{ + char *s{}; + const auto res = g_vasprintf (&s, frm, args); + if (res == -1) { + std::cerr << "string format failed" << std::endl; + return {}; + } + + std::string str{s}; + g_free (s); + + return str; +} + + +constexpr const auto InternalDateFormat = "%010" G_GINT64_FORMAT; +constexpr const char InternalDateMin[] = "0000000000"; +constexpr const char InternalDateMax[] = "9999999999"; +static_assert(sizeof(InternalDateMin) == 10 + 1, "invalid"); +static_assert(sizeof(InternalDateMax) == 10 + 1, "invalid"); + +static std::string +date_boundary (bool is_first) +{ + return is_first ? InternalDateMin : InternalDateMax; +} + +std::string +Mu::date_to_time_t_string (int64_t t) +{ + char buf[sizeof(InternalDateMax)]; + g_snprintf (buf, sizeof(buf), InternalDateFormat, t); + + return buf; +} + +static std::string +delta_ymwdhMs (const std::string& expr) +{ + char *endptr; + auto num = strtol (expr.c_str(), &endptr, 10); + if (num <= 0 || num > 9999 || !endptr || !*endptr) + return date_boundary (true); + + int years, months, weeks, days, hours, minutes, seconds; + years = months = weeks = days = hours = minutes = seconds = 0; + + switch (endptr[0]) { + case 's': seconds = num; break; + case 'M': minutes = num; break; + case 'h': hours = num; break; + case 'd': days = num; break; + case 'w': weeks = num; break; + case 'm': months = num; break; + case 'y': years = num; break; + default: + return date_boundary (true); + } + + GDateTime *then, *now = g_date_time_new_now_local (); + if (weeks != 0) + then = g_date_time_add_weeks (now, -weeks); + else + then = g_date_time_add_full (now, -years, -months,-days, + -hours, -minutes, -seconds); + + time_t t = MAX (0, (gint64)g_date_time_to_unix (then)); + + g_date_time_unref (then); + g_date_time_unref (now); + + return date_to_time_t_string (t); +} + +static std::string +special_date (const std::string& d, bool is_first) +{ + if (d == "now") + return date_to_time_t_string (time(NULL)); + + else if (d == "today") { + + GDateTime *dt, *midnight; + dt = g_date_time_new_now_local (); + + if (!is_first) { + GDateTime *tmp = dt; + dt = g_date_time_add_days (dt, 1); + g_date_time_unref (tmp); + } + + midnight = g_date_time_add_full (dt, 0, 0, 0, + -g_date_time_get_hour(dt), + -g_date_time_get_minute (dt), + -g_date_time_get_second (dt)); + time_t t = MAX(0, (gint64)g_date_time_to_unix (midnight)); + g_date_time_unref (dt); + g_date_time_unref (midnight); + return date_to_time_t_string ((time_t)t); + + } else + return date_boundary (is_first); +} + +// if a date has a month day greater than the number of days in that month, +// change it to a valid date point to the last second in that month +static void +fixup_month (struct tm *tbuf) +{ + decltype(tbuf->tm_mday) max_days; + const auto month = tbuf->tm_mon + 1; + const auto year = tbuf->tm_year + 1900; + + switch (month) { + case 2: + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + max_days = 29; + else + max_days = 28; + break; + case 4: + case 6: + case 9: + case 11: + max_days = 30; + break; + default: + max_days = 31; + break; + } + + if (tbuf->tm_mday > max_days) { + tbuf->tm_mday = max_days; + tbuf->tm_hour = 23; + tbuf->tm_min = 59; + tbuf->tm_sec = 59; + } +} + +std::string +Mu::date_to_time_t_string (const std::string& dstr, bool is_first) +{ + gint64 t; + struct tm tbuf; + GDateTime *dtime; + + /* one-sided dates */ + if (dstr.empty()) + return date_boundary (is_first); + else if (dstr == "today" || dstr == "now") + return special_date (dstr, is_first); + + else if (dstr.find_first_of("ymdwhMs") != std::string::npos) + return delta_ymwdhMs (dstr); + + constexpr char UserDateMin[] = "19700101000000"; + constexpr char UserDateMax[] = "29991231235959"; + + std::string date (is_first ? UserDateMin : UserDateMax); + std::copy_if (dstr.begin(), dstr.end(), date.begin(),[](auto c){return isdigit(c);}); + + memset (&tbuf, 0, sizeof tbuf); + if (!strptime (date.c_str(), "%Y%m%d%H%M%S", &tbuf) && + !strptime (date.c_str(), "%Y%m%d%H%M", &tbuf) && + !strptime (date.c_str(), "%Y%m%d", &tbuf) && + !strptime (date.c_str(), "%Y%m", &tbuf) && + !strptime (date.c_str(), "%Y", &tbuf)) + return date_boundary (is_first); + + fixup_month(&tbuf); + + dtime = g_date_time_new_local (tbuf.tm_year + 1900, + tbuf.tm_mon + 1, + tbuf.tm_mday, + tbuf.tm_hour, + tbuf.tm_min, + tbuf.tm_sec); + if (!dtime) { + g_warning ("invalid %s date '%s'", + is_first ? "lower" : "upper", date.c_str()); + return date_boundary (is_first); + } + + t = g_date_time_to_unix (dtime); + g_date_time_unref (dtime); + + if (t < 0 || t > 9999999999) + return date_boundary (is_first); + else + return date_to_time_t_string (t); +} + +constexpr const auto SizeFormat = "%010" G_GINT64_FORMAT; + +constexpr const char SizeMin[] = "0000000000"; +constexpr const char SizeMax[] = "9999999999"; +static_assert(sizeof(SizeMin) == 10 + 1, "invalid"); +static_assert(sizeof(SizeMax) == 10 + 1, "invalid"); + +static std::string +size_boundary (bool is_first) +{ + return is_first ? SizeMin : SizeMax; +} + +std::string +Mu::size_to_string (int64_t size) +{ + char buf[sizeof(SizeMax)]; + g_snprintf (buf, sizeof(buf), SizeFormat, size); + + return buf; +} + +std::string +Mu::size_to_string (const std::string& val, bool is_first) +{ + std::string str; + GRegex *rx; + GMatchInfo *minfo; + + /* one-sided ranges */ + if (val.empty()) + return size_boundary (is_first); + + rx = g_regex_new ("(\\d+)(b|k|kb|m|mb|g|gb)?", + G_REGEX_CASELESS, (GRegexMatchFlags)0, NULL); + minfo = NULL; + if (g_regex_match (rx, val.c_str(), (GRegexMatchFlags)0, &minfo)) { + gint64 size; + char *s; + + s = g_match_info_fetch (minfo, 1); + size = atoll (s); + g_free (s); + + s = g_match_info_fetch (minfo, 2); + switch (s ? g_ascii_tolower(s[0]) : 0) { + case 'k': size *= 1024; break; + case 'm': size *= (1024 * 1024); break; + case 'g': size *= (1024 * 1024 * 1024); break; + default: break; + } + + g_free (s); + str = size_to_string (size); + } else + str = size_boundary (is_first); + + g_regex_unref (rx); + g_match_info_unref (minfo); + + return str; +} + +void +Mu::assert_equal(const std::string& s1, const std::string& s2) +{ + g_assert_cmpstr (s1.c_str(), ==, s2.c_str()); +} + +void +Mu::assert_equal (const Mu::StringVec& v1, const Mu::StringVec& v2) +{ + g_assert_cmpuint(v1.size(), ==, v2.size()); + + for (auto i = 0U; i != v1.size(); ++i) + assert_equal(v1[i], v2[i]); +} + + +void +Mu::allow_warnings() +{ + g_test_log_set_fatal_handler( + [](const char*, GLogLevelFlags, const char*, gpointer) { + return FALSE; + },{}); + +} diff --git a/lib/utils/mu-utils.hh b/lib/utils/mu-utils.hh new file mode 100644 index 0000000..0c35170 --- /dev/null +++ b/lib/utils/mu-utils.hh @@ -0,0 +1,271 @@ +/* +** Copyright (C) 2017 Dirk-Jan C. Binnema +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + +#ifndef __MU_UTILS_HH__ +#define __MU_UTILS_HH__ + +#include +#include +#include +#include +#include +#include + +namespace Mu { + +using StringVec = std::vector; + +/** + * Flatten a string -- downcase and fold diacritics etc. + * + * @param str a string + * + * @return a flattened string + */ +std::string utf8_flatten (const char *str); +inline std::string utf8_flatten (const std::string& s) { return utf8_flatten(s.c_str()); } + + + +/** + * Replace all control characters with spaces, and remove leading and trailing space. + * + * @param dirty an unclean string + * + * @return a cleaned-up string. + */ +std::string utf8_clean (const std::string& dirty); + + +/** + * Split a string in parts + * + * @param str a string + * @param sepa the separator + * + * @return the parts. + */ +std::vector split (const std::string& str, + const std::string& sepa); + +/** + * Quote & escape a string + * + * @param str a string + * + * @return quoted string + */ +std::string quote (const std::string& str); + +/** + * Format a string, printf style + * + * @param frm format string + * @param ... parameters + * + * @return a formatted string + */ +std::string format (const char *frm, ...) __attribute__((format(printf, 1, 2))); + +/** + * Format a string, printf style + * + * @param frm format string + * @param ... parameters + * + * @return a formatted string + */ +std::string format (const char *frm, va_list args) __attribute__((format(printf, 1, 0))); + + +/** + * Convert an date to the corresponding time expressed as a string with a + * 10-digit time_t + * + * @param date the date expressed a YYYYMMDDHHMMSS or any n... of the first + * characters. + * @param first whether to fill out incomplete dates to the start or the end; + * ie. either 1972 -> 197201010000 or 1972 -> 197212312359 + * + * @return the corresponding time_t expressed as a string + */ +std::string date_to_time_t_string (const std::string& date, bool first); + +/** + * 64-bit incarnation of time_t expressed as a 10-digit string. Uses 64-bit for the time-value, + * regardless of the size of time_t. + * + * @param t some time value + * + * @return + */ +std::string date_to_time_t_string (int64_t t); + + + +/** + * Convert a size string to a size in bytes + * + * @param sizestr the size string + * @param first + * + * @return the size expressed as a string with the decimal number of bytes + */ +std::string size_to_string (const std::string& sizestr, bool first); + +/** + * Convert a size into a size in bytes string + * + * @param size the size + * @param first + * + * @return the size expressed as a string with the decimal number of bytes + */ +std::string size_to_string (int64_t size); + + +/** + * Convert any ostreamable<< value to a string + * + * @param t the value + * + * @return a std::string + */ +template +static inline std::string to_string (const T& val) +{ + std::stringstream sstr; + sstr << val; + + return sstr.str(); +} + + +/** + * + * don't repeat these catch blocks everywhere... + * + */ + +#define MU_XAPIAN_CATCH_BLOCK \ + catch (const Xapian::Error &xerr) { \ + g_critical ("%s: xapian error '%s'", \ + __func__, xerr.get_msg().c_str()); \ + } catch (const std::runtime_error& re) { \ + g_critical ("%s: error: %s", __func__, re.what()); \ + } catch (...) { \ + g_critical ("%s: caught exception", __func__); \ + } + +#define MU_XAPIAN_CATCH_BLOCK_G_ERROR(GE,E) \ + catch (const Xapian::DatabaseLockError &xerr) { \ + mu_util_g_set_error ((GE), \ + MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK, \ + "%s: xapian error '%s'", \ + __func__, xerr.get_msg().c_str()); \ + } catch (const Xapian::DatabaseError &xerr) { \ + mu_util_g_set_error ((GE),MU_ERROR_XAPIAN, \ + "%s: xapian error '%s'", \ + __func__, xerr.get_msg().c_str()); \ + } catch (const Xapian::Error &xerr) { \ + mu_util_g_set_error ((GE),(E), \ + "%s: xapian error '%s'", \ + __func__, xerr.get_msg().c_str()); \ + } catch (const std::runtime_error& ex) { \ + mu_util_g_set_error ((GE),(MU_ERROR_INTERNAL), \ + "%s: error: %s", __func__, ex.what()); \ + \ + } catch (...) { \ + mu_util_g_set_error ((GE),(MU_ERROR_INTERNAL), \ + "%s: caught exception", __func__); \ + } + + +#define MU_XAPIAN_CATCH_BLOCK_RETURN(R) \ + catch (const Xapian::Error &xerr) { \ + g_critical ("%s: xapian error '%s'", \ + __func__, xerr.get_msg().c_str()); \ + return (R); \ + } catch (const std::runtime_error& ex) { \ + g_critical("%s: error: %s", __func__, ex.what()); \ + return (R); \ + } catch (...) { \ + g_critical ("%s: caught exception", __func__); \ + return (R); \ + } + +#define MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(GE,E,R) \ + catch (const Xapian::Error &xerr) { \ + mu_util_g_set_error ((GE),(E), \ + "%s: xapian error '%s'", \ + __func__, xerr.get_msg().c_str()); \ + return (R); \ + } catch (const std::runtime_error& ex) { \ + mu_util_g_set_error ((GE),(MU_ERROR_INTERNAL), \ + "%s: error: %s", __func__, ex.what()); \ + return (R); \ + } catch (...) { \ + if ((GE)&&!(*(GE))) \ + mu_util_g_set_error ((GE), \ + (MU_ERROR_INTERNAL), \ + "%s: caught exception", __func__); \ + return (R); \ + } + + + + +/// Allow using enum structs as bitflags +#define MU_TO_NUM(ET,ELM) std::underlying_type_t(ELM) +#define MU_TO_ENUM(ET,NUM) static_cast(NUM) +#define MU_ENABLE_BITOPS(ET) \ + constexpr ET operator& (ET e1, ET e2) { return MU_TO_ENUM(ET,MU_TO_NUM(ET,e1)&MU_TO_NUM(ET,e2)); } \ + constexpr ET operator| (ET e1, ET e2) { return MU_TO_ENUM(ET,MU_TO_NUM(ET,e1)|MU_TO_NUM(ET,e2)); } \ + constexpr ET operator~ (ET e) { return MU_TO_ENUM(ET,~(MU_TO_NUM(ET, e))); } \ + constexpr bool any_of(ET e) { return MU_TO_NUM(ET,e) != 0; } \ + constexpr bool none_of(ET e) { return MU_TO_NUM(ET,e) == 0; } \ + static inline ET& operator&=(ET& e1, ET e2) { return e1 = e1 & e2;} \ + static inline ET& operator|=(ET& e1, ET e2) { return e1 = e1 | e2;} + + +/** + * For unit tests, assert two std::string's are equal. + * + * @param s1 string1 + * @param s2 string2 + */ +void assert_equal(const std::string& s1, const std::string& s2); +/** + * For unit tests, assert that to containers are the same. + * + * @param c1 container1 + * @param c2 container2 + */ +void assert_equal (const StringVec& v1, const StringVec& v2); + +/** + * For unit-tests, allow warnings in the current function. + * + */ +void allow_warnings(); + +} // namespace Mu + + +#endif /* __MU_UTILS_HH__ */ diff --git a/lib/utils/test-command-parser.cc b/lib/utils/test-command-parser.cc new file mode 100644 index 0000000..f18e642 --- /dev/null +++ b/lib/utils/test-command-parser.cc @@ -0,0 +1,147 @@ +/* +** Copyright (C) 2017 Dirk-Jan C. Binnema +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + +#include +#include + +#include +#include + +#include "mu-command-parser.hh" +#include "mu-utils.hh" + +using namespace Mu; + +static void +test_param_getters() +{ + const auto node { Sexp::parse(R"((foo :bar 123 :cuux "456" :boo nil :bah true))")}; + + std::cout << node << "\n"; + + g_assert_cmpint(Command::get_int_or(node.children,"bar"), ==, 123); + assert_equal(Command::get_string_or(node.children, "bra", "bla"), "bla"); + assert_equal(Command::get_string_or(node.children, "cuux"), "456"); + + g_assert_true(Command::get_bool_or(node.children,"boo") == false); + g_assert_true(Command::get_bool_or(node.children,"bah") == true); +} + + +static bool +call (const Command::CommandMap& cmap, const std::string& sexp) try +{ + const auto node{Sexp::parse(sexp)}; + g_message ("invoking %s", to_string(node).c_str()); + + invoke (cmap, node); + + return true; + +} catch (const Error& err) { + g_warning ("%s", err.what()); + return false; +} + +static void +test_command() +{ + using namespace Command; + allow_warnings(); + + CommandMap cmap; + + + cmap.emplace("my-command", + CommandInfo{ + ArgMap{ {"param1", ArgInfo{Sexp::Type::String, true, "some string" }}, + {"param2", ArgInfo{Sexp::Type::Integer, false, "some integer"}}}, + "My command,", + {}}); + + //std::cout << cmap << "\n"; + + g_assert_true(call(cmap, "(my-command :param1 \"hello\")")); + g_assert_true(call(cmap, "(my-command :param1 \"hello\" :param2 123)")); + + g_assert_false(call(cmap, "(my-command :param1 \"hello\" :param2 123 :param3 xxx)")); +} + +static void +test_command2() +{ + using namespace Command; + allow_warnings(); + + CommandMap cmap; + cmap.emplace("bla", + CommandInfo{ + ArgMap{ + {"foo", ArgInfo{Sexp::Type::Integer, false, "foo"}}, + {"bar", ArgInfo{Sexp::Type::String, false, "bar"}}, + },"yeah", + [&](const auto& params){}}); + + + g_assert_true (call(cmap, "(bla :foo nil)")); + g_assert_false (call(cmap, "(bla :foo nil :bla nil)")); +} + + +static void +test_command_fail() +{ + using namespace Command; + + allow_warnings(); + + CommandMap cmap; + + cmap.emplace("my-command", + CommandInfo{ + ArgMap{ {"param1", ArgInfo{Sexp::Type::String, true, "some string" }}, + {"param2", ArgInfo{Sexp::Type::Integer, false, "some integer"}}}, + "My command,", + {}}); + + g_assert_false (call(cmap, "(my-command)")); + g_assert_false (call(cmap, "(my-command2)")); + g_assert_false(call(cmap, "(my-command :param1 123 :param2 123)")); + g_assert_false(call(cmap, "(my-command :param1 \"hello\" :param2 \"123\")")); + +} + + +int +main (int argc, char *argv[]) try +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/utils/command-parser/param-getters", test_param_getters); + g_test_add_func ("/utils/command-parser/command", test_command); + g_test_add_func ("/utils/command-parser/command2", test_command2); + g_test_add_func ("/utils/command-parser/command-fail", test_command_fail); + + return g_test_run (); + + +} catch (const std::runtime_error& re) { + std::cerr << re.what() << "\n"; + return 1; +} diff --git a/lib/utils/test-mu-str.c b/lib/utils/test-mu-str.c new file mode 100644 index 0000000..75fc71f --- /dev/null +++ b/lib/utils/test-mu-str.c @@ -0,0 +1,275 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include +#include +#include +#include + +#include + +#include "mu-str.h" + + +static void +test_mu_str_size_01 (void) +{ + struct lconv *lc; + char *tmp2; + + lc = localeconv(); + + g_assert_cmpstr (mu_str_size_s (0), ==, "0 bytes"); + + tmp2 = g_strdup_printf ("97%s7 KB", lc->decimal_point); + g_assert_cmpstr (mu_str_size_s (100000), ==, tmp2); + g_free (tmp2); + + tmp2 = g_strdup_printf ("1%s0 MB", lc->decimal_point); + g_assert_cmpstr (mu_str_size_s (1100*1000), ==, tmp2); + g_free (tmp2); +} + + + +static void +test_mu_str_size_02 (void) +{ + struct lconv *lc; + char *tmp1, *tmp2; + + lc = localeconv(); + + tmp2 = g_strdup_printf ("1%s0 MB", lc->decimal_point); + tmp1 = mu_str_size (999999); + g_assert_cmpstr (tmp1, !=, tmp2); + + g_free (tmp1); + g_free (tmp2); +} + +static void +test_mu_str_esc_to_list (void) +{ + int i; + struct { + const char* str; + const char* strs[3]; + } strings [] = { + { "maildir:foo", + {"maildir:foo", NULL, NULL}}, + { "maildir:sent items", + {"maildir:sent", "items", NULL}}, + { "\"maildir:sent items\"", + {"maildir:sent items", NULL, NULL}}, + }; + + for (i = 0; i != G_N_ELEMENTS(strings); ++i) { + GSList *lst, *cur; + unsigned u; + lst = mu_str_esc_to_list (strings[i].str); + for (cur = lst, u = 0; cur; cur = g_slist_next(cur), ++u) + g_assert_cmpstr ((const char*)cur->data,==, + strings[i].strs[u]); + mu_str_free_list (lst); + } +} + + + +static void +assert_cmplst (GSList *lst, const char *items[]) +{ + int i; + + if (!lst) + g_assert (!items); + + for (i = 0; lst; lst = g_slist_next(lst), ++i) + g_assert_cmpstr ((char*)lst->data,==,items[i]); + + g_assert (items[i] == NULL); +} + + +static GSList* +create_list (const char *items[]) +{ + GSList *lst; + + lst = NULL; + while (items && *items) { + lst = g_slist_prepend (lst, g_strdup(*items)); + ++items; + } + + return g_slist_reverse (lst); + +} + +static void +test_mu_str_from_list (void) +{ + { + const char *strs[] = {"aap", "noot", "mies", NULL}; + GSList *lst = create_list (strs); + gchar *str = mu_str_from_list (lst, ','); + g_assert_cmpstr ("aap,noot,mies", ==, str); + mu_str_free_list (lst); + g_free (str); + } + + { + const char *strs[] = {"aap", "no,ot", "mies", NULL}; + GSList *lst = create_list (strs); + gchar *str = mu_str_from_list (lst, ','); + g_assert_cmpstr ("aap,no,ot,mies", ==, str); + mu_str_free_list (lst); + g_free (str); + } + + { + const char *strs[] = {NULL}; + GSList *lst = create_list (strs); + gchar *str = mu_str_from_list (lst,'@'); + g_assert_cmpstr (NULL, ==, str); + mu_str_free_list (lst); + g_free (str); + } + + +} + + +static void +test_mu_str_to_list (void) +{ + { + const char *items[]= {"foo", "bar ", "cuux", NULL}; + GSList *lst = mu_str_to_list ("foo@bar @cuux",'@', FALSE); + assert_cmplst (lst, items); + mu_str_free_list (lst); + } + + { + GSList *lst = mu_str_to_list (NULL,'x',FALSE); + g_assert (lst == NULL); + mu_str_free_list (lst); + } +} + +static void +test_mu_str_to_list_strip (void) +{ + const char *items[]= {"foo", "bar", "cuux", NULL}; + GSList *lst = mu_str_to_list ("foo@bar @cuux",'@', TRUE); + assert_cmplst (lst, items); + mu_str_free_list (lst); +} + + +static void +test_mu_str_replace (void) +{ + unsigned u; + struct { + const char* str; + const char* sub; + const char *repl; + const char *exp; + } strings [] = { + { "hello", "ll", "xx", "hexxo" }, + { "hello", "hello", "hi", "hi" }, + { "hello", "foo", "bar", "hello" } + }; + + for (u = 0; u != G_N_ELEMENTS(strings); ++u) { + char *res; + res = mu_str_replace (strings[u].str, + strings[u].sub, + strings[u].repl); + g_assert_cmpstr (res,==,strings[u].exp); + g_free (res); + } +} + + +static void +test_mu_str_remove_ctrl_in_place (void) +{ + unsigned u; + struct { + char *str; + const char *exp; + } strings [] = { + { g_strdup(""), ""}, + { g_strdup("hello, world!"), "hello, world!" }, + { g_strdup("hello,\tworld!"), "hello, world!" }, + { g_strdup("hello,\n\nworld!"), "hello, world!", }, + { g_strdup("hello,\x1f\x1e\x1ew\nor\nld!"), "hello,w or ld!" }, + { g_strdup("\x1ehello, world!\x1f"), "hello, world!" } + }; + + for (u = 0; u != G_N_ELEMENTS(strings); ++u) { + char *res; + res = mu_str_remove_ctrl_in_place (strings[u].str); + g_assert_cmpstr (res,==,strings[u].exp); + g_free (strings[u].str); + } +} + + +int +main (int argc, char *argv[]) +{ + setlocale (LC_ALL, ""); + + g_test_init (&argc, &argv, NULL); + + /* mu_str_size */ + g_test_add_func ("/mu-str/mu-str-size-01", + test_mu_str_size_01); + g_test_add_func ("/mu-str/mu-str-size-02", + test_mu_str_size_02); + + g_test_add_func ("/mu-str/mu-str-from-list", + test_mu_str_from_list); + g_test_add_func ("/mu-str/mu-str-to-list", + test_mu_str_to_list); + g_test_add_func ("/mu-str/mu-str-to-list-strip", + test_mu_str_to_list_strip); + + g_test_add_func ("/mu-str/mu-str-replace", + test_mu_str_replace); + + g_test_add_func ("/mu-str/mu-str-esc-to-list", + test_mu_str_esc_to_list); + + g_test_add_func ("/mu-str/mu_str_remove_ctrl_in_place", + test_mu_str_remove_ctrl_in_place); + + + return g_test_run (); +} diff --git a/lib/utils/test-mu-util.c b/lib/utils/test-mu-util.c new file mode 100644 index 0000000..f3b0277 --- /dev/null +++ b/lib/utils/test-mu-util.c @@ -0,0 +1,248 @@ +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include +#include + +#include +#include +#include + +#include "mu-util.h" + +static void +test_mu_util_dir_expand_00 (void) +{ +#ifdef HAVE_WORDEXP_H + gchar *got, *expected; + + got = mu_util_dir_expand ("~/IProbablyDoNotExist"); + expected = g_strdup_printf ("%s%cIProbablyDoNotExist", + getenv("HOME"), G_DIR_SEPARATOR); + + g_assert_cmpstr (got,==,expected); + + g_free (got); + g_free (expected); +#endif /*HAVE_WORDEXP_H*/ +} + +static void +test_mu_util_dir_expand_01 (void) +{ + /* XXXX: the testcase does not work when using some dir + * setups; (see issue #585), although the code should still + * work. Turn of the test for now */ + return; + + +#ifdef HAVE_WORDEXP_H + { + gchar *got, *expected; + + got = mu_util_dir_expand ("~/Desktop"); + expected = g_strdup_printf ("%s%cDesktop", + getenv("HOME"), G_DIR_SEPARATOR); + + g_assert_cmpstr (got,==,expected); + + g_free (got); + g_free (expected); + } +#endif /*HAVE_WORDEXP_H*/ +} + + + +static void +test_mu_util_guess_maildir_01 (void) +{ + char *got; + const char *expected; + + /* skip the test if there's no /tmp */ + if (access ("/tmp", F_OK)) + return; + + g_setenv ("MAILDIR", "/tmp", TRUE); + + got = mu_util_guess_maildir (); + expected = "/tmp"; + + g_assert_cmpstr (got,==,expected); + g_free (got); +} + + +static void +test_mu_util_guess_maildir_02 (void) +{ + char *got, *mdir; + + g_unsetenv ("MAILDIR"); + + mdir = g_strdup_printf ("%s%cMaildir", + getenv("HOME"), G_DIR_SEPARATOR); + got = mu_util_guess_maildir (); + + if (access (mdir, F_OK) == 0) + g_assert_cmpstr (got, ==, mdir); + else + g_assert_cmpstr (got, == , NULL); + + g_free (got); + g_free (mdir); +} + + +static void +test_mu_util_check_dir_01 (void) +{ + if (g_access ("/usr/bin", F_OK) == 0) { + g_assert_cmpuint ( + mu_util_check_dir ("/usr/bin", TRUE, FALSE) == TRUE, + ==, + g_access ("/usr/bin", R_OK) == 0); + } +} + + +static void +test_mu_util_check_dir_02 (void) +{ + if (g_access ("/tmp", F_OK) == 0) { + g_assert_cmpuint ( + mu_util_check_dir ("/tmp", FALSE, TRUE) == TRUE, + ==, + g_access ("/tmp", W_OK) == 0); + } +} + + +static void +test_mu_util_check_dir_03 (void) +{ + if (g_access (".", F_OK) == 0) { + g_assert_cmpuint ( + mu_util_check_dir (".", TRUE, TRUE) == TRUE, + ==, + g_access (".", W_OK | R_OK) == 0); + } +} + + +static void +test_mu_util_check_dir_04 (void) +{ + /* not a dir, so it must be false */ + g_assert_cmpuint ( + mu_util_check_dir ("test-util.c", TRUE, TRUE), + ==, + FALSE); +} + +static void +test_mu_util_get_dtype_with_lstat (void) +{ + g_assert_cmpuint ( + mu_util_get_dtype_with_lstat (MU_TESTMAILDIR), ==, DT_DIR); + g_assert_cmpuint ( + mu_util_get_dtype_with_lstat (MU_TESTMAILDIR2), ==, DT_DIR); + g_assert_cmpuint ( + mu_util_get_dtype_with_lstat (MU_TESTMAILDIR2 "/Foo/cur/mail5"), + ==, DT_REG); +} + + +static void +test_mu_util_supports (void) +{ + gboolean has_guile; + gchar *path; + + has_guile = FALSE; +#ifdef BUILD_GUILE + has_guile = TRUE; +#endif /*BUILD_GUILE*/ + + g_assert_cmpuint (mu_util_supports (MU_FEATURE_GUILE), == ,has_guile); + g_assert_cmpuint (mu_util_supports (MU_FEATURE_CRYPTO), == ,TRUE); + + path = g_find_program_in_path ("gnuplot"); + g_free (path); + + g_assert_cmpuint (mu_util_supports (MU_FEATURE_GNUPLOT),==, + path ? TRUE : FALSE); + + g_assert_cmpuint ( + mu_util_supports (MU_FEATURE_GNUPLOT|MU_FEATURE_GUILE| + MU_FEATURE_CRYPTO), + ==, + has_guile && path ? TRUE : FALSE); +} + + +static void +test_mu_util_program_in_path (void) +{ + g_assert_cmpuint (mu_util_program_in_path("ls"),==,TRUE); +} + + + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + /* mu_util_dir_expand */ + g_test_add_func ("/mu-util/mu-util-dir-expand-00", + test_mu_util_dir_expand_00); + g_test_add_func ("/mu-util/mu-util-dir-expand-01", + test_mu_util_dir_expand_01); + + /* mu_util_guess_maildir */ + g_test_add_func ("/mu-util/mu-util-guess-maildir-01", + test_mu_util_guess_maildir_01); + g_test_add_func ("/mu-util/mu-util-guess-maildir-02", + test_mu_util_guess_maildir_02); + + /* mu_util_check_dir */ + g_test_add_func ("/mu-util/mu-util-check-dir-01", + test_mu_util_check_dir_01); + g_test_add_func ("/mu-util/mu-util-check-dir-02", + test_mu_util_check_dir_02); + g_test_add_func ("/mu-util/mu-util-check-dir-03", + test_mu_util_check_dir_03); + g_test_add_func ("/mu-util/mu-util-check-dir-04", + test_mu_util_check_dir_04); + + g_test_add_func ("/mu-util/mu-util-get-dtype-with-lstat", + test_mu_util_get_dtype_with_lstat); + + g_test_add_func ("/mu-util/mu-util-supports", test_mu_util_supports); + g_test_add_func ("/mu-util/mu-util-program-in-path", + test_mu_util_program_in_path); + + return g_test_run (); +} diff --git a/lib/utils/test-sexp-parser.cc b/lib/utils/test-sexp-parser.cc new file mode 100644 index 0000000..0dccf96 --- /dev/null +++ b/lib/utils/test-sexp-parser.cc @@ -0,0 +1,76 @@ +/* +** Copyright (C) 2020 Dirk-Jan C. Binnema +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + +#include +#include + +#include +#include + +#include "mu-command-parser.hh" +#include "mu-utils.hh" + +using namespace Mu; + +static bool +check_parse (const std::string& expr, const std::string& expected) +{ + try { + const auto parsed{to_string(Sexp::parse(expr))}; + g_assert_cmpstr(parsed.c_str(), ==, expected.c_str()); + return true; + + } catch (const Error& err) { + g_warning ("caught exception parsing '%s': %s", expr.c_str(), err.what()); + return false; + } +} + +static void +test_parser() +{ + check_parse(R"(:foo-123)", "{:foo-123}"); + check_parse(R"("foo")", "{foo}"); + check_parse(R"(12345)", "{12345}"); + check_parse(R"(-12345)", "{-12345}"); + check_parse(R"((123 bar "cuux"))", "({123}{bar}{cuux})"); + + check_parse(R"("\"")", "{\"}"); + check_parse(R"("\\")", "{\\}"); +} + +int +main (int argc, char *argv[]) try +{ + g_test_init (&argc, &argv, NULL); + + if (argc == 2) { + std::cout << Sexp::parse(argv[1]) << '\n'; + return 0; + } + + g_test_add_func ("/utils/command-parser/parse", test_parser); + + return g_test_run (); + + +} catch (const std::runtime_error& re) { + std::cerr << re.what() << "\n"; + return 1; +} diff --git a/lib/utils/test-utils.cc b/lib/utils/test-utils.cc new file mode 100644 index 0000000..b1f666e --- /dev/null +++ b/lib/utils/test-utils.cc @@ -0,0 +1,206 @@ +/* +** Copyright (C) 2017 Dirk-Jan C. Binnema +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public License +** as published by the Free Software Foundation; either version 2.1 +** of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; if not, write to the Free +** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +** 02110-1301, USA. +*/ + +#include +#include + +#include +#include +#include + +#include "mu-utils.hh" + +using namespace Mu; + +struct Case { + const std::string expr; + bool is_first{}; + const std::string expected; +}; +using CaseVec = std::vector; +using ProcFunc = std::function; + + +static void +test_cases(const CaseVec& cases, ProcFunc proc) +{ + for (const auto& casus : cases ) { + + const auto res = proc(casus.expr, casus.is_first); + if (g_test_verbose()) { + std::cout << "\n"; + std::cout << casus.expr << ' ' << casus.is_first << std::endl; + std::cout << "exp: '" << casus.expected << "'" << std::endl; + std::cout << "got: '" << res << "'" << std::endl; + } + + g_assert_true (casus.expected == res); + } +} + +static void +test_date_basic () +{ + g_setenv ("TZ", "Europe/Helsinki", TRUE); + + CaseVec cases = { + { "2015-09-18T09:10:23", true, "1442556623" }, + { "1972-12-14T09:10:23", true, "0093165023" }, + { "1854-11-18T17:10:23", true, "0000000000" }, + + { "2000-02-31T09:10:23", true, "0951861599" }, + { "2000-02-29T23:59:59", true, "0951861599" }, + + { "2016", true, "1451599200" }, + { "2016", false, "1483221599" }, + + { "fnorb", true, "0000000000" }, + { "fnorb", false, "9999999999" }, + { "", false, "9999999999" }, + { "", true, "0000000000" } + }; + + test_cases (cases, [](auto s, auto f){ return date_to_time_t_string(s,f); }); +} + +static void +test_date_ymwdhMs (void) +{ + struct { + std::string expr; + long diff; + int tolerance; + } tests[] = { + { "3h", 3 * 60 * 60, 1 }, + { "21d", 21 * 24 * 60 * 60, 3600 + 1 }, + { "2w", 2 * 7 * 24 * 60 * 60, 3600 + 1 }, + + { "2y", 2 * 365 * 24 * 60 * 60, 24 * 3600 + 1 }, + { "3m", 3 * 30 * 24 * 60 * 60, 3 * 24 * 3600 + 1 } + }; + + for (auto i = 0; i != G_N_ELEMENTS(tests); ++i) { + const auto diff = time(NULL) - + strtol(Mu::date_to_time_t_string(tests[i].expr, true).c_str(), + NULL, 10); + if (g_test_verbose()) + std::cerr << tests[i].expr << ' ' + << diff << ' ' + << tests[i].diff << std::endl; + + g_assert_true (tests[i].diff - diff <= tests[i].tolerance); + } + + g_assert_true (strtol(Mu::date_to_time_t_string("-1y", true).c_str(), + NULL, 10) == 0); +} + +static void +test_size () +{ + CaseVec cases = { + { "456", true, "0000000456" }, + { "", false, "9999999999" }, + { "", true, "0000000000" }, + }; + + test_cases (cases, [](auto s, auto f){ return size_to_string(s,f); }); +} + + +static void +test_flatten () +{ + CaseVec cases = { + { "Менделе́ев", true, "менделеев" }, + { "", false, "" }, + { "Ångström", true, "angstrom" }, + }; + + test_cases (cases, [](auto s, auto f){ return utf8_flatten(s); }); +} + +static void +test_clean () +{ + CaseVec cases = { + { "\t a\t\nb ", true, "a b" }, + { "", false, "" }, + { "Ångström", true, "Ångström" }, + }; + + test_cases (cases, [](auto s, auto f){ return utf8_clean(s); }); +} + + +static void +test_format () +{ + g_assert_true (format ("hello %s, %u", "world", 123) == + "hello world, 123"); +} + + +enum struct Bits { None = 0, Bit1 = 1 << 0, Bit2 = 1 << 1 }; +MU_ENABLE_BITOPS(Bits); + +static void +test_define_bitmap() +{ + g_assert_cmpuint((guint)Bits::None,==,(guint)0); + g_assert_cmpuint((guint)Bits::Bit1,==,(guint)1); + g_assert_cmpuint((guint)Bits::Bit2,==,(guint)2); + + g_assert_cmpuint((guint)(Bits::Bit1|Bits::Bit2),==,(guint)3); + g_assert_cmpuint((guint)(Bits::Bit1&Bits::Bit2),==,(guint)0); + + g_assert_cmpuint((guint)(Bits::Bit1&(~Bits::Bit2)),==,(guint)1); + + { + Bits b{Bits::Bit1}; + b|=Bits::Bit2; + g_assert_cmpuint((guint)b,==,(guint)3); + } + + { + Bits b{Bits::Bit1}; + b&=Bits::Bit1; + g_assert_cmpuint((guint)b,==,(guint)1); + } + + +} + + + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/utils/date-basic", test_date_basic); + g_test_add_func ("/utils/date-ymwdhMs", test_date_ymwdhMs); + g_test_add_func ("/utils/size", test_size); + g_test_add_func ("/utils/flatten", test_flatten); + g_test_add_func ("/utils/clean", test_clean); + g_test_add_func ("/utils/format", test_format); + g_test_add_func ("/utils/define-bitmap", test_define_bitmap); + + return g_test_run (); +} diff --git a/m4/Makefile.am b/m4/Makefile.am new file mode 100644 index 0000000..eeb8a05 --- /dev/null +++ b/m4/Makefile.am @@ -0,0 +1,47 @@ +## Copyright (C) 2008-2020 Dirk-Jan C. Binnema +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +EXTRA_DIST= \ + ax_ac_append_to_file.m4 \ + ax_ac_print_to_file.m4 \ + ax_add_am_macro_static.m4 \ + ax_am_macros_static.m4 \ + ax_append_compile_flags.m4 \ + ax_append_flag.m4 \ + ax_append_link_flags.m4 \ + ax_check_compile_flag.m4 \ + ax_check_enable_debug.m4 \ + ax_check_gnu_make.m4 \ + ax_check_link_flag.m4 \ + ax_code_coverage.m4 \ + ax_compiler_flags.m4 \ + ax_compiler_flags_cflags.m4 \ + ax_compiler_flags_cxxflags.m4 \ + ax_compiler_flags_gir.m4 \ + ax_compiler_flags_ldflags.m4 \ + ax_cxx_compile_stdcxx.m4 \ + ax_cxx_compile_stdcxx_14.m4 \ + ax_file_escapes.m4 \ + ax_is_release.m4 \ + ax_lib_readline.m4 \ + ax_require_defined.m4 \ + ax_valgrind_check.m4 \ + guile-2.2.m4 \ + lib-ld.m4 \ + lib-link.m4 \ + lib-prefix.m4 diff --git a/m4/ax_ac_append_to_file.m4 b/m4/ax_ac_append_to_file.m4 new file mode 100644 index 0000000..242b3d5 --- /dev/null +++ b/m4/ax_ac_append_to_file.m4 @@ -0,0 +1,32 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_ac_append_to_file.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_AC_APPEND_TO_FILE([FILE],[DATA]) +# +# DESCRIPTION +# +# Appends the specified data to the specified Autoconf is run. If you want +# to append to a file when configure is run use AX_APPEND_TO_FILE instead. +# +# LICENSE +# +# Copyright (c) 2009 Allan Caffee +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 10 + +AC_DEFUN([AX_AC_APPEND_TO_FILE],[ +AC_REQUIRE([AX_FILE_ESCAPES]) +m4_esyscmd( +AX_FILE_ESCAPES +[ +printf "%s" "$2" >> "$1" +]) +]) diff --git a/m4/ax_ac_print_to_file.m4 b/m4/ax_ac_print_to_file.m4 new file mode 100644 index 0000000..642dfc1 --- /dev/null +++ b/m4/ax_ac_print_to_file.m4 @@ -0,0 +1,32 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_ac_print_to_file.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_AC_PRINT_TO_FILE([FILE],[DATA]) +# +# DESCRIPTION +# +# Writes the specified data to the specified file when Autoconf is run. If +# you want to print to a file when configure is run use AX_PRINT_TO_FILE +# instead. +# +# LICENSE +# +# Copyright (c) 2009 Allan Caffee +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 10 + +AC_DEFUN([AX_AC_PRINT_TO_FILE],[ +m4_esyscmd( +AC_REQUIRE([AX_FILE_ESCAPES]) +[ +printf "%s" "$2" > "$1" +]) +]) diff --git a/m4/ax_add_am_macro_static.m4 b/m4/ax_add_am_macro_static.m4 new file mode 100644 index 0000000..6442d24 --- /dev/null +++ b/m4/ax_add_am_macro_static.m4 @@ -0,0 +1,28 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_add_am_macro_static.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_ADD_AM_MACRO_STATIC([RULE]) +# +# DESCRIPTION +# +# Adds the specified rule to $AMINCLUDE. +# +# LICENSE +# +# Copyright (c) 2009 Tom Howard +# Copyright (c) 2009 Allan Caffee +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 8 + +AC_DEFUN([AX_ADD_AM_MACRO_STATIC],[ + AC_REQUIRE([AX_AM_MACROS_STATIC]) + AX_AC_APPEND_TO_FILE(AMINCLUDE_STATIC,[$1]) +]) diff --git a/m4/ax_am_macros_static.m4 b/m4/ax_am_macros_static.m4 new file mode 100644 index 0000000..f4cee8c --- /dev/null +++ b/m4/ax_am_macros_static.m4 @@ -0,0 +1,38 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_am_macros_static.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_AM_MACROS_STATIC +# +# DESCRIPTION +# +# Adds support for macros that create Automake rules. You must manually +# add the following line +# +# include $(top_srcdir)/aminclude_static.am +# +# to your Makefile.am files. +# +# LICENSE +# +# Copyright (c) 2009 Tom Howard +# Copyright (c) 2009 Allan Caffee +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 11 + +AC_DEFUN([AMINCLUDE_STATIC],[aminclude_static.am]) + +AC_DEFUN([AX_AM_MACROS_STATIC], +[ +AX_AC_PRINT_TO_FILE(AMINCLUDE_STATIC,[ +# ]AMINCLUDE_STATIC[ generated automatically by Autoconf +# from AX_AM_MACROS_STATIC on ]m4_esyscmd([LC_ALL=C date])[ +]) +]) diff --git a/m4/ax_append_compile_flags.m4 b/m4/ax_append_compile_flags.m4 new file mode 100644 index 0000000..9c85635 --- /dev/null +++ b/m4/ax_append_compile_flags.m4 @@ -0,0 +1,46 @@ +# ============================================================================ +# https://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html +# ============================================================================ +# +# SYNOPSIS +# +# AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# For every FLAG1, FLAG2 it is checked whether the compiler works with the +# flag. If it does, the flag is added FLAGS-VARIABLE +# +# If FLAGS-VARIABLE is not specified, the current language's flags (e.g. +# CFLAGS) is used. During the check the flag is always added to the +# current language's flags. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# NOTE: This macro depends on the AX_APPEND_FLAG and +# AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with +# AX_APPEND_LINK_FLAGS. +# +# LICENSE +# +# Copyright (c) 2011 Maarten Bosmans +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 7 + +AC_DEFUN([AX_APPEND_COMPILE_FLAGS], +[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) +AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) +for flag in $1; do + AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4]) +done +])dnl AX_APPEND_COMPILE_FLAGS diff --git a/m4/ax_append_flag.m4 b/m4/ax_append_flag.m4 new file mode 100644 index 0000000..dd6d8b6 --- /dev/null +++ b/m4/ax_append_flag.m4 @@ -0,0 +1,50 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_append_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE]) +# +# DESCRIPTION +# +# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space +# added in between. +# +# If FLAGS-VARIABLE is not specified, the current language's flags (e.g. +# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains +# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly +# FLAG. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 8 + +AC_DEFUN([AX_APPEND_FLAG], +[dnl +AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF +AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])]) +AS_VAR_SET_IF(FLAGS,[ + AS_CASE([" AS_VAR_GET(FLAGS) "], + [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])], + [ + AS_VAR_APPEND(FLAGS,[" $1"]) + AC_RUN_LOG([: FLAGS="$FLAGS"]) + ]) + ], + [ + AS_VAR_SET(FLAGS,[$1]) + AC_RUN_LOG([: FLAGS="$FLAGS"]) + ]) +AS_VAR_POPDEF([FLAGS])dnl +])dnl AX_APPEND_FLAG diff --git a/m4/ax_append_link_flags.m4 b/m4/ax_append_link_flags.m4 new file mode 100644 index 0000000..99b9fa5 --- /dev/null +++ b/m4/ax_append_link_flags.m4 @@ -0,0 +1,44 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_append_link_flags.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_APPEND_LINK_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# For every FLAG1, FLAG2 it is checked whether the linker works with the +# flag. If it does, the flag is added FLAGS-VARIABLE +# +# If FLAGS-VARIABLE is not specified, the linker's flags (LDFLAGS) is +# used. During the check the flag is always added to the linker's flags. +# +# If EXTRA-FLAGS is defined, it is added to the linker's default flags +# when the check is done. The check is thus made with the flags: "LDFLAGS +# EXTRA-FLAGS FLAG". This can for example be used to force the linker to +# issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# NOTE: This macro depends on the AX_APPEND_FLAG and AX_CHECK_LINK_FLAG. +# Please keep this macro in sync with AX_APPEND_COMPILE_FLAGS. +# +# LICENSE +# +# Copyright (c) 2011 Maarten Bosmans +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 7 + +AC_DEFUN([AX_APPEND_LINK_FLAGS], +[AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) +AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) +for flag in $1; do + AX_CHECK_LINK_FLAG([$flag], [AX_APPEND_FLAG([$flag], [m4_default([$2], [LDFLAGS])])], [], [$3], [$4]) +done +])dnl AX_APPEND_LINK_FLAGS diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4 new file mode 100644 index 0000000..bd753b3 --- /dev/null +++ b/m4/ax_check_compile_flag.m4 @@ -0,0 +1,53 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 6 + +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_VAR_IF(CACHEVAR,yes, + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS diff --git a/m4/ax_check_enable_debug.m4 b/m4/ax_check_enable_debug.m4 new file mode 100644 index 0000000..7bc7710 --- /dev/null +++ b/m4/ax_check_enable_debug.m4 @@ -0,0 +1,124 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_check_enable_debug.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_ENABLE_DEBUG([enable by default=yes/info/profile/no], [ENABLE DEBUG VARIABLES ...], [DISABLE DEBUG VARIABLES NDEBUG ...], [IS-RELEASE]) +# +# DESCRIPTION +# +# Check for the presence of an --enable-debug option to configure, with +# the specified default value used when the option is not present. Return +# the value in the variable $ax_enable_debug. +# +# Specifying 'yes' adds '-g -O0' to the compilation flags for all +# languages. Specifying 'info' adds '-g' to the compilation flags. +# Specifying 'profile' adds '-g -pg' to the compilation flags and '-pg' to +# the linking flags. Otherwise, nothing is added. +# +# Define the variables listed in the second argument if debug is enabled, +# defaulting to no variables. Defines the variables listed in the third +# argument if debug is disabled, defaulting to NDEBUG. All lists of +# variables should be space-separated. +# +# If debug is not enabled, ensure AC_PROG_* will not add debugging flags. +# Should be invoked prior to any AC_PROG_* compiler checks. +# +# IS-RELEASE can be used to change the default to 'no' when making a +# release. Set IS-RELEASE to 'yes' or 'no' as appropriate. By default, it +# uses the value of $ax_is_release, so if you are using the AX_IS_RELEASE +# macro, there is no need to pass this parameter. +# +# AX_IS_RELEASE([git-directory]) +# AX_CHECK_ENABLE_DEBUG() +# +# LICENSE +# +# Copyright (c) 2011 Rhys Ulerich +# Copyright (c) 2014, 2015 Philip Withnall +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. + +#serial 9 + +AC_DEFUN([AX_CHECK_ENABLE_DEBUG],[ + AC_BEFORE([$0],[AC_PROG_CC])dnl + AC_BEFORE([$0],[AC_PROG_CXX])dnl + AC_BEFORE([$0],[AC_PROG_F77])dnl + AC_BEFORE([$0],[AC_PROG_FC])dnl + + AC_MSG_CHECKING(whether to enable debugging) + + ax_enable_debug_default=m4_tolower(m4_normalize(ifelse([$1],,[no],[$1]))) + ax_enable_debug_is_release=m4_tolower(m4_normalize(ifelse([$4],, + [$ax_is_release], + [$4]))) + + # If this is a release, override the default. + AS_IF([test "$ax_enable_debug_is_release" = "yes"], + [ax_enable_debug_default="no"]) + + m4_define(ax_enable_debug_vars,[m4_normalize(ifelse([$2],,,[$2]))]) + m4_define(ax_disable_debug_vars,[m4_normalize(ifelse([$3],,[NDEBUG],[$3]))]) + + AC_ARG_ENABLE(debug, + [AS_HELP_STRING([--enable-debug=]@<:@yes/info/profile/no@:>@,[compile with debugging])], + [],enable_debug=$ax_enable_debug_default) + + # empty mean debug yes + AS_IF([test "x$enable_debug" = "x"], + [enable_debug="yes"]) + + # case of debug + AS_CASE([$enable_debug], + [yes],[ + AC_MSG_RESULT(yes) + CFLAGS="${CFLAGS} -g -O0" + CXXFLAGS="${CXXFLAGS} -g -O0" + FFLAGS="${FFLAGS} -g -O0" + FCFLAGS="${FCFLAGS} -g -O0" + OBJCFLAGS="${OBJCFLAGS} -g -O0" + ], + [info],[ + AC_MSG_RESULT(info) + CFLAGS="${CFLAGS} -g" + CXXFLAGS="${CXXFLAGS} -g" + FFLAGS="${FFLAGS} -g" + FCFLAGS="${FCFLAGS} -g" + OBJCFLAGS="${OBJCFLAGS} -g" + ], + [profile],[ + AC_MSG_RESULT(profile) + CFLAGS="${CFLAGS} -g -pg" + CXXFLAGS="${CXXFLAGS} -g -pg" + FFLAGS="${FFLAGS} -g -pg" + FCFLAGS="${FCFLAGS} -g -pg" + OBJCFLAGS="${OBJCFLAGS} -g -pg" + LDFLAGS="${LDFLAGS} -pg" + ], + [ + AC_MSG_RESULT(no) + dnl Ensure AC_PROG_CC/CXX/F77/FC/OBJC will not enable debug flags + dnl by setting any unset environment flag variables + AS_IF([test "x${CFLAGS+set}" != "xset"], + [CFLAGS=""]) + AS_IF([test "x${CXXFLAGS+set}" != "xset"], + [CXXFLAGS=""]) + AS_IF([test "x${FFLAGS+set}" != "xset"], + [FFLAGS=""]) + AS_IF([test "x${FCFLAGS+set}" != "xset"], + [FCFLAGS=""]) + AS_IF([test "x${OBJCFLAGS+set}" != "xset"], + [OBJCFLAGS=""]) + ]) + + dnl Define various variables if debugging is disabled. + dnl assert.h is a NOP if NDEBUG is defined, so define it by default. + AS_IF([test "x$enable_debug" = "xyes"], + [m4_map_args_w(ax_enable_debug_vars, [AC_DEFINE(], [,[1],[Define if debugging is enabled])])], + [m4_map_args_w(ax_disable_debug_vars, [AC_DEFINE(], [,[1],[Define if debugging is disabled])])]) + ax_enable_debug=$enable_debug +]) diff --git a/m4/ax_check_gnu_make.m4 b/m4/ax_check_gnu_make.m4 new file mode 100644 index 0000000..6811043 --- /dev/null +++ b/m4/ax_check_gnu_make.m4 @@ -0,0 +1,95 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_check_gnu_make.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_GNU_MAKE([run-if-true],[run-if-false]) +# +# DESCRIPTION +# +# This macro searches for a GNU version of make. If a match is found: +# +# * The makefile variable `ifGNUmake' is set to the empty string, otherwise +# it is set to "#". This is useful for including a special features in a +# Makefile, which cannot be handled by other versions of make. +# * The makefile variable `ifnGNUmake' is set to #, otherwise +# it is set to the empty string. This is useful for including a special +# features in a Makefile, which can be handled +# by other versions of make or to specify else like clause. +# * The variable `_cv_gnu_make_command` is set to the command to invoke +# GNU make if it exists, the empty string otherwise. +# * The variable `ax_cv_gnu_make_command` is set to the command to invoke +# GNU make by copying `_cv_gnu_make_command`, otherwise it is unset. +# * If GNU Make is found, its version is extracted from the output of +# `make --version` as the last field of a record of space-separated +# columns and saved into the variable `ax_check_gnu_make_version`. +# * Additionally if GNU Make is found, run shell code run-if-true +# else run shell code run-if-false. +# +# Here is an example of its use: +# +# Makefile.in might contain: +# +# # A failsafe way of putting a dependency rule into a makefile +# $(DEPEND): +# $(CC) -MM $(srcdir)/*.c > $(DEPEND) +# +# @ifGNUmake@ ifeq ($(DEPEND),$(wildcard $(DEPEND))) +# @ifGNUmake@ include $(DEPEND) +# @ifGNUmake@ else +# fallback code +# @ifGNUmake@ endif +# +# Then configure.in would normally contain: +# +# AX_CHECK_GNU_MAKE() +# AC_OUTPUT(Makefile) +# +# Then perhaps to cause gnu make to override any other make, we could do +# something like this (note that GNU make always looks for GNUmakefile +# first): +# +# if ! test x$_cv_gnu_make_command = x ; then +# mv Makefile GNUmakefile +# echo .DEFAULT: > Makefile ; +# echo \ $_cv_gnu_make_command \$@ >> Makefile; +# fi +# +# Then, if any (well almost any) other make is called, and GNU make also +# exists, then the other make wraps the GNU make. +# +# LICENSE +# +# Copyright (c) 2008 John Darrington +# Copyright (c) 2015 Enrico M. Crisostomo +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 11 + +AC_DEFUN([AX_CHECK_GNU_MAKE],dnl + [AC_PROG_AWK + AC_CACHE_CHECK([for GNU make],[_cv_gnu_make_command],[dnl + _cv_gnu_make_command="" ; +dnl Search all the common names for GNU make + for a in "$MAKE" make gmake gnumake ; do + if test -z "$a" ; then continue ; fi ; + if "$a" --version 2> /dev/null | grep GNU 2>&1 > /dev/null ; then + _cv_gnu_make_command=$a ; + AX_CHECK_GNU_MAKE_HEADLINE=$("$a" --version 2> /dev/null | grep "GNU Make") + ax_check_gnu_make_version=$(echo ${AX_CHECK_GNU_MAKE_HEADLINE} | ${AWK} -F " " '{ print $(NF); }') + break ; + fi + done ;]) +dnl If there was a GNU version, then set @ifGNUmake@ to the empty string, '#' otherwise + AS_VAR_IF([_cv_gnu_make_command], [""], [AS_VAR_SET([ifGNUmake], ["#"])], [AS_VAR_SET([ifGNUmake], [""])]) + AS_VAR_IF([_cv_gnu_make_command], [""], [AS_VAR_SET([ifnGNUmake], [""])], [AS_VAR_SET([ifGNUmake], ["#"])]) + AS_VAR_IF([_cv_gnu_make_command], [""], [AS_UNSET(ax_cv_gnu_make_command)], [AS_VAR_SET([ax_cv_gnu_make_command], [${_cv_gnu_make_command}])]) + AS_VAR_IF([_cv_gnu_make_command], [""],[$2],[$1]) + AC_SUBST([ifGNUmake]) + AC_SUBST([ifnGNUmake]) +]) diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4 new file mode 100644 index 0000000..03a30ce --- /dev/null +++ b/m4/ax_check_link_flag.m4 @@ -0,0 +1,53 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the linker or gives an error. +# (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the linker's default flags +# when the check is done. The check is thus made with the flags: "LDFLAGS +# EXTRA-FLAGS FLAG". This can for example be used to force the linker to +# issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_LINK_IFELSE. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 6 + +AC_DEFUN([AX_CHECK_LINK_FLAG], +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl +AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS $4 $1" + AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + LDFLAGS=$ax_check_save_flags]) +AS_VAR_IF(CACHEVAR,yes, + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_LINK_FLAGS diff --git a/m4/ax_code_coverage.m4 b/m4/ax_code_coverage.m4 new file mode 100644 index 0000000..6d08319 --- /dev/null +++ b/m4/ax_code_coverage.m4 @@ -0,0 +1,272 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_code_coverage.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CODE_COVERAGE() +# +# DESCRIPTION +# +# Defines CODE_COVERAGE_CPPFLAGS, CODE_COVERAGE_CFLAGS, +# CODE_COVERAGE_CXXFLAGS and CODE_COVERAGE_LIBS which should be included +# in the CPPFLAGS, CFLAGS CXXFLAGS and LIBS/LIBADD variables of every +# build target (program or library) which should be built with code +# coverage support. Also add rules using AX_ADD_AM_MACRO_STATIC; and +# $enable_code_coverage which can be used in subsequent configure output. +# CODE_COVERAGE_ENABLED is defined and substituted, and corresponds to the +# value of the --enable-code-coverage option, which defaults to being +# disabled. +# +# Test also for gcov program and create GCOV variable that could be +# substituted. +# +# Note that all optimization flags in CFLAGS must be disabled when code +# coverage is enabled. +# +# Usage example: +# +# configure.ac: +# +# AX_CODE_COVERAGE +# +# Makefile.am: +# +# include $(top_srcdir)/aminclude_static.am +# +# my_program_LIBS = ... $(CODE_COVERAGE_LIBS) ... +# my_program_CPPFLAGS = ... $(CODE_COVERAGE_CPPFLAGS) ... +# my_program_CFLAGS = ... $(CODE_COVERAGE_CFLAGS) ... +# my_program_CXXFLAGS = ... $(CODE_COVERAGE_CXXFLAGS) ... +# +# clean-local: code-coverage-clean +# distclean-local: code-coverage-dist-clean +# +# This results in a "check-code-coverage" rule being added to any +# Makefile.am which do "include $(top_srcdir)/aminclude_static.am" +# (assuming the module has been configured with --enable-code-coverage). +# Running `make check-code-coverage` in that directory will run the +# module's test suite (`make check`) and build a code coverage report +# detailing the code which was touched, then print the URI for the report. +# +# This code was derived from Makefile.decl in GLib, originally licensed +# under LGPLv2.1+. +# +# LICENSE +# +# Copyright (c) 2012, 2016 Philip Withnall +# Copyright (c) 2012 Xan Lopez +# Copyright (c) 2012 Christian Persch +# Copyright (c) 2012 Paolo Borelli +# Copyright (c) 2012 Dan Winship +# Copyright (c) 2015,2018 Bastien ROUCARIES +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or (at +# your option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +#serial 33 + +m4_define(_AX_CODE_COVERAGE_RULES,[ +AX_ADD_AM_MACRO_STATIC([ +# Code coverage +# +# Optional: +# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting. +# Multiple directories may be specified, separated by whitespace. +# (Default: \$(top_builddir)) +# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated +# by lcov for code coverage. (Default: +# \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage.info) +# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage +# reports to be created. (Default: +# \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage) +# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage, +# set to 0 to disable it and leave empty to stay with the default. +# (Default: empty) +# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov +# instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) +# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov +# instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) +# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov +# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the +# collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) +# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov +# instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) +# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering +# lcov instance. (Default: empty) +# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov +# instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) +# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the +# genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) +# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml +# instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) +# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore +# +# The generated report will be titled using the \$(PACKAGE_NAME) and +# \$(PACKAGE_VERSION). In order to add the current git hash to the title, +# use the git-version-gen script, available online. +# Optional variables +# run only on top dir +if CODE_COVERAGE_ENABLED + ifeq (\$(abs_builddir), \$(abs_top_builddir)) +CODE_COVERAGE_DIRECTORY ?= \$(top_builddir) +CODE_COVERAGE_OUTPUT_FILE ?= \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage.info +CODE_COVERAGE_OUTPUT_DIRECTORY ?= \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage + +CODE_COVERAGE_BRANCH_COVERAGE ?= +CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= \$(if \$(CODE_COVERAGE_BRANCH_COVERAGE),\ +--rc lcov_branch_coverage=\$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_LCOV_SHOPTS ?= \$(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) +CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool \"\$(GCOV)\" +CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= \$(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) +CODE_COVERAGE_LCOV_OPTIONS ?= \$(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) +CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?= +CODE_COVERAGE_LCOV_RMOPTS ?= \$(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) +CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\ +\$(if \$(CODE_COVERAGE_BRANCH_COVERAGE),\ +--rc genhtml_branch_coverage=\$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_GENHTML_OPTIONS ?= \$(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) +CODE_COVERAGE_IGNORE_PATTERN ?= + +GITIGNOREFILES = \$(GITIGNOREFILES) \$(CODE_COVERAGE_OUTPUT_FILE) \$(CODE_COVERAGE_OUTPUT_DIRECTORY) +code_coverage_v_lcov_cap = \$(code_coverage_v_lcov_cap_\$(V)) +code_coverage_v_lcov_cap_ = \$(code_coverage_v_lcov_cap_\$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_lcov_cap_0 = @echo \" LCOV --capture\" \$(CODE_COVERAGE_OUTPUT_FILE); +code_coverage_v_lcov_ign = \$(code_coverage_v_lcov_ign_\$(V)) +code_coverage_v_lcov_ign_ = \$(code_coverage_v_lcov_ign_\$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_lcov_ign_0 = @echo \" LCOV --remove /tmp/*\" \$(CODE_COVERAGE_IGNORE_PATTERN); +code_coverage_v_genhtml = \$(code_coverage_v_genhtml_\$(V)) +code_coverage_v_genhtml_ = \$(code_coverage_v_genhtml_\$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_genhtml_0 = @echo \" GEN \" \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\"; +code_coverage_quiet = \$(code_coverage_quiet_\$(V)) +code_coverage_quiet_ = \$(code_coverage_quiet_\$(AM_DEFAULT_VERBOSITY)) +code_coverage_quiet_0 = --quiet + +# sanitizes the test-name: replaces with underscores: dashes and dots +code_coverage_sanitize = \$(subst -,_,\$(subst .,_,\$(1))) + +# Use recursive makes in order to ignore errors during check +check-code-coverage: + -\$(AM_V_at)\$(MAKE) \$(AM_MAKEFLAGS) -k check + \$(AM_V_at)\$(MAKE) \$(AM_MAKEFLAGS) code-coverage-capture + +# Capture code coverage data +code-coverage-capture: code-coverage-capture-hook + \$(code_coverage_v_lcov_cap)\$(LCOV) \$(code_coverage_quiet) \$(addprefix --directory ,\$(CODE_COVERAGE_DIRECTORY)) --capture --output-file \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" --test-name \"\$(call code_coverage_sanitize,\$(PACKAGE_NAME)-\$(PACKAGE_VERSION))\" --no-checksum --compat-libtool \$(CODE_COVERAGE_LCOV_SHOPTS) \$(CODE_COVERAGE_LCOV_OPTIONS) + \$(code_coverage_v_lcov_ign)\$(LCOV) \$(code_coverage_quiet) \$(addprefix --directory ,\$(CODE_COVERAGE_DIRECTORY)) --remove \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" \"/tmp/*\" \$(CODE_COVERAGE_IGNORE_PATTERN) --output-file \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \$(CODE_COVERAGE_LCOV_SHOPTS) \$(CODE_COVERAGE_LCOV_RMOPTS) + -@rm -f \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" + \$(code_coverage_v_genhtml)LANG=C \$(GENHTML) \$(code_coverage_quiet) \$(addprefix --prefix ,\$(CODE_COVERAGE_DIRECTORY)) --output-directory \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\" --title \"\$(PACKAGE_NAME)-\$(PACKAGE_VERSION) Code Coverage\" --legend --show-details \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \$(CODE_COVERAGE_GENHTML_OPTIONS) + @echo \"file://\$(abs_builddir)/\$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html\" + +code-coverage-clean: + -\$(LCOV) --directory \$(top_builddir) -z + -rm -rf \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\" + -find . \\( -name \"*.gcda\" -o -name \"*.gcno\" -o -name \"*.gcov\" \\) -delete + +code-coverage-dist-clean: + +A][M_DISTCHECK_CONFIGURE_FLAGS := \$(A][M_DISTCHECK_CONFIGURE_FLAGS) --disable-code-coverage + else # ifneq (\$(abs_builddir), \$(abs_top_builddir)) +check-code-coverage: + +code-coverage-capture: code-coverage-capture-hook + +code-coverage-clean: + +code-coverage-dist-clean: + endif # ifeq (\$(abs_builddir), \$(abs_top_builddir)) +else #! CODE_COVERAGE_ENABLED +# Use recursive makes in order to ignore errors during check +check-code-coverage: + @echo \"Need to reconfigure with --enable-code-coverage\" +# Capture code coverage data +code-coverage-capture: code-coverage-capture-hook + @echo \"Need to reconfigure with --enable-code-coverage\" + +code-coverage-clean: + +code-coverage-dist-clean: + +endif #CODE_COVERAGE_ENABLED +# Hook rule executed before code-coverage-capture, overridable by the user +code-coverage-capture-hook: + +.PHONY: check-code-coverage code-coverage-capture code-coverage-dist-clean code-coverage-clean code-coverage-capture-hook +]) +]) + +AC_DEFUN([_AX_CODE_COVERAGE_ENABLED],[ + AX_CHECK_GNU_MAKE([],[AC_MSG_ERROR([not using GNU make that is needed for coverage])]) + AC_REQUIRE([AX_ADD_AM_MACRO_STATIC]) + # check for gcov + AC_CHECK_TOOL([GCOV], + [$_AX_CODE_COVERAGE_GCOV_PROG_WITH], + [:]) + AS_IF([test "X$GCOV" = "X:"], + [AC_MSG_ERROR([gcov is needed to do coverage])]) + AC_SUBST([GCOV]) + + dnl Check if gcc is being used + AS_IF([ test "$GCC" = "no" ], [ + AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage]) + ]) + + AC_CHECK_PROG([LCOV], [lcov], [lcov]) + AC_CHECK_PROG([GENHTML], [genhtml], [genhtml]) + + AS_IF([ test x"$LCOV" = x ], [ + AC_MSG_ERROR([To enable code coverage reporting you must have lcov installed]) + ]) + + AS_IF([ test x"$GENHTML" = x ], [ + AC_MSG_ERROR([Could not find genhtml from the lcov package]) + ]) + + dnl Build the code coverage flags + dnl Define CODE_COVERAGE_LDFLAGS for backwards compatibility + CODE_COVERAGE_CPPFLAGS="-DNDEBUG" + CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" + CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" + CODE_COVERAGE_LIBS="-lgcov" + + AC_SUBST([CODE_COVERAGE_CPPFLAGS]) + AC_SUBST([CODE_COVERAGE_CFLAGS]) + AC_SUBST([CODE_COVERAGE_CXXFLAGS]) + AC_SUBST([CODE_COVERAGE_LIBS]) +]) + +AC_DEFUN([AX_CODE_COVERAGE],[ + dnl Check for --enable-code-coverage + + # allow to override gcov location + AC_ARG_WITH([gcov], + [AS_HELP_STRING([--with-gcov[=GCOV]], [use given GCOV for coverage (GCOV=gcov).])], + [_AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov], + [_AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov]) + + AC_MSG_CHECKING([whether to build with code coverage support]) + AC_ARG_ENABLE([code-coverage], + AS_HELP_STRING([--enable-code-coverage], + [Whether to enable code coverage support]),, + enable_code_coverage=no) + + AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test "x$enable_code_coverage" = xyes]) + AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage]) + AC_MSG_RESULT($enable_code_coverage) + + AS_IF([ test "x$enable_code_coverage" = xyes ], [ + _AX_CODE_COVERAGE_ENABLED + ]) + + _AX_CODE_COVERAGE_RULES +]) diff --git a/m4/ax_compiler_flags.m4 b/m4/ax_compiler_flags.m4 new file mode 100644 index 0000000..ddb0456 --- /dev/null +++ b/m4/ax_compiler_flags.m4 @@ -0,0 +1,158 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_compiler_flags.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_COMPILER_FLAGS([CFLAGS-VARIABLE], [LDFLAGS-VARIABLE], [IS-RELEASE], [EXTRA-BASE-CFLAGS], [EXTRA-YES-CFLAGS], [UNUSED], [UNUSED], [UNUSED], [EXTRA-BASE-LDFLAGS], [EXTRA-YES-LDFLAGS], [UNUSED], [UNUSED], [UNUSED]) +# +# DESCRIPTION +# +# Check for the presence of an --enable-compile-warnings option to +# configure, defaulting to "error" in normal operation, or "yes" if +# IS-RELEASE is equal to "yes". Return the value in the variable +# $ax_enable_compile_warnings. +# +# Depending on the value of --enable-compile-warnings, different compiler +# warnings are checked to see if they work with the current compiler and, +# if so, are appended to CFLAGS-VARIABLE and LDFLAGS-VARIABLE. This +# allows a consistent set of baseline compiler warnings to be used across +# a code base, irrespective of any warnings enabled locally by individual +# developers. By standardising the warnings used by all developers of a +# project, the project can commit to a zero-warnings policy, using -Werror +# to prevent compilation if new warnings are introduced. This makes +# catching bugs which are flagged by warnings a lot easier. +# +# By providing a consistent --enable-compile-warnings argument across all +# projects using this macro, continuous integration systems can easily be +# configured the same for all projects. Automated systems or build +# systems aimed at beginners may want to pass the --disable-Werror +# argument to unconditionally prevent warnings being fatal. +# +# --enable-compile-warnings can take the values: +# +# * no: Base compiler warnings only; not even -Wall. +# * yes: The above, plus a broad range of useful warnings. +# * error: The above, plus -Werror so that all warnings are fatal. +# Use --disable-Werror to override this and disable fatal +# warnings. +# +# The set of base and enabled flags can be augmented using the +# EXTRA-*-CFLAGS and EXTRA-*-LDFLAGS variables, which are tested and +# appended to the output variable if --enable-compile-warnings is not +# "no". Flags should not be disabled using these arguments, as the entire +# point of AX_COMPILER_FLAGS is to enforce a consistent set of useful +# compiler warnings on code, using warnings which have been chosen for low +# false positive rates. If a compiler emits false positives for a +# warning, a #pragma should be used in the code to disable the warning +# locally. See: +# +# https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas +# +# The EXTRA-* variables should only be used to supply extra warning flags, +# and not general purpose compiler flags, as they are controlled by +# configure options such as --disable-Werror. +# +# IS-RELEASE can be used to disable -Werror when making a release, which +# is useful for those hairy moments when you just want to get the release +# done as quickly as possible. Set it to "yes" to disable -Werror. By +# default, it uses the value of $ax_is_release, so if you are using the +# AX_IS_RELEASE macro, there is no need to pass this parameter. For +# example: +# +# AX_IS_RELEASE([git-directory]) +# AX_COMPILER_FLAGS() +# +# CFLAGS-VARIABLE defaults to WARN_CFLAGS, and LDFLAGS-VARIABLE defaults +# to WARN_LDFLAGS. Both variables are AC_SUBST-ed by this macro, but must +# be manually added to the CFLAGS and LDFLAGS variables for each target in +# the code base. +# +# If C++ language support is enabled with AC_PROG_CXX, which must occur +# before this macro in configure.ac, warning flags for the C++ compiler +# are AC_SUBST-ed as WARN_CXXFLAGS, and must be manually added to the +# CXXFLAGS variables for each target in the code base. EXTRA-*-CFLAGS can +# be used to augment the base and enabled flags. +# +# Warning flags for g-ir-scanner (from GObject Introspection) are +# AC_SUBST-ed as WARN_SCANNERFLAGS. This variable must be manually added +# to the SCANNERFLAGS variable for each GIR target in the code base. If +# extra g-ir-scanner flags need to be enabled, the AX_COMPILER_FLAGS_GIR +# macro must be invoked manually. +# +# AX_COMPILER_FLAGS may add support for other tools in future, in addition +# to the compiler and linker. No extra EXTRA-* variables will be added +# for those tools, and all extra support will still use the single +# --enable-compile-warnings configure option. For finer grained control +# over the flags for individual tools, use AX_COMPILER_FLAGS_CFLAGS, +# AX_COMPILER_FLAGS_LDFLAGS and AX_COMPILER_FLAGS_* for new tools. +# +# The UNUSED variables date from a previous version of this macro, and are +# automatically appended to the preceding non-UNUSED variable. They should +# be left empty in new uses of the macro. +# +# LICENSE +# +# Copyright (c) 2014, 2015 Philip Withnall +# Copyright (c) 2015 David King +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 14 + +# _AX_COMPILER_FLAGS_LANG([LANGNAME]) +m4_defun([_AX_COMPILER_FLAGS_LANG], +[m4_ifdef([_AX_COMPILER_FLAGS_LANG_]$1[_enabled], [], + [m4_define([_AX_COMPILER_FLAGS_LANG_]$1[_enabled], [])dnl + AX_REQUIRE_DEFINED([AX_COMPILER_FLAGS_]$1[FLAGS])])dnl +]) + +AC_DEFUN([AX_COMPILER_FLAGS],[ + # C support is enabled by default. + _AX_COMPILER_FLAGS_LANG([C]) + # Only enable C++ support if AC_PROG_CXX is called. The redefinition of + # AC_PROG_CXX is so that a fatal error is emitted if this macro is called + # before AC_PROG_CXX, which would otherwise cause no C++ warnings to be + # checked. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AX_COMPILER_FLAGS_LANG([CXX])], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AX_COMPILER_FLAGS_LANG([CXX])])]) + AX_REQUIRE_DEFINED([AX_COMPILER_FLAGS_LDFLAGS]) + + # Default value for IS-RELEASE is $ax_is_release + ax_compiler_flags_is_release=m4_tolower(m4_normalize(ifelse([$3],, + [$ax_is_release], + [$3]))) + + AC_ARG_ENABLE([compile-warnings], + AS_HELP_STRING([--enable-compile-warnings=@<:@no/yes/error@:>@], + [Enable compiler warnings and errors]),, + [AS_IF([test "$ax_compiler_flags_is_release" = "yes"], + [enable_compile_warnings="yes"], + [enable_compile_warnings="error"])]) + AC_ARG_ENABLE([Werror], + AS_HELP_STRING([--disable-Werror], + [Unconditionally make all compiler warnings non-fatal]),, + [enable_Werror=maybe]) + + # Return the user's chosen warning level + AS_IF([test "$enable_Werror" = "no" -a \ + "$enable_compile_warnings" = "error"],[ + enable_compile_warnings="yes" + ]) + + ax_enable_compile_warnings=$enable_compile_warnings + + AX_COMPILER_FLAGS_CFLAGS([$1],[$ax_compiler_flags_is_release], + [$4],[$5 $6 $7 $8]) + m4_ifdef([_AX_COMPILER_FLAGS_LANG_CXX_enabled], + [AX_COMPILER_FLAGS_CXXFLAGS([WARN_CXXFLAGS], + [$ax_compiler_flags_is_release], + [$4],[$5 $6 $7 $8])]) + AX_COMPILER_FLAGS_LDFLAGS([$2],[$ax_compiler_flags_is_release], + [$9],[$10 $11 $12 $13]) + AX_COMPILER_FLAGS_GIR([WARN_SCANNERFLAGS],[$ax_compiler_flags_is_release]) +])dnl AX_COMPILER_FLAGS diff --git a/m4/ax_compiler_flags_cflags.m4 b/m4/ax_compiler_flags_cflags.m4 new file mode 100644 index 0000000..916f918 --- /dev/null +++ b/m4/ax_compiler_flags_cflags.m4 @@ -0,0 +1,161 @@ +# ============================================================================= +# https://www.gnu.org/software/autoconf-archive/ax_compiler_flags_cflags.html +# ============================================================================= +# +# SYNOPSIS +# +# AX_COMPILER_FLAGS_CFLAGS([VARIABLE], [IS-RELEASE], [EXTRA-BASE-FLAGS], [EXTRA-YES-FLAGS]) +# +# DESCRIPTION +# +# Add warning flags for the C compiler to VARIABLE, which defaults to +# WARN_CFLAGS. VARIABLE is AC_SUBST-ed by this macro, but must be +# manually added to the CFLAGS variable for each target in the code base. +# +# This macro depends on the environment set up by AX_COMPILER_FLAGS. +# Specifically, it uses the value of $ax_enable_compile_warnings to decide +# which flags to enable. +# +# LICENSE +# +# Copyright (c) 2014, 2015 Philip Withnall +# Copyright (c) 2017, 2018 Reini Urban +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 17 + +AC_DEFUN([AX_COMPILER_FLAGS_CFLAGS],[ + AC_REQUIRE([AC_PROG_SED]) + AX_REQUIRE_DEFINED([AX_APPEND_COMPILE_FLAGS]) + AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) + AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) + + # Variable names + m4_define([ax_warn_cflags_variable], + [m4_normalize(ifelse([$1],,[WARN_CFLAGS],[$1]))]) + + AC_LANG_PUSH([C]) + + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ + [#ifndef __cplusplus + #error "no C++" + #endif]])], + [ax_compiler_cxx=yes;], + [ax_compiler_cxx=no;]) + + # Always pass -Werror=unknown-warning-option to get Clang to fail on bad + # flags, otherwise they are always appended to the warn_cflags variable, and + # Clang warns on them for every compilation unit. + # If this is passed to GCC, it will explode, so the flag must be enabled + # conditionally. + AX_CHECK_COMPILE_FLAG([-Werror=unknown-warning-option],[ + ax_compiler_flags_test="-Werror=unknown-warning-option" + ],[ + ax_compiler_flags_test="" + ]) + + # Check that -Wno-suggest-attribute=format is supported + AX_CHECK_COMPILE_FLAG([-Wno-suggest-attribute=format],[ + ax_compiler_no_suggest_attribute_flags="-Wno-suggest-attribute=format" + ],[ + ax_compiler_no_suggest_attribute_flags="" + ]) + + # Base flags + AX_APPEND_COMPILE_FLAGS([ dnl + -fno-strict-aliasing dnl + $3 dnl + ],ax_warn_cflags_variable,[$ax_compiler_flags_test]) + + AS_IF([test "$ax_enable_compile_warnings" != "no"],[ + if test "$ax_compiler_cxx" = "no" ; then + # C-only flags. Warn in C++ + AX_APPEND_COMPILE_FLAGS([ dnl + -Wnested-externs dnl + -Wmissing-prototypes dnl + -Wstrict-prototypes dnl + -Wdeclaration-after-statement dnl + -Wimplicit-function-declaration dnl + -Wold-style-definition dnl + -Wjump-misses-init dnl + ],ax_warn_cflags_variable,[$ax_compiler_flags_test]) + fi + + # "yes" flags + AX_APPEND_COMPILE_FLAGS([ dnl + -Wall dnl + -Wextra dnl + -Wundef dnl + -Wwrite-strings dnl + -Wpointer-arith dnl + -Wmissing-declarations dnl + -Wredundant-decls dnl + -Wno-unused-parameter dnl + -Wno-missing-field-initializers dnl + -Wformat=2 dnl + -Wcast-align dnl + -Wformat-nonliteral dnl + -Wformat-security dnl + -Wsign-compare dnl + -Wstrict-aliasing dnl + -Wshadow dnl + -Winline dnl + -Wpacked dnl + -Wmissing-format-attribute dnl + -Wmissing-noreturn dnl + -Winit-self dnl + -Wredundant-decls dnl + -Wmissing-include-dirs dnl + -Wunused-but-set-variable dnl + -Warray-bounds dnl + -Wreturn-type dnl + -Wswitch-enum dnl + -Wswitch-default dnl + -Wduplicated-cond dnl + -Wduplicated-branches dnl + -Wlogical-op dnl + -Wrestrict dnl + -Wnull-dereference dnl + -Wdouble-promotion dnl + $4 dnl + $5 dnl + $6 dnl + $7 dnl + ],ax_warn_cflags_variable,[$ax_compiler_flags_test]) + ]) + AS_IF([test "$ax_enable_compile_warnings" = "error"],[ + # "error" flags; -Werror has to be appended unconditionally because + # it's not possible to test for + # + # suggest-attribute=format is disabled because it gives too many false + # positives + AX_APPEND_FLAG([-Werror],ax_warn_cflags_variable) + + AX_APPEND_COMPILE_FLAGS([ dnl + [$ax_compiler_no_suggest_attribute_flags] dnl + ],ax_warn_cflags_variable,[$ax_compiler_flags_test]) + ]) + + # In the flags below, when disabling specific flags, always add *both* + # -Wno-foo and -Wno-error=foo. This fixes the situation where (for example) + # we enable -Werror, disable a flag, and a build bot passes CFLAGS=-Wall, + # which effectively turns that flag back on again as an error. + for flag in $ax_warn_cflags_variable; do + AS_CASE([$flag], + [-Wno-*=*],[], + [-Wno-*],[ + AX_APPEND_COMPILE_FLAGS([-Wno-error=$(AS_ECHO([$flag]) | $SED 's/^-Wno-//')], + ax_warn_cflags_variable, + [$ax_compiler_flags_test]) + ]) + done + + AC_LANG_POP([C]) + + # Substitute the variables + AC_SUBST(ax_warn_cflags_variable) +])dnl AX_COMPILER_FLAGS diff --git a/m4/ax_compiler_flags_cxxflags.m4 b/m4/ax_compiler_flags_cxxflags.m4 new file mode 100644 index 0000000..3067d9b --- /dev/null +++ b/m4/ax_compiler_flags_cxxflags.m4 @@ -0,0 +1,136 @@ +# =============================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_compiler_flags_cxxflags.html +# =============================================================================== +# +# SYNOPSIS +# +# AX_COMPILER_FLAGS_CXXFLAGS([VARIABLE], [IS-RELEASE], [EXTRA-BASE-FLAGS], [EXTRA-YES-FLAGS]) +# +# DESCRIPTION +# +# Add warning flags for the C++ compiler to VARIABLE, which defaults to +# WARN_CXXFLAGS. VARIABLE is AC_SUBST-ed by this macro, but must be +# manually added to the CXXFLAGS variable for each target in the code +# base. +# +# This macro depends on the environment set up by AX_COMPILER_FLAGS. +# Specifically, it uses the value of $ax_enable_compile_warnings to decide +# which flags to enable. +# +# LICENSE +# +# Copyright (c) 2015 David King +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 10 + +AC_DEFUN([AX_COMPILER_FLAGS_CXXFLAGS],[ + AC_REQUIRE([AC_PROG_SED]) + AX_REQUIRE_DEFINED([AX_APPEND_COMPILE_FLAGS]) + AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) + AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) + + # Variable names + m4_define([ax_warn_cxxflags_variable], + [m4_normalize(ifelse([$1],,[WARN_CXXFLAGS],[$1]))]) + + AC_LANG_PUSH([C++]) + + # Always pass -Werror=unknown-warning-option to get Clang to fail on bad + # flags, otherwise they are always appended to the warn_cxxflags variable, + # and Clang warns on them for every compilation unit. + # If this is passed to GCC, it will explode, so the flag must be enabled + # conditionally. + AX_CHECK_COMPILE_FLAG([-Werror=unknown-warning-option],[ + ax_compiler_flags_test="-Werror=unknown-warning-option" + ],[ + ax_compiler_flags_test="" + ]) + + # Check that -Wno-suggest-attribute=format is supported + AX_CHECK_COMPILE_FLAG([-Wno-suggest-attribute=format],[ + ax_compiler_no_suggest_attribute_flags="-Wno-suggest-attribute=format" + ],[ + ax_compiler_no_suggest_attribute_flags="" + ]) + + # Base flags + AX_APPEND_COMPILE_FLAGS([ dnl + -fno-strict-aliasing dnl + $3 dnl + ],ax_warn_cxxflags_variable,[$ax_compiler_flags_test]) + + AS_IF([test "$ax_enable_compile_warnings" != "no"],[ + # "yes" flags + AX_APPEND_COMPILE_FLAGS([ dnl + -Wall dnl + -Wextra dnl + -Wundef dnl + -Wwrite-strings dnl + -Wpointer-arith dnl + -Wmissing-declarations dnl + -Wredundant-decls dnl + -Wno-unused-parameter dnl + -Wno-missing-field-initializers dnl + -Wformat=2 dnl + -Wcast-align dnl + -Wformat-nonliteral dnl + -Wformat-security dnl + -Wsign-compare dnl + -Wstrict-aliasing dnl + -Wshadow dnl + -Winline dnl + -Wpacked dnl + -Wmissing-format-attribute dnl + -Wmissing-noreturn dnl + -Winit-self dnl + -Wredundant-decls dnl + -Wmissing-include-dirs dnl + -Wunused-but-set-variable dnl + -Warray-bounds dnl + -Wreturn-type dnl + -Wno-overloaded-virtual dnl + -Wswitch-enum dnl + -Wswitch-default dnl + $4 dnl + $5 dnl + $6 dnl + $7 dnl + ],ax_warn_cxxflags_variable,[$ax_compiler_flags_test]) + ]) + AS_IF([test "$ax_enable_compile_warnings" = "error"],[ + # "error" flags; -Werror has to be appended unconditionally because + # it's not possible to test for + # + # suggest-attribute=format is disabled because it gives too many false + # positives + AX_APPEND_FLAG([-Werror],ax_warn_cxxflags_variable) + + AX_APPEND_COMPILE_FLAGS([ dnl + [$ax_compiler_no_suggest_attribute_flags] dnl + ],ax_warn_cxxflags_variable,[$ax_compiler_flags_test]) + ]) + + # In the flags below, when disabling specific flags, always add *both* + # -Wno-foo and -Wno-error=foo. This fixes the situation where (for example) + # we enable -Werror, disable a flag, and a build bot passes CXXFLAGS=-Wall, + # which effectively turns that flag back on again as an error. + for flag in $ax_warn_cxxflags_variable; do + AS_CASE([$flag], + [-Wno-*=*],[], + [-Wno-*],[ + AX_APPEND_COMPILE_FLAGS([-Wno-error=$(AS_ECHO([$flag]) | $SED 's/^-Wno-//')], + ax_warn_cxxflags_variable, + [$ax_compiler_flags_test]) + ]) + done + + AC_LANG_POP([C++]) + + # Substitute the variables + AC_SUBST(ax_warn_cxxflags_variable) +])dnl AX_COMPILER_FLAGS_CXXFLAGS diff --git a/m4/ax_compiler_flags_gir.m4 b/m4/ax_compiler_flags_gir.m4 new file mode 100644 index 0000000..5b4924a --- /dev/null +++ b/m4/ax_compiler_flags_gir.m4 @@ -0,0 +1,60 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_compiler_flags_gir.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_COMPILER_FLAGS_GIR([VARIABLE], [IS-RELEASE], [EXTRA-BASE-FLAGS], [EXTRA-YES-FLAGS]) +# +# DESCRIPTION +# +# Add warning flags for the g-ir-scanner (from GObject Introspection) to +# VARIABLE, which defaults to WARN_SCANNERFLAGS. VARIABLE is AC_SUBST-ed +# by this macro, but must be manually added to the SCANNERFLAGS variable +# for each GIR target in the code base. +# +# This macro depends on the environment set up by AX_COMPILER_FLAGS. +# Specifically, it uses the value of $ax_enable_compile_warnings to decide +# which flags to enable. +# +# LICENSE +# +# Copyright (c) 2015 Philip Withnall +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 6 + +AC_DEFUN([AX_COMPILER_FLAGS_GIR],[ + AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) + + # Variable names + m4_define([ax_warn_scannerflags_variable], + [m4_normalize(ifelse([$1],,[WARN_SCANNERFLAGS],[$1]))]) + + # Base flags + AX_APPEND_FLAG([$3],ax_warn_scannerflags_variable) + + AS_IF([test "$ax_enable_compile_warnings" != "no"],[ + # "yes" flags + AX_APPEND_FLAG([ dnl + --warn-all dnl + $4 dnl + $5 dnl + $6 dnl + $7 dnl + ],ax_warn_scannerflags_variable) + ]) + AS_IF([test "$ax_enable_compile_warnings" = "error"],[ + # "error" flags + AX_APPEND_FLAG([ dnl + --warn-error dnl + ],ax_warn_scannerflags_variable) + ]) + + # Substitute the variables + AC_SUBST(ax_warn_scannerflags_variable) +])dnl AX_COMPILER_FLAGS diff --git a/m4/ax_compiler_flags_ldflags.m4 b/m4/ax_compiler_flags_ldflags.m4 new file mode 100644 index 0000000..976d119 --- /dev/null +++ b/m4/ax_compiler_flags_ldflags.m4 @@ -0,0 +1,111 @@ +# ============================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_compiler_flags_ldflags.html +# ============================================================================== +# +# SYNOPSIS +# +# AX_COMPILER_FLAGS_LDFLAGS([VARIABLE], [IS-RELEASE], [EXTRA-BASE-FLAGS], [EXTRA-YES-FLAGS]) +# +# DESCRIPTION +# +# Add warning flags for the linker to VARIABLE, which defaults to +# WARN_LDFLAGS. VARIABLE is AC_SUBST-ed by this macro, but must be +# manually added to the LDFLAGS variable for each target in the code base. +# +# This macro depends on the environment set up by AX_COMPILER_FLAGS. +# Specifically, it uses the value of $ax_enable_compile_warnings to decide +# which flags to enable. +# +# LICENSE +# +# Copyright (c) 2014, 2015 Philip Withnall +# Copyright (c) 2017, 2018 Reini Urban +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 9 + +AC_DEFUN([AX_COMPILER_FLAGS_LDFLAGS],[ + AX_REQUIRE_DEFINED([AX_APPEND_LINK_FLAGS]) + AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) + AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) + AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) + + # Variable names + m4_define([ax_warn_ldflags_variable], + [m4_normalize(ifelse([$1],,[WARN_LDFLAGS],[$1]))]) + + # Always pass -Werror=unknown-warning-option to get Clang to fail on bad + # flags, otherwise they are always appended to the warn_ldflags variable, + # and Clang warns on them for every compilation unit. + # If this is passed to GCC, it will explode, so the flag must be enabled + # conditionally. + AX_CHECK_COMPILE_FLAG([-Werror=unknown-warning-option],[ + ax_compiler_flags_test="-Werror=unknown-warning-option" + ],[ + ax_compiler_flags_test="" + ]) + + AX_CHECK_LINK_FLAG([-Wl,--as-needed], [ + AX_APPEND_LINK_FLAGS([-Wl,--as-needed], + [AM_LDFLAGS],[$ax_compiler_flags_test]) + ]) + AX_CHECK_LINK_FLAG([-Wl,-z,relro], [ + AX_APPEND_LINK_FLAGS([-Wl,-z,relro], + [AM_LDFLAGS],[$ax_compiler_flags_test]) + ]) + AX_CHECK_LINK_FLAG([-Wl,-z,now], [ + AX_APPEND_LINK_FLAGS([-Wl,-z,now], + [AM_LDFLAGS],[$ax_compiler_flags_test]) + ]) + AX_CHECK_LINK_FLAG([-Wl,-z,noexecstack], [ + AX_APPEND_LINK_FLAGS([-Wl,-z,noexecstack], + [AM_LDFLAGS],[$ax_compiler_flags_test]) + ]) + # textonly, retpolineplt not yet + + # macOS and cygwin linker do not have --as-needed + AX_CHECK_LINK_FLAG([-Wl,--no-as-needed], [ + ax_compiler_flags_as_needed_option="-Wl,--no-as-needed" + ], [ + ax_compiler_flags_as_needed_option="" + ]) + + # macOS linker speaks with a different accent + ax_compiler_flags_fatal_warnings_option="" + AX_CHECK_LINK_FLAG([-Wl,--fatal-warnings], [ + ax_compiler_flags_fatal_warnings_option="-Wl,--fatal-warnings" + ]) + AX_CHECK_LINK_FLAG([-Wl,-fatal_warnings], [ + ax_compiler_flags_fatal_warnings_option="-Wl,-fatal_warnings" + ]) + + # Base flags + AX_APPEND_LINK_FLAGS([ dnl + $ax_compiler_flags_as_needed_option dnl + $3 dnl + ],ax_warn_ldflags_variable,[$ax_compiler_flags_test]) + + AS_IF([test "$ax_enable_compile_warnings" != "no"],[ + # "yes" flags + AX_APPEND_LINK_FLAGS([$4 $5 $6 $7], + ax_warn_ldflags_variable, + [$ax_compiler_flags_test]) + ]) + AS_IF([test "$ax_enable_compile_warnings" = "error"],[ + # "error" flags; -Werror has to be appended unconditionally because + # it's not possible to test for + # + # suggest-attribute=format is disabled because it gives too many false + # positives + AX_APPEND_LINK_FLAGS([ dnl + $ax_compiler_flags_fatal_warnings_option dnl + ],ax_warn_ldflags_variable,[$ax_compiler_flags_test]) + ]) + + # Substitute the variables + AC_SUBST(ax_warn_ldflags_variable) +])dnl AX_COMPILER_FLAGS diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 0000000..9e9eaed --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,948 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) +# or '14' (for the C++14 standard). +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016, 2018 Krzesimir Nowak +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 10 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + if test x$ac_success = xyes; then + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 +) + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201703L + +#error "This is not a C++17 compiler" + +#else + +#include +#include +#include + +namespace cxx17 +{ + + namespace test_constexpr_lambdas + { + + constexpr int foo = [](){return 42;}(); + + } + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + + namespace test_template_argument_deduction_for_class_templates + { + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + + namespace test_structured_bindings + { + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } + + namespace test_exception_spec_type_system + { + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // __cplusplus < 201703L + +]]) diff --git a/m4/ax_cxx_compile_stdcxx_14.m4 b/m4/ax_cxx_compile_stdcxx_14.m4 new file mode 100644 index 0000000..094db0d --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx_14.m4 @@ -0,0 +1,34 @@ +# ============================================================================= +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_14.html +# ============================================================================= +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX_14([ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the C++14 +# standard; if necessary, add switches to CXX and CXXCPP to enable +# support. +# +# This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX +# macro with the version set to C++14. The two optional arguments are +# forwarded literally as the second and third argument respectively. +# Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for +# more information. If you want to use this macro, you also need to +# download the ax_cxx_compile_stdcxx.m4 file. +# +# LICENSE +# +# Copyright (c) 2015 Moritz Klammler +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 5 + +AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) +AC_DEFUN([AX_CXX_COMPILE_STDCXX_14], [AX_CXX_COMPILE_STDCXX([14], [$1], [$2])]) diff --git a/m4/ax_file_escapes.m4 b/m4/ax_file_escapes.m4 new file mode 100644 index 0000000..a86fdc3 --- /dev/null +++ b/m4/ax_file_escapes.m4 @@ -0,0 +1,30 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_file_escapes.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_FILE_ESCAPES +# +# DESCRIPTION +# +# Writes the specified data to the specified file. +# +# LICENSE +# +# Copyright (c) 2008 Tom Howard +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 8 + +AC_DEFUN([AX_FILE_ESCAPES],[ +AX_DOLLAR="\$" +AX_SRB="\\135" +AX_SLB="\\133" +AX_BS="\\\\" +AX_DQ="\"" +]) diff --git a/m4/ax_is_release.m4 b/m4/ax_is_release.m4 new file mode 100644 index 0000000..9097ddb --- /dev/null +++ b/m4/ax_is_release.m4 @@ -0,0 +1,80 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_is_release.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_IS_RELEASE(POLICY) +# +# DESCRIPTION +# +# Determine whether the code is being configured as a release, or from +# git. Set the ax_is_release variable to 'yes' or 'no'. +# +# If building a release version, it is recommended that the configure +# script disable compiler errors and debug features, by conditionalising +# them on the ax_is_release variable. If building from git, these +# features should be enabled. +# +# The POLICY parameter specifies how ax_is_release is determined. It can +# take the following values: +# +# * git-directory: ax_is_release will be 'no' if a '.git' directory exists +# * minor-version: ax_is_release will be 'no' if the minor version number +# in $PACKAGE_VERSION is odd; this assumes +# $PACKAGE_VERSION follows the 'major.minor.micro' scheme +# * micro-version: ax_is_release will be 'no' if the micro version number +# in $PACKAGE_VERSION is odd; this assumes +# $PACKAGE_VERSION follows the 'major.minor.micro' scheme +# * dash-version: ax_is_release will be 'no' if there is a dash '-' +# in $PACKAGE_VERSION, for example 1.2-pre3, 1.2.42-a8b9 +# or 2.0-dirty (in particular this is suitable for use +# with git-version-gen) +# * always: ax_is_release will always be 'yes' +# * never: ax_is_release will always be 'no' +# +# Other policies may be added in future. +# +# LICENSE +# +# Copyright (c) 2015 Philip Withnall +# Copyright (c) 2016 Collabora Ltd. +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. + +#serial 7 + +AC_DEFUN([AX_IS_RELEASE],[ + AC_BEFORE([AC_INIT],[$0]) + + m4_case([$1], + [git-directory],[ + # $is_release = (.git directory does not exist) + AS_IF([test -d ${srcdir}/.git],[ax_is_release=no],[ax_is_release=yes]) + ], + [minor-version],[ + # $is_release = ($minor_version is even) + minor_version=`echo "$PACKAGE_VERSION" | sed 's/[[^.]][[^.]]*.\([[^.]][[^.]]*\).*/\1/'` + AS_IF([test "$(( $minor_version % 2 ))" -ne 0], + [ax_is_release=no],[ax_is_release=yes]) + ], + [micro-version],[ + # $is_release = ($micro_version is even) + micro_version=`echo "$PACKAGE_VERSION" | sed 's/[[^.]]*\.[[^.]]*\.\([[^.]]*\).*/\1/'` + AS_IF([test "$(( $micro_version % 2 ))" -ne 0], + [ax_is_release=no],[ax_is_release=yes]) + ], + [dash-version],[ + # $is_release = ($PACKAGE_VERSION has a dash) + AS_CASE([$PACKAGE_VERSION], + [*-*], [ax_is_release=no], + [*], [ax_is_release=yes]) + ], + [always],[ax_is_release=yes], + [never],[ax_is_release=no], + [ + AC_MSG_ERROR([Invalid policy. Valid policies: git-directory, minor-version, micro-version, dash-version, always, never.]) + ]) +]) diff --git a/m4/ax_lib_readline.m4 b/m4/ax_lib_readline.m4 new file mode 100644 index 0000000..0d0822b --- /dev/null +++ b/m4/ax_lib_readline.m4 @@ -0,0 +1,107 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_lib_readline.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_LIB_READLINE +# +# DESCRIPTION +# +# Searches for a readline compatible library. If found, defines +# `HAVE_LIBREADLINE'. If the found library has the `add_history' function, +# sets also `HAVE_READLINE_HISTORY'. Also checks for the locations of the +# necessary include files and sets `HAVE_READLINE_H' or +# `HAVE_READLINE_READLINE_H' and `HAVE_READLINE_HISTORY_H' or +# 'HAVE_HISTORY_H' if the corresponding include files exists. +# +# The libraries that may be readline compatible are `libedit', +# `libeditline' and `libreadline'. Sometimes we need to link a termcap +# library for readline to work, this macro tests these cases too by trying +# to link with `libtermcap', `libcurses' or `libncurses' before giving up. +# +# Here is an example of how to use the information provided by this macro +# to perform the necessary includes or declarations in a C file: +# +# #ifdef HAVE_LIBREADLINE +# # if defined(HAVE_READLINE_READLINE_H) +# # include +# # elif defined(HAVE_READLINE_H) +# # include +# # else /* !defined(HAVE_READLINE_H) */ +# extern char *readline (); +# # endif /* !defined(HAVE_READLINE_H) */ +# char *cmdline = NULL; +# #else /* !defined(HAVE_READLINE_READLINE_H) */ +# /* no readline */ +# #endif /* HAVE_LIBREADLINE */ +# +# #ifdef HAVE_READLINE_HISTORY +# # if defined(HAVE_READLINE_HISTORY_H) +# # include +# # elif defined(HAVE_HISTORY_H) +# # include +# # else /* !defined(HAVE_HISTORY_H) */ +# extern void add_history (); +# extern int write_history (); +# extern int read_history (); +# # endif /* defined(HAVE_READLINE_HISTORY_H) */ +# /* no history */ +# #endif /* HAVE_READLINE_HISTORY */ +# +# LICENSE +# +# Copyright (c) 2008 Ville Laurikari +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 8 + +AU_ALIAS([VL_LIB_READLINE], [AX_LIB_READLINE]) +AC_DEFUN([AX_LIB_READLINE], [ + AC_CACHE_CHECK([for a readline compatible library], + ax_cv_lib_readline, [ + ORIG_LIBS="$LIBS" + for readline_lib in readline edit editline; do + for termcap_lib in "" termcap curses ncurses; do + if test -z "$termcap_lib"; then + TRY_LIB="-l$readline_lib" + else + TRY_LIB="-l$readline_lib -l$termcap_lib" + fi + LIBS="$ORIG_LIBS $TRY_LIB" + AC_LINK_IFELSE([AC_LANG_CALL([], [readline])], [ax_cv_lib_readline="$TRY_LIB"]) + if test -n "$ax_cv_lib_readline"; then + break + fi + done + if test -n "$ax_cv_lib_readline"; then + break + fi + done + if test -z "$ax_cv_lib_readline"; then + ax_cv_lib_readline="no" + fi + LIBS="$ORIG_LIBS" + ]) + + if test "$ax_cv_lib_readline" != "no"; then + LIBS="$LIBS $ax_cv_lib_readline" + AC_DEFINE(HAVE_LIBREADLINE, 1, + [Define if you have a readline compatible library]) + AC_CHECK_HEADERS(readline.h readline/readline.h) + AC_CACHE_CHECK([whether readline supports history], + ax_cv_lib_readline_history, [ + ax_cv_lib_readline_history="no" + AC_LINK_IFELSE([AC_LANG_CALL([], [add_history])], [ax_cv_lib_readline_history="yes"]) + ]) + if test "$ax_cv_lib_readline_history" = "yes"; then + AC_DEFINE(HAVE_READLINE_HISTORY, 1, + [Define if your readline library has \`add_history']) + AC_CHECK_HEADERS(history.h readline/history.h) + fi + fi +])dnl diff --git a/m4/ax_require_defined.m4 b/m4/ax_require_defined.m4 new file mode 100644 index 0000000..17c3eab --- /dev/null +++ b/m4/ax_require_defined.m4 @@ -0,0 +1,37 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_require_defined.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_REQUIRE_DEFINED(MACRO) +# +# DESCRIPTION +# +# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have +# been defined and thus are available for use. This avoids random issues +# where a macro isn't expanded. Instead the configure script emits a +# non-fatal: +# +# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found +# +# It's like AC_REQUIRE except it doesn't expand the required macro. +# +# Here's an example: +# +# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) +# +# LICENSE +# +# Copyright (c) 2014 Mike Frysinger +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 2 + +AC_DEFUN([AX_REQUIRE_DEFINED], [dnl + m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) +])dnl AX_REQUIRE_DEFINED diff --git a/m4/ax_valgrind_check.m4 b/m4/ax_valgrind_check.m4 new file mode 100644 index 0000000..7033798 --- /dev/null +++ b/m4/ax_valgrind_check.m4 @@ -0,0 +1,239 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_valgrind_check.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_VALGRIND_DFLT(memcheck|helgrind|drd|sgcheck, on|off) +# AX_VALGRIND_CHECK() +# +# DESCRIPTION +# +# AX_VALGRIND_CHECK checks whether Valgrind is present and, if so, allows +# running `make check` under a variety of Valgrind tools to check for +# memory and threading errors. +# +# Defines VALGRIND_CHECK_RULES which should be substituted in your +# Makefile; and $enable_valgrind which can be used in subsequent configure +# output. VALGRIND_ENABLED is defined and substituted, and corresponds to +# the value of the --enable-valgrind option, which defaults to being +# enabled if Valgrind is installed and disabled otherwise. Individual +# Valgrind tools can be disabled via --disable-valgrind-, the +# default is configurable via the AX_VALGRIND_DFLT command or is to use +# all commands not disabled via AX_VALGRIND_DFLT. All AX_VALGRIND_DFLT +# calls must be made before the call to AX_VALGRIND_CHECK. +# +# If unit tests are written using a shell script and automake's +# LOG_COMPILER system, the $(VALGRIND) variable can be used within the +# shell scripts to enable Valgrind, as described here: +# +# https://www.gnu.org/software/gnulib/manual/html_node/Running-self_002dtests-under-valgrind.html +# +# Usage example: +# +# configure.ac: +# +# AX_VALGRIND_DFLT([sgcheck], [off]) +# AX_VALGRIND_CHECK +# +# in each Makefile.am with tests: +# +# @VALGRIND_CHECK_RULES@ +# VALGRIND_SUPPRESSIONS_FILES = my-project.supp +# EXTRA_DIST = my-project.supp +# +# This results in a "check-valgrind" rule being added. Running `make +# check-valgrind` in that directory will recursively run the module's test +# suite (`make check`) once for each of the available Valgrind tools (out +# of memcheck, helgrind and drd) while the sgcheck will be skipped unless +# enabled again on the commandline with --enable-valgrind-sgcheck. The +# results for each check will be output to test-suite-$toolname.log. The +# target will succeed if there are zero errors and fail otherwise. +# +# Alternatively, a "check-valgrind-$TOOL" rule will be added, for $TOOL in +# memcheck, helgrind, drd and sgcheck. These are useful because often only +# some of those tools can be ran cleanly on a codebase. +# +# The macro supports running with and without libtool. +# +# LICENSE +# +# Copyright (c) 2014, 2015, 2016 Philip Withnall +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 17 + +dnl Configured tools +m4_define([valgrind_tool_list], [[memcheck], [helgrind], [drd], [sgcheck]]) +m4_set_add_all([valgrind_exp_tool_set], [sgcheck]) +m4_foreach([vgtool], [valgrind_tool_list], + [m4_define([en_dflt_valgrind_]vgtool, [on])]) + +AC_DEFUN([AX_VALGRIND_DFLT],[ + m4_define([en_dflt_valgrind_$1], [$2]) +])dnl + +AM_EXTRA_RECURSIVE_TARGETS([check-valgrind]) +m4_foreach([vgtool], [valgrind_tool_list], + [AM_EXTRA_RECURSIVE_TARGETS([check-valgrind-]vgtool)]) + +AC_DEFUN([AX_VALGRIND_CHECK],[ + dnl Check for --enable-valgrind + AC_ARG_ENABLE([valgrind], + [AS_HELP_STRING([--enable-valgrind], [Whether to enable Valgrind on the unit tests])], + [enable_valgrind=$enableval],[enable_valgrind=]) + + AS_IF([test "$enable_valgrind" != "no"],[ + # Check for Valgrind. + AC_CHECK_PROG([VALGRIND],[valgrind],[valgrind]) + AS_IF([test "$VALGRIND" = ""],[ + AS_IF([test "$enable_valgrind" = "yes"],[ + AC_MSG_ERROR([Could not find valgrind; either install it or reconfigure with --disable-valgrind]) + ],[ + enable_valgrind=no + ]) + ],[ + enable_valgrind=yes + ]) + ]) + + AM_CONDITIONAL([VALGRIND_ENABLED],[test "$enable_valgrind" = "yes"]) + AC_SUBST([VALGRIND_ENABLED],[$enable_valgrind]) + + # Check for Valgrind tools we care about. + [valgrind_enabled_tools=] + m4_foreach([vgtool],[valgrind_tool_list],[ + AC_ARG_ENABLE([valgrind-]vgtool, + m4_if(m4_defn([en_dflt_valgrind_]vgtool),[off],dnl +[AS_HELP_STRING([--enable-valgrind-]vgtool, [Whether to use ]vgtool[ during the Valgrind tests])],dnl +[AS_HELP_STRING([--disable-valgrind-]vgtool, [Whether to skip ]vgtool[ during the Valgrind tests])]), + [enable_valgrind_]vgtool[=$enableval], + [enable_valgrind_]vgtool[=]) + AS_IF([test "$enable_valgrind" = "no"],[ + enable_valgrind_]vgtool[=no], + [test "$enable_valgrind_]vgtool[" ]dnl +m4_if(m4_defn([en_dflt_valgrind_]vgtool), [off], [= "yes"], [!= "no"]),[ + AC_CACHE_CHECK([for Valgrind tool ]vgtool, + [ax_cv_valgrind_tool_]vgtool,[ + ax_cv_valgrind_tool_]vgtool[=no + m4_set_contains([valgrind_exp_tool_set],vgtool, + [m4_define([vgtoolx],[exp-]vgtool)], + [m4_define([vgtoolx],vgtool)]) + AS_IF([`$VALGRIND --tool=]vgtoolx[ --help >/dev/null 2>&1`],[ + ax_cv_valgrind_tool_]vgtool[=yes + ]) + ]) + AS_IF([test "$ax_cv_valgrind_tool_]vgtool[" = "no"],[ + AS_IF([test "$enable_valgrind_]vgtool[" = "yes"],[ + AC_MSG_ERROR([Valgrind does not support ]vgtool[; reconfigure with --disable-valgrind-]vgtool) + ],[ + enable_valgrind_]vgtool[=no + ]) + ],[ + enable_valgrind_]vgtool[=yes + ]) + ]) + AS_IF([test "$enable_valgrind_]vgtool[" = "yes"],[ + valgrind_enabled_tools="$valgrind_enabled_tools ]m4_bpatsubst(vgtool,[^exp-])[" + ]) + AC_SUBST([ENABLE_VALGRIND_]vgtool,[$enable_valgrind_]vgtool) + ]) + AC_SUBST([valgrind_tools],["]m4_join([ ], valgrind_tool_list)["]) + AC_SUBST([valgrind_enabled_tools],[$valgrind_enabled_tools]) + +[VALGRIND_CHECK_RULES=' +# Valgrind check +# +# Optional: +# - VALGRIND_SUPPRESSIONS_FILES: Space-separated list of Valgrind suppressions +# files to load. (Default: empty) +# - VALGRIND_FLAGS: General flags to pass to all Valgrind tools. +# (Default: --num-callers=30) +# - VALGRIND_$toolname_FLAGS: Flags to pass to Valgrind $toolname (one of: +# memcheck, helgrind, drd, sgcheck). (Default: various) + +# Optional variables +VALGRIND_SUPPRESSIONS ?= $(addprefix --suppressions=,$(VALGRIND_SUPPRESSIONS_FILES)) +VALGRIND_FLAGS ?= --num-callers=30 +VALGRIND_memcheck_FLAGS ?= --leak-check=full --show-reachable=no +VALGRIND_helgrind_FLAGS ?= --history-level=approx +VALGRIND_drd_FLAGS ?= +VALGRIND_sgcheck_FLAGS ?= + +# Internal use +valgrind_log_files = $(addprefix test-suite-,$(addsuffix .log,$(valgrind_tools))) + +valgrind_memcheck_flags = --tool=memcheck $(VALGRIND_memcheck_FLAGS) +valgrind_helgrind_flags = --tool=helgrind $(VALGRIND_helgrind_FLAGS) +valgrind_drd_flags = --tool=drd $(VALGRIND_drd_FLAGS) +valgrind_sgcheck_flags = --tool=exp-sgcheck $(VALGRIND_sgcheck_FLAGS) + +valgrind_quiet = $(valgrind_quiet_$(V)) +valgrind_quiet_ = $(valgrind_quiet_$(AM_DEFAULT_VERBOSITY)) +valgrind_quiet_0 = --quiet +valgrind_v_use = $(valgrind_v_use_$(V)) +valgrind_v_use_ = $(valgrind_v_use_$(AM_DEFAULT_VERBOSITY)) +valgrind_v_use_0 = @echo " USE " $(patsubst check-valgrind-%-am,%,$''@):; + +# Support running with and without libtool. +ifneq ($(LIBTOOL),) +valgrind_lt = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=execute +else +valgrind_lt = +endif + +# Use recursive makes in order to ignore errors during check +check-valgrind-am: +ifeq ($(VALGRIND_ENABLED),yes) + $(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k \ + $(foreach tool, $(valgrind_enabled_tools), check-valgrind-$(tool)) +else + @echo "Need to reconfigure with --enable-valgrind" +endif + +# Valgrind running +VALGRIND_TESTS_ENVIRONMENT = \ + $(TESTS_ENVIRONMENT) \ + env VALGRIND=$(VALGRIND) \ + G_SLICE=always-malloc,debug-blocks \ + G_DEBUG=fatal-warnings,fatal-criticals,gc-friendly + +VALGRIND_LOG_COMPILER = \ + $(valgrind_lt) \ + $(VALGRIND) $(VALGRIND_SUPPRESSIONS) --error-exitcode=1 $(VALGRIND_FLAGS) + +define valgrind_tool_rule +check-valgrind-$(1)-am: +ifeq ($$(VALGRIND_ENABLED)-$$(ENABLE_VALGRIND_$(1)),yes-yes) +ifneq ($$(TESTS),) + $$(valgrind_v_use)$$(MAKE) check-TESTS \ + TESTS_ENVIRONMENT="$$(VALGRIND_TESTS_ENVIRONMENT)" \ + LOG_COMPILER="$$(VALGRIND_LOG_COMPILER)" \ + LOG_FLAGS="$$(valgrind_$(1)_flags)" \ + TEST_SUITE_LOG=test-suite-$(1).log +endif +else ifeq ($$(VALGRIND_ENABLED),yes) + @echo "Need to reconfigure with --enable-valgrind-$(1)" +else + @echo "Need to reconfigure with --enable-valgrind" +endif +endef + +$(foreach tool,$(valgrind_tools),$(eval $(call valgrind_tool_rule,$(tool)))) + +A''M_DISTCHECK_CONFIGURE_FLAGS ?= +A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-valgrind + +MOSTLYCLEANFILES ?= +MOSTLYCLEANFILES += $(valgrind_log_files) + +.PHONY: check-valgrind $(add-prefix check-valgrind-,$(valgrind_tools)) +'] + + AC_SUBST([VALGRIND_CHECK_RULES]) + m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([VALGRIND_CHECK_RULES])]) +]) diff --git a/m4/guile-2.2.m4 b/m4/guile-2.2.m4 new file mode 100644 index 0000000..89823e9 --- /dev/null +++ b/m4/guile-2.2.m4 @@ -0,0 +1,394 @@ +## Autoconf macros for working with Guile. +## +## Copyright (C) 1998,2001, 2006, 2010, 2012, 2013, 2014 Free Software Foundation, Inc. +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public License +## as published by the Free Software Foundation; either version 3 of +## the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +## 02110-1301 USA + +# serial 10 + +## Index +## ----- +## +## GUILE_PKG -- find Guile development files +## GUILE_PROGS -- set paths to Guile interpreter, config and tool programs +## GUILE_FLAGS -- set flags for compiling and linking with Guile +## GUILE_SITE_DIR -- find path to Guile "site" directories +## GUILE_CHECK -- evaluate Guile Scheme code and capture the return value +## GUILE_MODULE_CHECK -- check feature of a Guile Scheme module +## GUILE_MODULE_AVAILABLE -- check availability of a Guile Scheme module +## GUILE_MODULE_REQUIRED -- fail if a Guile Scheme module is unavailable +## GUILE_MODULE_EXPORTS -- check if a module exports a variable +## GUILE_MODULE_REQUIRED_EXPORT -- fail if a module doesn't export a variable + +## Code +## ---- + +## NOTE: Comments preceding an AC_DEFUN (starting from "Usage:") are massaged +## into doc/ref/autoconf-macros.texi (see Makefile.am in that directory). + +# GUILE_PKG -- find Guile development files +# +# Usage: GUILE_PKG([VERSIONS]) +# +# This macro runs the @code{pkg-config} tool to find development files +# for an available version of Guile. +# +# By default, this macro will search for the latest stable version of +# Guile (e.g. 2.2), falling back to the previous stable version +# (e.g. 2.0) if it is available. If no guile-@var{VERSION}.pc file is +# found, an error is signalled. The found version is stored in +# @var{GUILE_EFFECTIVE_VERSION}. +# +# If @code{GUILE_PROGS} was already invoked, this macro ensures that the +# development files have the same effective version as the Guile +# program. +# +# @var{GUILE_EFFECTIVE_VERSION} is marked for substitution, as by +# @code{AC_SUBST}. +# +AC_DEFUN([GUILE_PKG], + [PKG_PROG_PKG_CONFIG + _guile_versions_to_search="m4_default([$1], [2.2 2.0 1.8])" + if test -n "$GUILE_EFFECTIVE_VERSION"; then + _guile_tmp="" + for v in $_guile_versions_to_search; do + if test "$v" = "$GUILE_EFFECTIVE_VERSION"; then + _guile_tmp=$v + fi + done + if test -z "$_guile_tmp"; then + AC_MSG_FAILURE([searching for guile development files for versions $_guile_versions_to_search, but previously found $GUILE version $GUILE_EFFECTIVE_VERSION]) + fi + _guile_versions_to_search=$GUILE_EFFECTIVE_VERSION + fi + GUILE_EFFECTIVE_VERSION="" + _guile_errors="" + for v in $_guile_versions_to_search; do + if test -z "$GUILE_EFFECTIVE_VERSION"; then + AC_MSG_NOTICE([checking for guile $v]) + PKG_CHECK_EXISTS([guile-$v], [GUILE_EFFECTIVE_VERSION=$v], []) + fi + done + + if test -z "$GUILE_EFFECTIVE_VERSION"; then + AC_MSG_ERROR([ +No Guile development packages were found. + +Please verify that you have Guile installed. If you installed Guile +from a binary distribution, please verify that you have also installed +the development packages. If you installed it yourself, you might need +to adjust your PKG_CONFIG_PATH; see the pkg-config man page for more. +]) + fi + AC_MSG_NOTICE([found guile $GUILE_EFFECTIVE_VERSION]) + AC_SUBST([GUILE_EFFECTIVE_VERSION]) + ]) + +# GUILE_FLAGS -- set flags for compiling and linking with Guile +# +# Usage: GUILE_FLAGS +# +# This macro runs the @code{pkg-config} tool to find out how to compile +# and link programs against Guile. It sets four variables: +# @var{GUILE_CFLAGS}, @var{GUILE_LDFLAGS}, @var{GUILE_LIBS}, and +# @var{GUILE_LTLIBS}. +# +# @var{GUILE_CFLAGS}: flags to pass to a C or C++ compiler to build code that +# uses Guile header files. This is almost always just one or more @code{-I} +# flags. +# +# @var{GUILE_LDFLAGS}: flags to pass to the compiler to link a program +# against Guile. This includes @code{-lguile-@var{VERSION}} for the +# Guile library itself, and may also include one or more @code{-L} flag +# to tell the compiler where to find the libraries. But it does not +# include flags that influence the program's runtime search path for +# libraries, and will therefore lead to a program that fails to start, +# unless all necessary libraries are installed in a standard location +# such as @file{/usr/lib}. +# +# @var{GUILE_LIBS} and @var{GUILE_LTLIBS}: flags to pass to the compiler or to +# libtool, respectively, to link a program against Guile. It includes flags +# that augment the program's runtime search path for libraries, so that shared +# libraries will be found at the location where they were during linking, even +# in non-standard locations. @var{GUILE_LIBS} is to be used when linking the +# program directly with the compiler, whereas @var{GUILE_LTLIBS} is to be used +# when linking the program is done through libtool. +# +# The variables are marked for substitution, as by @code{AC_SUBST}. +# +AC_DEFUN([GUILE_FLAGS], + [AC_REQUIRE([GUILE_PKG]) + PKG_CHECK_MODULES(GUILE, [guile-$GUILE_EFFECTIVE_VERSION]) + + dnl GUILE_CFLAGS and GUILE_LIBS are already defined and AC_SUBST'd by + dnl PKG_CHECK_MODULES. But GUILE_LIBS to pkg-config is GUILE_LDFLAGS + dnl to us. + + GUILE_LDFLAGS=$GUILE_LIBS + + dnl Determine the platform dependent parameters needed to use rpath. + dnl AC_LIB_LINKFLAGS_FROM_LIBS is defined in gnulib/m4/lib-link.m4 and needs + dnl the file gnulib/build-aux/config.rpath. + AC_LIB_LINKFLAGS_FROM_LIBS([GUILE_LIBS], [$GUILE_LDFLAGS], []) + GUILE_LIBS="$GUILE_LDFLAGS $GUILE_LIBS" + AC_LIB_LINKFLAGS_FROM_LIBS([GUILE_LTLIBS], [$GUILE_LDFLAGS], [yes]) + GUILE_LTLIBS="$GUILE_LDFLAGS $GUILE_LTLIBS" + + AC_SUBST([GUILE_EFFECTIVE_VERSION]) + AC_SUBST([GUILE_CFLAGS]) + AC_SUBST([GUILE_LDFLAGS]) + AC_SUBST([GUILE_LIBS]) + AC_SUBST([GUILE_LTLIBS]) + ]) + +# GUILE_SITE_DIR -- find path to Guile site directories +# +# Usage: GUILE_SITE_DIR +# +# This looks for Guile's "site" directories. The variable @var{GUILE_SITE} will +# be set to Guile's "site" directory for Scheme source files (usually something +# like PREFIX/share/guile/site). @var{GUILE_SITE_CCACHE} will be set to the +# directory for compiled Scheme files also known as @code{.go} files +# (usually something like +# PREFIX/lib/guile/@var{GUILE_EFFECTIVE_VERSION}/site-ccache). +# @var{GUILE_EXTENSION} will be set to the directory for compiled C extensions +# (usually something like +# PREFIX/lib/guile/@var{GUILE_EFFECTIVE_VERSION}/extensions). The latter two +# are set to blank if the particular version of Guile does not support +# them. Note that this macro will run the macros @code{GUILE_PKG} and +# @code{GUILE_PROGS} if they have not already been run. +# +# The variables are marked for substitution, as by @code{AC_SUBST}. +# +AC_DEFUN([GUILE_SITE_DIR], + [AC_REQUIRE([GUILE_PKG]) + AC_REQUIRE([GUILE_PROGS]) + AC_MSG_CHECKING(for Guile site directory) + GUILE_SITE=`$PKG_CONFIG --print-errors --variable=sitedir guile-$GUILE_EFFECTIVE_VERSION` + AC_MSG_RESULT($GUILE_SITE) + if test "$GUILE_SITE" = ""; then + AC_MSG_FAILURE(sitedir not found) + fi + AC_SUBST(GUILE_SITE) + AC_MSG_CHECKING([for Guile site-ccache directory using pkgconfig]) + GUILE_SITE_CCACHE=`$PKG_CONFIG --variable=siteccachedir guile-$GUILE_EFFECTIVE_VERSION` + if test "$GUILE_SITE_CCACHE" = ""; then + AC_MSG_RESULT(no) + AC_MSG_CHECKING([for Guile site-ccache directory using interpreter]) + GUILE_SITE_CCACHE=`$GUILE -c "(display (if (defined? '%site-ccache-dir) (%site-ccache-dir) \"\"))"` + if test $? != "0" -o "$GUILE_SITE_CCACHE" = ""; then + AC_MSG_RESULT(no) + GUILE_SITE_CCACHE="" + AC_MSG_WARN([siteccachedir not found]) + fi + fi + AC_MSG_RESULT($GUILE_SITE_CCACHE) + AC_SUBST([GUILE_SITE_CCACHE]) + AC_MSG_CHECKING(for Guile extensions directory) + GUILE_EXTENSION=`$PKG_CONFIG --print-errors --variable=extensiondir guile-$GUILE_EFFECTIVE_VERSION` + AC_MSG_RESULT($GUILE_EXTENSION) + if test "$GUILE_EXTENSION" = ""; then + GUILE_EXTENSION="" + AC_MSG_WARN(extensiondir not found) + fi + AC_SUBST(GUILE_EXTENSION) + ]) + +# GUILE_PROGS -- set paths to Guile interpreter, config and tool programs +# +# Usage: GUILE_PROGS([VERSION]) +# +# This macro looks for programs @code{guile} and @code{guild}, setting +# variables @var{GUILE} and @var{GUILD} to their paths, respectively. +# The macro will attempt to find @code{guile} with the suffix of +# @code{-X.Y}, followed by looking for it with the suffix @code{X.Y}, and +# then fall back to looking for @code{guile} with no suffix. If +# @code{guile} is still not found, signal an error. The suffix, if any, +# that was required to find @code{guile} will be used for @code{guild} +# as well. +# +# By default, this macro will search for the latest stable version of +# Guile (e.g. 2.2). x.y or x.y.z versions can be specified. If an older +# version is found, the macro will signal an error. +# +# The effective version of the found @code{guile} is set to +# @var{GUILE_EFFECTIVE_VERSION}. This macro ensures that the effective +# version is compatible with the result of a previous invocation of +# @code{GUILE_FLAGS}, if any. +# +# As a legacy interface, it also looks for @code{guile-config} and +# @code{guile-tools}, setting @var{GUILE_CONFIG} and @var{GUILE_TOOLS}. +# +# The variables are marked for substitution, as by @code{AC_SUBST}. +# +AC_DEFUN([GUILE_PROGS], + [_guile_required_version="m4_default([$1], [$GUILE_EFFECTIVE_VERSION])" + if test -z "$_guile_required_version"; then + _guile_required_version=2.2 + fi + + _guile_candidates=guile + _tmp= + for v in `echo "$_guile_required_version" | tr . ' '`; do + if test -n "$_tmp"; then _tmp=$_tmp.; fi + _tmp=$_tmp$v + _guile_candidates="guile-$_tmp guile$_tmp $_guile_candidates" + done + + AC_PATH_PROGS(GUILE,[$_guile_candidates]) + if test -z "$GUILE"; then + AC_MSG_ERROR([guile required but not found]) + fi + + _guile_suffix=`echo "$GUILE" | sed -e 's,^.*/guile\(.*\)$,\1,'` + _guile_effective_version=`$GUILE -c "(display (effective-version))"` + if test -z "$GUILE_EFFECTIVE_VERSION"; then + GUILE_EFFECTIVE_VERSION=$_guile_effective_version + elif test "$GUILE_EFFECTIVE_VERSION" != "$_guile_effective_version"; then + AC_MSG_ERROR([found development files for Guile $GUILE_EFFECTIVE_VERSION, but $GUILE has effective version $_guile_effective_version]) + fi + + _guile_major_version=`$GUILE -c "(display (major-version))"` + _guile_minor_version=`$GUILE -c "(display (minor-version))"` + _guile_micro_version=`$GUILE -c "(display (micro-version))"` + _guile_prog_version="$_guile_major_version.$_guile_minor_version.$_guile_micro_version" + + AC_MSG_CHECKING([for Guile version >= $_guile_required_version]) + _major_version=`echo $_guile_required_version | cut -d . -f 1` + _minor_version=`echo $_guile_required_version | cut -d . -f 2` + _micro_version=`echo $_guile_required_version | cut -d . -f 3` + if test "$_guile_major_version" -gt "$_major_version"; then + true + elif test "$_guile_major_version" -eq "$_major_version"; then + if test "$_guile_minor_version" -gt "$_minor_version"; then + true + elif test "$_guile_minor_version" -eq "$_minor_version"; then + if test -n "$_micro_version"; then + if test "$_guile_micro_version" -lt "$_micro_version"; then + AC_MSG_ERROR([Guile $_guile_required_version required, but $_guile_prog_version found]) + fi + fi + elif test "$GUILE_EFFECTIVE_VERSION" = "$_major_version.$_minor_version" -a -z "$_micro_version"; then + # Allow prereleases that have the right effective version. + true + else + as_fn_error $? "Guile $_guile_required_version required, but $_guile_prog_version found" "$LINENO" 5 + fi + elif test "$GUILE_EFFECTIVE_VERSION" = "$_major_version.$_minor_version" -a -z "$_micro_version"; then + # Allow prereleases that have the right effective version. + true + else + AC_MSG_ERROR([Guile $_guile_required_version required, but $_guile_prog_version found]) + fi + AC_MSG_RESULT([$_guile_prog_version]) + + AC_PATH_PROG(GUILD,[guild$_guile_suffix]) + AC_SUBST(GUILD) + + AC_PATH_PROG(GUILE_CONFIG,[guile-config$_guile_suffix]) + AC_SUBST(GUILE_CONFIG) + if test -n "$GUILD"; then + GUILE_TOOLS=$GUILD + else + AC_PATH_PROG(GUILE_TOOLS,[guile-tools$_guile_suffix]) + fi + AC_SUBST(GUILE_TOOLS) + ]) + +# GUILE_CHECK -- evaluate Guile Scheme code and capture the return value +# +# Usage: GUILE_CHECK_RETVAL(var,check) +# +# @var{var} is a shell variable name to be set to the return value. +# @var{check} is a Guile Scheme expression, evaluated with "$GUILE -c", and +# returning either 0 or non-#f to indicate the check passed. +# Non-0 number or #f indicates failure. +# Avoid using the character "#" since that confuses autoconf. +# +AC_DEFUN([GUILE_CHECK], + [AC_REQUIRE([GUILE_PROGS]) + $GUILE -c "$2" > /dev/null 2>&1 + $1=$? + ]) + +# GUILE_MODULE_CHECK -- check feature of a Guile Scheme module +# +# Usage: GUILE_MODULE_CHECK(var,module,featuretest,description) +# +# @var{var} is a shell variable name to be set to "yes" or "no". +# @var{module} is a list of symbols, like: (ice-9 common-list). +# @var{featuretest} is an expression acceptable to GUILE_CHECK, q.v. +# @var{description} is a present-tense verb phrase (passed to AC_MSG_CHECKING). +# +AC_DEFUN([GUILE_MODULE_CHECK], + [AC_MSG_CHECKING([if $2 $4]) + GUILE_CHECK($1,(use-modules $2) (exit ((lambda () $3)))) + if test "$$1" = "0" ; then $1=yes ; else $1=no ; fi + AC_MSG_RESULT($$1) + ]) + +# GUILE_MODULE_AVAILABLE -- check availability of a Guile Scheme module +# +# Usage: GUILE_MODULE_AVAILABLE(var,module) +# +# @var{var} is a shell variable name to be set to "yes" or "no". +# @var{module} is a list of symbols, like: (ice-9 common-list). +# +AC_DEFUN([GUILE_MODULE_AVAILABLE], + [GUILE_MODULE_CHECK($1,$2,0,is available) + ]) + +# GUILE_MODULE_REQUIRED -- fail if a Guile Scheme module is unavailable +# +# Usage: GUILE_MODULE_REQUIRED(symlist) +# +# @var{symlist} is a list of symbols, WITHOUT surrounding parens, +# like: ice-9 common-list. +# +AC_DEFUN([GUILE_MODULE_REQUIRED], + [GUILE_MODULE_AVAILABLE(ac_guile_module_required, ($1)) + if test "$ac_guile_module_required" = "no" ; then + AC_MSG_ERROR([required guile module not found: ($1)]) + fi + ]) + +# GUILE_MODULE_EXPORTS -- check if a module exports a variable +# +# Usage: GUILE_MODULE_EXPORTS(var,module,modvar) +# +# @var{var} is a shell variable to be set to "yes" or "no". +# @var{module} is a list of symbols, like: (ice-9 common-list). +# @var{modvar} is the Guile Scheme variable to check. +# +AC_DEFUN([GUILE_MODULE_EXPORTS], + [GUILE_MODULE_CHECK($1,$2,$3,exports `$3') + ]) + +# GUILE_MODULE_REQUIRED_EXPORT -- fail if a module doesn't export a variable +# +# Usage: GUILE_MODULE_REQUIRED_EXPORT(module,modvar) +# +# @var{module} is a list of symbols, like: (ice-9 common-list). +# @var{modvar} is the Guile Scheme variable to check. +# +AC_DEFUN([GUILE_MODULE_REQUIRED_EXPORT], + [GUILE_MODULE_EXPORTS(guile_module_required_export,$1,$2) + if test "$guile_module_required_export" = "no" ; then + AC_MSG_ERROR([module $1 does not export $2; required]) + fi + ]) + +## guile.m4 ends here diff --git a/m4/host-cpu-c-abi.m4 b/m4/host-cpu-c-abi.m4 new file mode 100644 index 0000000..6db2aa2 --- /dev/null +++ b/m4/host-cpu-c-abi.m4 @@ -0,0 +1,675 @@ +# host-cpu-c-abi.m4 serial 13 +dnl Copyright (C) 2002-2020 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible and Sam Steingold. + +dnl Sets the HOST_CPU variable to the canonical name of the CPU. +dnl Sets the HOST_CPU_C_ABI variable to the canonical name of the CPU with its +dnl C language ABI (application binary interface). +dnl Also defines __${HOST_CPU}__ and __${HOST_CPU_C_ABI}__ as C macros in +dnl config.h. +dnl +dnl This canonical name can be used to select a particular assembly language +dnl source file that will interoperate with C code on the given host. +dnl +dnl For example: +dnl * 'i386' and 'sparc' are different canonical names, because code for i386 +dnl will not run on SPARC CPUs and vice versa. They have different +dnl instruction sets. +dnl * 'sparc' and 'sparc64' are different canonical names, because code for +dnl 'sparc' and code for 'sparc64' cannot be linked together: 'sparc' code +dnl contains 32-bit instructions, whereas 'sparc64' code contains 64-bit +dnl instructions. A process on a SPARC CPU can be in 32-bit mode or in 64-bit +dnl mode, but not both. +dnl * 'mips' and 'mipsn32' are different canonical names, because they use +dnl different argument passing and return conventions for C functions, and +dnl although the instruction set of 'mips' is a large subset of the +dnl instruction set of 'mipsn32'. +dnl * 'mipsn32' and 'mips64' are different canonical names, because they use +dnl different sizes for the C types like 'int' and 'void *', and although +dnl the instruction sets of 'mipsn32' and 'mips64' are the same. +dnl * The same canonical name is used for different endiannesses. You can +dnl determine the endianness through preprocessor symbols: +dnl - 'arm': test __ARMEL__. +dnl - 'mips', 'mipsn32', 'mips64': test _MIPSEB vs. _MIPSEL. +dnl - 'powerpc64': test _BIG_ENDIAN vs. _LITTLE_ENDIAN. +dnl * The same name 'i386' is used for CPUs of type i386, i486, i586 +dnl (Pentium), AMD K7, Pentium II, Pentium IV, etc., because +dnl - Instructions that do not exist on all of these CPUs (cmpxchg, +dnl MMX, SSE, SSE2, 3DNow! etc.) are not frequently used. If your +dnl assembly language source files use such instructions, you will +dnl need to make the distinction. +dnl - Speed of execution of the common instruction set is reasonable across +dnl the entire family of CPUs. If you have assembly language source files +dnl that are optimized for particular CPU types (like GNU gmp has), you +dnl will need to make the distinction. +dnl See . +AC_DEFUN([gl_HOST_CPU_C_ABI], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([gl_C_ASM]) + AC_CACHE_CHECK([host CPU and C ABI], [gl_cv_host_cpu_c_abi], + [case "$host_cpu" in + +changequote(,)dnl + i[34567]86 ) +changequote([,])dnl + gl_cv_host_cpu_c_abi=i386 + ;; + + x86_64 ) + # On x86_64 systems, the C compiler may be generating code in one of + # these ABIs: + # - 64-bit instruction set, 64-bit pointers, 64-bit 'long': x86_64. + # - 64-bit instruction set, 64-bit pointers, 32-bit 'long': x86_64 + # with native Windows (mingw, MSVC). + # - 64-bit instruction set, 32-bit pointers, 32-bit 'long': x86_64-x32. + # - 32-bit instruction set, 32-bit pointers, 32-bit 'long': i386. + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#if (defined __x86_64__ || defined __amd64__ \ + || defined _M_X64 || defined _M_AMD64) + int ok; + #else + error fail + #endif + ]])], + [AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#if defined __ILP32__ || defined _ILP32 + int ok; + #else + error fail + #endif + ]])], + [gl_cv_host_cpu_c_abi=x86_64-x32], + [gl_cv_host_cpu_c_abi=x86_64])], + [gl_cv_host_cpu_c_abi=i386]) + ;; + +changequote(,)dnl + alphaev[4-8] | alphaev56 | alphapca5[67] | alphaev6[78] ) +changequote([,])dnl + gl_cv_host_cpu_c_abi=alpha + ;; + + arm* | aarch64 ) + # Assume arm with EABI. + # On arm64 systems, the C compiler may be generating code in one of + # these ABIs: + # - aarch64 instruction set, 64-bit pointers, 64-bit 'long': arm64. + # - aarch64 instruction set, 32-bit pointers, 32-bit 'long': arm64-ilp32. + # - 32-bit instruction set, 32-bit pointers, 32-bit 'long': arm or armhf. + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#ifdef __aarch64__ + int ok; + #else + error fail + #endif + ]])], + [AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#if defined __ILP32__ || defined _ILP32 + int ok; + #else + error fail + #endif + ]])], + [gl_cv_host_cpu_c_abi=arm64-ilp32], + [gl_cv_host_cpu_c_abi=arm64])], + [# Don't distinguish little-endian and big-endian arm, since they + # don't require different machine code for simple operations and + # since the user can distinguish them through the preprocessor + # defines __ARMEL__ vs. __ARMEB__. + # But distinguish arm which passes floating-point arguments and + # return values in integer registers (r0, r1, ...) - this is + # gcc -mfloat-abi=soft or gcc -mfloat-abi=softfp - from arm which + # passes them in float registers (s0, s1, ...) and double registers + # (d0, d1, ...) - this is gcc -mfloat-abi=hard. GCC 4.6 or newer + # sets the preprocessor defines __ARM_PCS (for the first case) and + # __ARM_PCS_VFP (for the second case), but older GCC does not. + echo 'double ddd; void func (double dd) { ddd = dd; }' > conftest.c + # Look for a reference to the register d0 in the .s file. + AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $gl_c_asm_opt conftest.c) >/dev/null 2>&1 + if LC_ALL=C grep 'd0,' conftest.$gl_asmext >/dev/null; then + gl_cv_host_cpu_c_abi=armhf + else + gl_cv_host_cpu_c_abi=arm + fi + rm -f conftest* + ]) + ;; + + hppa1.0 | hppa1.1 | hppa2.0* | hppa64 ) + # On hppa, the C compiler may be generating 32-bit code or 64-bit + # code. In the latter case, it defines _LP64 and __LP64__. + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#ifdef __LP64__ + int ok; + #else + error fail + #endif + ]])], + [gl_cv_host_cpu_c_abi=hppa64], + [gl_cv_host_cpu_c_abi=hppa]) + ;; + + ia64* ) + # On ia64 on HP-UX, the C compiler may be generating 64-bit code or + # 32-bit code. In the latter case, it defines _ILP32. + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#ifdef _ILP32 + int ok; + #else + error fail + #endif + ]])], + [gl_cv_host_cpu_c_abi=ia64-ilp32], + [gl_cv_host_cpu_c_abi=ia64]) + ;; + + mips* ) + # We should also check for (_MIPS_SZPTR == 64), but gcc keeps this + # at 32. + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#if defined _MIPS_SZLONG && (_MIPS_SZLONG == 64) + int ok; + #else + error fail + #endif + ]])], + [gl_cv_host_cpu_c_abi=mips64], + [# In the n32 ABI, _ABIN32 is defined, _ABIO32 is not defined (but + # may later get defined by ), and _MIPS_SIM == _ABIN32. + # In the 32 ABI, _ABIO32 is defined, _ABIN32 is not defined (but + # may later get defined by ), and _MIPS_SIM == _ABIO32. + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#if (_MIPS_SIM == _ABIN32) + int ok; + #else + error fail + #endif + ]])], + [gl_cv_host_cpu_c_abi=mipsn32], + [gl_cv_host_cpu_c_abi=mips])]) + ;; + + powerpc* ) + # Different ABIs are in use on AIX vs. Mac OS X vs. Linux,*BSD. + # No need to distinguish them here; the caller may distinguish + # them based on the OS. + # On powerpc64 systems, the C compiler may still be generating + # 32-bit code. And on powerpc-ibm-aix systems, the C compiler may + # be generating 64-bit code. + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#if defined __powerpc64__ || defined _ARCH_PPC64 + int ok; + #else + error fail + #endif + ]])], + [# On powerpc64, there are two ABIs on Linux: The AIX compatible + # one and the ELFv2 one. The latter defines _CALL_ELF=2. + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#if defined _CALL_ELF && _CALL_ELF == 2 + int ok; + #else + error fail + #endif + ]])], + [gl_cv_host_cpu_c_abi=powerpc64-elfv2], + [gl_cv_host_cpu_c_abi=powerpc64]) + ], + [gl_cv_host_cpu_c_abi=powerpc]) + ;; + + rs6000 ) + gl_cv_host_cpu_c_abi=powerpc + ;; + + riscv32 | riscv64 ) + # There are 2 architectures (with variants): rv32* and rv64*. + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#if __riscv_xlen == 64 + int ok; + #else + error fail + #endif + ]])], + [cpu=riscv64], + [cpu=riscv32]) + # There are 6 ABIs: ilp32, ilp32f, ilp32d, lp64, lp64f, lp64d. + # Size of 'long' and 'void *': + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#if defined __LP64__ + int ok; + #else + error fail + #endif + ]])], + [main_abi=lp64], + [main_abi=ilp32]) + # Float ABIs: + # __riscv_float_abi_double: + # 'float' and 'double' are passed in floating-point registers. + # __riscv_float_abi_single: + # 'float' are passed in floating-point registers. + # __riscv_float_abi_soft: + # No values are passed in floating-point registers. + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#if defined __riscv_float_abi_double + int ok; + #else + error fail + #endif + ]])], + [float_abi=d], + [AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#if defined __riscv_float_abi_single + int ok; + #else + error fail + #endif + ]])], + [float_abi=f], + [float_abi='']) + ]) + gl_cv_host_cpu_c_abi="${cpu}-${main_abi}${float_abi}" + ;; + + s390* ) + # On s390x, the C compiler may be generating 64-bit (= s390x) code + # or 31-bit (= s390) code. + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#if defined __LP64__ || defined __s390x__ + int ok; + #else + error fail + #endif + ]])], + [gl_cv_host_cpu_c_abi=s390x], + [gl_cv_host_cpu_c_abi=s390]) + ;; + + sparc | sparc64 ) + # UltraSPARCs running Linux have `uname -m` = "sparc64", but the + # C compiler still generates 32-bit code. + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#if defined __sparcv9 || defined __arch64__ + int ok; + #else + error fail + #endif + ]])], + [gl_cv_host_cpu_c_abi=sparc64], + [gl_cv_host_cpu_c_abi=sparc]) + ;; + + *) + gl_cv_host_cpu_c_abi="$host_cpu" + ;; + esac + ]) + + dnl In most cases, $HOST_CPU and $HOST_CPU_C_ABI are the same. + HOST_CPU=`echo "$gl_cv_host_cpu_c_abi" | sed -e 's/-.*//'` + HOST_CPU_C_ABI="$gl_cv_host_cpu_c_abi" + AC_SUBST([HOST_CPU]) + AC_SUBST([HOST_CPU_C_ABI]) + + # This was + # AC_DEFINE_UNQUOTED([__${HOST_CPU}__]) + # AC_DEFINE_UNQUOTED([__${HOST_CPU_C_ABI}__]) + # earlier, but KAI C++ 3.2d doesn't like this. + sed -e 's/-/_/g' >> confdefs.h <&1 /dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +if test -n "$LD"; then + AC_MSG_CHECKING([for ld]) +elif test "$GCC" = yes; then + AC_MSG_CHECKING([for ld used by $CC]) +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +if test -n "$LD"; then + # Let the user override the test with a path. + : +else + AC_CACHE_VAL([acl_cv_path_LD], + [ + acl_cv_path_LD= # Final result of this test + ac_prog=ld # Program to search in $PATH + if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + acl_output=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + acl_output=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $acl_output in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + acl_output=`echo "$acl_output" | sed 's%\\\\%/%g'` + while echo "$acl_output" | grep "$re_direlt" > /dev/null 2>&1; do + acl_output=`echo $acl_output | sed "s%$re_direlt%/%"` + done + # Got the pathname. No search in PATH is needed. + acl_cv_path_LD="$acl_output" + ac_prog= + ;; + "") + # If it fails, then pretend we aren't using GCC. + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac + fi + if test -n "$ac_prog"; then + # Search for $ac_prog in $PATH. + acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$acl_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + ]) + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + dnl Determine whether the user wants rpath handling at all. + AC_ARG_ENABLE([rpath], + [ --disable-rpath do not hardcode runtime library paths], + :, enable_rpath=yes) +]) + +dnl AC_LIB_FROMPACKAGE(name, package) +dnl declares that libname comes from the given package. The configure file +dnl will then not have a --with-libname-prefix option but a +dnl --with-package-prefix option. Several libraries can come from the same +dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar +dnl macro call that searches for libname. +AC_DEFUN([AC_LIB_FROMPACKAGE], +[ + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_frompackage_]NAME, [$2]) + popdef([NAME]) + pushdef([PACK],[$2]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_libsinpackage_]PACKUP, + m4_ifdef([acl_libsinpackage_]PACKUP, [m4_defn([acl_libsinpackage_]PACKUP)[, ]],)[lib$1]) + popdef([PACKUP]) + popdef([PACK]) +]) + +dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. +dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found +dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS_BODY], +[ + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_ARG_WITH(PACK[-prefix], +[[ --with-]]PACK[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib + --without-]]PACK[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && test ! -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi +]) + dnl Search the library and its dependencies in $additional_libdir and + dnl $LDFLAGS. Using breadth-first-seach. + LIB[]NAME= + LTLIB[]NAME= + INC[]NAME= + LIB[]NAME[]_PREFIX= + dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been + dnl computed. So it has to be reset here. + HAVE_LIB[]NAME= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='$1 $2' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + dnl See if it was already located by an earlier AC_LIB_LINKFLAGS + dnl or AC_LIB_HAVE_LINKFLAGS call. + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" + else + dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined + dnl that this library doesn't exist. So just drop it. + : + fi + else + dnl Search the library lib$name in $additional_libdir and $LDFLAGS + dnl and the already constructed $LIBNAME/$LTLIBNAME. + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + dnl The same code as in the loop below: + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + dnl Found the library. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + dnl Linking with a shared library. We attempt to hardcode its + dnl directory into the executable's runpath, unless it's the + dnl standard /usr/lib. + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + dnl No hardcoding is needed. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + dnl The hardcoding into $LIBNAME is system dependent. + if test "$acl_hardcode_direct" = yes; then + dnl Using DIR/libNAME.so during linking hardcodes DIR into the + dnl resulting binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + dnl Rely on "-L$found_dir". + dnl But don't add it if it's already contained in the LDFLAGS + dnl or the already constructed $LIBNAME + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH + dnl here, because this doesn't fit in flags passed to the + dnl compiler. So give up. No hardcoding. This affects only + dnl very old systems. + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + dnl Linking with a static library. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" + else + dnl We shouldn't come here, but anyway it's good to have a + dnl fallback. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" + fi + fi + dnl Assume the include files are nearby. + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + dnl Potentially add $additional_includedir to $INCNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's /usr/local/include and we are using GCC on Linux, + dnl 3. if it's already present in $CPPFLAGS or the already + dnl constructed $INCNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INC[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $INCNAME. + INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + dnl Look for dependencies. + if test -n "$found_la"; then + dnl Read the .la file. It defines the variables + dnl dlname, library_names, old_library, dependency_libs, current, + dnl age, revision, installed, dlopen, dlpreopen, libdir. + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + dnl We use only dependency_libs. + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's /usr/local/lib and we are using GCC on Linux, + dnl 3. if it's already present in $LDFLAGS or the already + dnl constructed $LIBNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LIBNAME. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LTLIBNAME. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + dnl Handle this in the next round. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + dnl Handle this in the next round. Throw away the .la's + dnl directory; it is already contained in a preceding -L + dnl option. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + dnl Most likely an immediate library name. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" + ;; + esac + done + fi + else + dnl Didn't find the library; assume it is in the system directories + dnl known to the linker and runtime loader. (All the system + dnl directories known to the linker should also be known to the + dnl runtime loader, otherwise the system is severely misconfigured.) + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user must + dnl pass all path elements in one option. We can arrange that for a + dnl single library, but not when more than one $LIBNAMEs are used. + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + else + dnl The -rpath options are cumulative. + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + dnl When using libtool, the option that works for both libraries and + dnl executables is -R. The -R options are cumulative. + for found_dir in $ltrpathdirs; do + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" + done + fi + popdef([PACKLIBS]) + popdef([PACKUP]) + popdef([PACK]) + popdef([NAME]) +]) + +dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, +dnl unless already present in VAR. +dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes +dnl contains two or three consecutive elements that belong together. +AC_DEFUN([AC_LIB_APPENDTOVAR], +[ + for element in [$2]; do + haveit= + for x in $[$1]; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + [$1]="${[$1]}${[$1]:+ }$element" + fi + done +]) + +dnl For those cases where a variable contains several -L and -l options +dnl referring to unknown libraries and directories, this macro determines the +dnl necessary additional linker options for the runtime path. +dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) +dnl sets LDADDVAR to linker options needed together with LIBSVALUE. +dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, +dnl otherwise linking without libtool is assumed. +AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], +[ + AC_REQUIRE([AC_LIB_RPATH]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + $1= + if test "$enable_rpath" != no; then + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode directories into the resulting + dnl binary. + rpathdirs= + next= + for opt in $2; do + if test -n "$next"; then + dir="$next" + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= + else + case $opt in + -L) next=yes ;; + -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= ;; + *) next= ;; + esac + fi + done + if test "X$rpathdirs" != "X"; then + if test -n ""$3""; then + dnl libtool is used for linking. Use -R options. + for dir in $rpathdirs; do + $1="${$1}${$1:+ }-R$dir" + done + else + dnl The linker is used for linking directly. + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user + dnl must pass all path elements in one option. + alldirs= + for dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="$flag" + else + dnl The -rpath options are cumulative. + for dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="${$1}${$1:+ }$flag" + done + fi + fi + fi + fi + fi + AC_SUBST([$1]) +]) diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4 new file mode 100644 index 0000000..8adb17b --- /dev/null +++ b/m4/lib-prefix.m4 @@ -0,0 +1,249 @@ +# lib-prefix.m4 serial 14 +dnl Copyright (C) 2001-2005, 2008-2019 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed +dnl to access previously installed libraries. The basic assumption is that +dnl a user will want packages to use other packages he previously installed +dnl with the same --prefix option. +dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate +dnl libraries, but is otherwise very convenient. +AC_DEFUN([AC_LIB_PREFIX], +[ + AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_ARG_WITH([lib-prefix], +[[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib + --without-lib-prefix don't search for libraries in includedir and libdir]], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi +]) + if test $use_additional = yes; then + dnl Potentially add $additional_includedir to $CPPFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's already present in $CPPFLAGS, + dnl 3. if it's /usr/local/include and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + for x in $CPPFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $CPPFLAGS. + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" + fi + fi + fi + fi + dnl Potentially add $additional_libdir to $LDFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's already present in $LDFLAGS, + dnl 3. if it's /usr/local/lib and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + for x in $LDFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LDFLAGS. + LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" + fi + fi + fi + fi + fi +]) + +dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, +dnl acl_final_exec_prefix, containing the values to which $prefix and +dnl $exec_prefix will expand at the end of the configure script. +AC_DEFUN([AC_LIB_PREPARE_PREFIX], +[ + dnl Unfortunately, prefix and exec_prefix get only finally determined + dnl at the end of configure. + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the +dnl variables prefix and exec_prefix bound to the values they will have +dnl at the end of the configure script. +AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], +[ + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + $1 + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_PREPARE_MULTILIB creates +dnl - a variable acl_libdirstem, containing the basename of the libdir, either +dnl "lib" or "lib64" or "lib/64", +dnl - a variable acl_libdirstem2, as a secondary possible value for +dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or +dnl "lib/amd64". +AC_DEFUN([AC_LIB_PREPARE_MULTILIB], +[ + dnl There is no formal standard regarding lib and lib64. + dnl On glibc systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine + dnl the compiler's default mode by looking at the compiler's library search + dnl path. If at least one of its elements ends in /lib64 or points to a + dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI. + dnl Otherwise we use the default, namely "lib". + dnl On Solaris systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or + dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib. + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([gl_HOST_CPU_C_ABI_32BIT]) + + case "$host_os" in + solaris*) + AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit], + [AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#ifdef _LP64 + int ok; + #else + error fail + #endif + ]])], + [gl_cv_solaris_64bit=yes], + [gl_cv_solaris_64bit=no]) + ]);; + esac + + dnl Allow the user to override the result by setting acl_cv_libdirstems. + AC_CACHE_CHECK([for the common suffixes of directories in the library search path], + [acl_cv_libdirstems], + [acl_libdirstem=lib + acl_libdirstem2= + case "$host_os" in + solaris*) + dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment + dnl . + dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link." + dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the + dnl symlink is missing, so we set acl_libdirstem2 too. + if test $gl_cv_solaris_64bit = yes; then + acl_libdirstem=lib/64 + case "$host_cpu" in + sparc*) acl_libdirstem2=lib/sparcv9 ;; + i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; + esac + fi + ;; + *) + dnl If $CC generates code for a 32-bit ABI, the libraries are + dnl surely under $prefix/lib, not $prefix/lib64. + if test "$HOST_CPU_C_ABI_32BIT" != yes; then + dnl The result is a property of the system. However, non-system + dnl compilers sometimes have odd library search paths. Therefore + dnl prefer asking /usr/bin/gcc, if available, rather than $CC. + searchpath=`(if test -f /usr/bin/gcc \ + && LC_ALL=C /usr/bin/gcc -print-search-dirs >/dev/null 2>/dev/null; then \ + LC_ALL=C /usr/bin/gcc -print-search-dirs; \ + else \ + LC_ALL=C $CC -print-search-dirs; \ + fi) 2>/dev/null \ + | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + */../ | */.. ) + # Better ignore directories of this form. They are misleading. + ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + fi + ;; + esac + test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" + acl_cv_libdirstems="$acl_libdirstem,$acl_libdirstem2" + ]) + # Decompose acl_cv_libdirstems into acl_libdirstem and acl_libdirstem2. + acl_libdirstem=`echo "$acl_cv_libdirstems" | sed -e 's/,.*//'` + acl_libdirstem2=`echo "$acl_cv_libdirstems" | sed -e '/,/s/.*,//'` +]) diff --git a/man/Makefile.am b/man/Makefile.am new file mode 100644 index 0000000..e055600 --- /dev/null +++ b/man/Makefile.am @@ -0,0 +1,37 @@ +## Copyright (C) 2008-2020 Dirk-Jan C. Binnema +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +dist_man_MANS = \ + mu-add.1 \ + mu-bookmarks.5 \ + mu-cfind.1 \ + mu-easy.1 \ + mu-extract.1 \ + mu-find.1 \ + mu-help.1 \ + mu-index.1 \ + mu-info.1 \ + mu-init.1 \ + mu-mkdir.1 \ + mu-query.7 \ + mu-remove.1 \ + mu-server.1 \ + mu-script.1 \ + mu-verify.1 \ + mu-view.1 \ + mu.1 diff --git a/man/mu-add.1 b/man/mu-add.1 new file mode 100644 index 0000000..fb4e081 --- /dev/null +++ b/man/mu-add.1 @@ -0,0 +1,48 @@ +.TH MU ADD 1 "July 2012" "User Manuals" + +.SH NAME + +mu add\- add one or more messages to the database + +.SH SYNOPSIS + +.B mu add [] + +.SH DESCRIPTION + +\fBmu add\fR is the command to add specific message files to the +database. Each file must be specified with an absolute path. + +.SH OPTIONS + +\fBmu add\fR does not have its own options, but the general options for +determining the location of the database (\fI--muhome\fR) are available. See +\fBmu-index\fR(1) for more information. + +.SH RETURN VALUE + +\fBmu add\fR returns 0 upon success; in general, the following error codes are +returned: + +.nf +| code | meaning | +|------+-----------------------------------| +| 0 | ok | +| 1 | general error | +| 5 | some database update error | +.fi + +.SH BUGS + +Please report bugs if you find them: +.BR https://github.com/djcb/mu/issues + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR mu (1), +.BR mu-index (1), +.BR mu-remove (1) diff --git a/man/mu-bookmarks.5 b/man/mu-bookmarks.5 new file mode 100644 index 0000000..f68a335 --- /dev/null +++ b/man/mu-bookmarks.5 @@ -0,0 +1,36 @@ +.TH MU-BOOKMARKS 5 "July 2019" "User Manuals" + +.SH NAME + +bookmarks \- file with bookmarks (shortcuts) for mu search expressions + +.SH DESCRIPTION + +Bookmarks are named shortcuts for search queries. They allow using a convenient +name for often-used queries. The bookmarks are also visible as shortcuts in the +mu experimental user interfaces, \fImug\fR and \fImug2\fR. + +The bookmarks file is read from \fI/bookmarks\fR. On Unix this would +typically be w be \fI~/.config/mu/bookmarks\fR, but this can be influenced using +the \fB\-\-muhome\fR parameter for \fBmu-find\fR(1) and \fBmug\fR(1). + +The bookmarks file is a typical key=value \fB.ini\fR-file, which is best shown +by means of an example: + +.nf + [mu] + inbox=maildir:/inbox # inbox + oldhat=maildir:/archive subject:hat # archived with subject containing 'hat' +.fi + +The \fB[mu]\fR group header is required. + +For practical uses of bookmarks, see \fBmu-find\fR(1). + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR mu (1), mu-find (1) diff --git a/man/mu-cfind.1 b/man/mu-cfind.1 new file mode 100644 index 0000000..a3618e1 --- /dev/null +++ b/man/mu-cfind.1 @@ -0,0 +1,133 @@ +.TH MU CFIND 1 "April 2019" "User Manuals" + +.SH NAME + +\fBmu cfind\fR is the \fBmu\fR command to find contacts in the \fBmu\fR +database and export them for use in other programs. + +.SH SYNOPSIS + +.B mu cfind [options] [] + +.SH DESCRIPTION + +\fBmu cfind\fR is the \fBmu\fR command for finding \fIcontacts\fR (name and +e-mail address of people who were either an e-mail's sender or +receiver). There are different output formats available, for importing the +contacts into other programs. + +.SH SEARCHING CONTACTS + +When you index your messages (see \fBmu index\fR), \fBmu\fR creates a list of +unique e-mail addresses found and the accompanying name, and caches this +list. In case the same e-mail address is used with different names, the most +recent non-empty name is used. + +\fBmu cfind\fR starts a search for contacts that match a \fIregular +expression\fR. For example: + +.nf + $ mu cfind '@gmail\.com' +.fi + +would find all contacts with a gmail-address, while + +.nf + $ mu cfind Mary +.fi + +lists all contacts with Mary in either name or e-mail address. + +If you do not specify a search expression, \fBmu cfind\fR returns the full list +of contacts. Note, \fBmu cfind\fR uses a cache with the e-mail information, +which is populated during the indexing process. + +The regular expressions are Perl-compatible (as per the PCRE-library used by +GRegex). + +.SH OPTIONS + +.TP +\fB\-\-format\fR=\fIplain|mutt-alias|mutt-ab|wl|org-contact|bbdb|csv\fR +sets the output format to the given value. The following are available: + +.nf +| --format= | description | +|-------------+-----------------------------------| +| plain | default, simple list | +| mutt-alias | mutt alias-format | +| mutt-ab | mutt external address book format | +| wl | wanderlust addressbook format | +| org-contact | org-mode org-contact format | +| bbdb | BBDB format | +| csv | comma-separated values (*) | +.fi + + +(*) CSV is not fully standardized, but \fBmu cfind\fR follows some common +practices: any double-quote is replaced by a double-double quote (thus, "hello" +become ""hello"", and fields with commas are put in double-quotes. Normally, +this should only apply to name fields. + +.TP +\fB\-\-personal\fR only show addresses seen in messages where one of 'my' e-mail +addresses was seen in one of the address fields; this is to exclude addresses +only seen in mailing-list messages. See the \fB\-\-my-address\fR parameter in +\fBmu index\fR. + +.TP +\fB\-\-after=\fR\fI\fR only show addresses last seen after +\fI\fR. \fI\fR is a UNIX \fBtime_t\fR value, the number of +seconds since 1970-01-01 (in UTC). + +From the command line, you can use the \fBdate\fR command to get this value. For +example, only consider addresses last seen after 2009-06-01, you could specify +.nf + --after=`date +%s --date='2009-06-01'` +.fi + +.SH RETURN VALUE + +\fBmu cfind\fR returns 0 upon successful completion -- that is, at least one +contact was found. Anything else leads to a non-zero return value: + +.nf +| code | meaning | +|------+--------------------------------| +| 0 | ok | +| 1 | general error | +| 2 | no matches (for 'mu cfind') | +.fi + +.SH INTEGRATION WITH MUTT + +You can use \fBmu cfind\fR as an external address book server for \fBmutt\fR. +For this to work, add the following to your \fImuttrc\fR: + +.nf +set query_command = "mu cfind --format=mutt-ab '%s'" +.fi + +Now, in mutt, you can search for e-mail addresses using the \fBquery\fR-command, +which is (by default) accessible by pressing \fBQ\fR. + +.SH ENCODING + +\fBmu cfind\fR output is encoded according to the current locale except for +\fI--format=bbdb\fR. This is hard-coded to UTF-8, and as such specified in the +output-file, so emacs/bbdb can handle things correctly, without guessing. + +.SH BUGS + +Please report bugs if you find them at \fBhttps://github.com/djcb/mu/issues\fR. + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR mu (1), +.BR mu-index (1), +.BR mu-find (1), +.BR pcrepattern(3) diff --git a/man/mu-easy.1 b/man/mu-easy.1 new file mode 100644 index 0000000..38953be --- /dev/null +++ b/man/mu-easy.1 @@ -0,0 +1,313 @@ +.TH MU-EASY 1 "February 2020" "User Manuals" + +.SH NAME + +mu easy \- a quick introduction to mu + +.SH DESCRIPTION + +\fBmu\fR is a set of tools for dealing with e-mail messages in Maildirs. There +are many options, which are all described in the man pages for the various +sub-commands. This man pages jumps over all of the details and gives examples of +some common use cases. If the use cases described here do not precisely do what +you want, please check the more extensive information in the man page about the +sub-command you are using -- for example, the \fBmu-index\fR(1) or +\fBmu-find\fR(1) man pages. + +\fBNOTE\fR: the \fBindex\fR command (and therefore, the ones that depend on +that, such as \fBfind\fR), require that you store your mail in the +Maildir-format. If you don't do so, you can still use the other commands, but +you won't be able to index/search your mail. + +By default, \fBmu\fR uses colorized output when it thinks your terminal is +capable of doing so. If you don't like color, you can use the \fB--nocolor\fR +command-line option, or set either the \fBMU_NOCOLOR\fR or the \fBNO_COLOR\fR +environment variable to non-empty. + +.SH SETTING THINGS UP + +The first time you run the mu commands, you need to initialize it. This is done +with the \fBinit\fR command. + +.nf + \fB$ mu init\fR +.fi + +This uses the defaults (see \fBmu-init(1)\fR for details on how to change that). + + +.SH INDEXING YOUR E-MAIL + +Before you can search e-mails, you'll first need to index them: + +.nf + \fB$ mu index\fR +.fi + +The process can take a few minutes, depending on the amount of mail +you have, the speed of your computer, hard drive etc. Usually, +indexing should be able to reach a speed of a few hundred messages per +second. + +\fBmu index\fR guesses the top-level Maildir to do its job; if it +guesses wrongly, you can use the \fI--maildir\fR option to specify the +top-level directory that should be processed. See the \fBmu-index\fR(1) +man page for more details. + +Normally, \fBmu index\fR visits all the directories under the +top-level Maildir; however, you can exclude certain directories (say, +the 'trash' or 'spam' folders) by creating a file called +\fI.noindex\fR in the directory. When \fBmu\fR sees such a file, it +will exclude this directory and its sub-directories from indexing. +Also see \fB.noupdate\fR in the \fBmu-index\fR(1) manpage. + +.SH SEARCHING YOUR E-MAIL + +After you have indexed your mail, you can start searching it. By +default, the search results are printed on standard output. +Alternatively, the output can take the form of Maildir with symbolic +links to the found messages. This enables integration with e-mail +clients; see the \fBmu-find\fR(1) man page for details, the syntax of the +search parameters and so on. Here, we just give some examples for +common cases. + +First, let's search for all messages sent to Julius (Caesar) regarding +fruit: + +.nf +\fB$ mu find t:julius fruit\fR +.fi + +This should return something like: + +.nf + 2008-07-31T21:57:25 EEST John Milton Fere libenter homines id quod volunt credunt +.fi + +This means there is a message to 'julius' with 'fruit' somewhere in +the message. In this case, it's a message from John Milton. Note that +the date format depends on your the language/locale you are using. + +How do we know that the message was sent to Julius Caesar? Well, it's +not visible from the results above, because the default fields that +are shown are date/sender/subject. However, we can change this using +the \fI--fields\fR parameter (see the \fBmu-find\fR(1) man page for the +details): + +.nf + \fB$ mu find --fields="t s" t:julius fruit\fR +.fi + +In other words, display the 'To:'-field (t) and the subject (s). This should +return something like: +.nf + Julius Caesar Fere libenter homines id quod volunt credunt +.fi + +This is the same message found before, only with some different fields +displayed. + +By default, \fBmu\fR uses the logical AND for the search parameters -- that +is, it displays messages that match all the parameters. However, we can use +logical OR as well: + +.nf + \fB$ mu find t:julius OR f:socrates\fR +.fi + +In other words, display messages that are either sent to Julius Caesar +\fBor\fR are from Socrates. This could return something like: + +.nf + 2008-07-31T21:57:25 EEST Socrates cool stuff + 2008-07-31T21:57:25 EEST John Milton Fere libenter homines id quod volunt credunt +.fi + +What if we want to see some of the body of the message? You can get +a 'summary' of the first lines of the message using the \fI--summary-len\fR +option, which will 'summarize' the first \fIn\fR lines of the message: + +.nf + \fB$ mu find --summary-len=3 napoleon m:/archive\fR +.fi + +.nf + 1970-01-01T02:00:00 EET Napoleon Bonaparte rock on dude + Summary: Le 24 février 1815, la vigie de Notre-Dame de la Garde signala le + trois-mâts le Pharaon, venant de Smyrne, Trieste et Naples. Comme + d'habitude, un pilote côtier partit aussitôt du port, rasa le château +.fi + +The summary consists of the first n lines of the message with all superfluous +whitespace removed. + +Also note the \fBm:/archive\fR parameter in the query. This means that we only +match messages in a maildir called '/archive'. + +.SH MORE QUERIES + +Let's list a few more queries that may be interesting; please note that +searches for message flags, priority and date ranges are only available in mu +version 0.9 or later. + +Get all important messages which are signed: +.nf + \fB$ mu find flag:signed prio:high \fR +.fi + +Get all messages from Jim without an attachment: +.nf + \fB$ mu find from:jim AND NOT flag:attach\fR +.fi + +Get all messages where Jack is in one of the contact fields: +.nf + \fB$ mu find contact:jack\fR +.fi +This uses the special contact: pseudo-field which matches (\fBfrom\fR, +\fBto\fR, \fBcc\fR and \fBbcc\fR). + +Get all messages in the Sent Items folder about yoghurt: +.nf + \fB$mu find maildir:'/Sent Items' yoghurt\fR +.fi +Note how we need to quote search terms that include spaces. + + +Get all unread messages where the subject mentions Ångström: +.nf + \fB$ mu find subject:Ångström flag:unread\fR +.fi +which is equivalent to: +.nf + \fB$ mu find subject:angstrom flag:unread\fR +.fi +because does mu is case-insensitive and accent-insensitive. + +Get all unread messages between March 2002 and August 2003 about some bird (or +a Swedish rock band): +.nf + \fB$ mu find date:20020301..20030831 nightingale flag:unread\fR +.fi + +Get all messages received today: +.nf + \fB$ mu find date:today..now\fR +.fi + +Get all messages we got in the last two weeks about emacs: +.nf + \fB$ mu find date:2w..now emacs\fR +.fi + +Another powerful feature (since 0.9.6) are wildcard searches, where you can +search for the last \fIn\fR characters in a word. For example, you can search +for: +.nf + \fB$ mu find 'subject:soc*'\fR +.fi +and get mails about soccer, Socrates, society, and so on. Note, it's important +to quote the search query, otherwise the shell will interpret +the '*'. + +You can also search for messages with a certain attachment using their +filename, for example: + +.nf + \fB$ mu find 'file:pic*'\fR +.fi +will get you all messages with an attachment starting with 'pic'. + +If you want to find attachments with a certain MIME-type, you can use the +following: + +Get all messages with PDF attachments: +.nf + \fB$ mu find mime:application/pdf\fR +.fi + +or even: + +Get all messages with image attachments: +.nf + \fB$ mu find 'mime:image/*'\fR +.fi + + +Note that (1) the '*' wildcard can only be used as the rightmost thing in a +search query, and (2) that you need to quote the search term, because +otherwise your shell will interpret the '*' (expanding it to all files in the +current directory -- probably not what you want). + +.SH DISPLAYING MESSAGES + +We might also want to display the complete messages instead of the header +information. This can be done using \fBmu view\fR command. Note that this +command does not use the database; you simply provide it the path to a +message. + +Therefore, if you want to display some message from a search query, you'll +need its path. To get the path (think \fBl\fRocation) for our first example we +can use: + +.nf + \fB$ mu find --fields="l" t:julius fruit\fR +.fi + +And we'll get something like: +.nf + /home/someuser/Maildir/archive/cur/1266188485_0.6850.cthulhu:2, +.fi +We can now display this message: + +.nf + \fB$ mu view /home/someuser/Maildir/archive/cur/1266188485_0.6850.cthulhu:2,\fR + + From: John Milton + To: Julius Caesar + Subject: Fere libenter homines id quod volunt credunt + Date: 2008-07-31T21:57:25 EEST + + OF Mans First Disobedience, and the Fruit + Of that Forbidden Tree, whose mortal taste + Brought Death into the World, and all our woe, + [...] +.fi + +.SH FINDING CONTACTS + +While \fBmu find\fR searches for messages, there is also \fBmu cfind\fR to +find \fIcontacts\fR, that is, names + addresses. Without any search +expression, \fBmu cfind\fR lists all of your contacts. + +.nf + \fB$ mu cfind julius\fR +.fi + +will find all contacts with 'julius' in either name or e-mail address. Note +that \fBmu cfind\fR accepts a \fIregular expression\fR. + +\fBmu cfind\fR also supports a \fI--format=\fR-parameter, which sets the +output to some specific format, so the results can be imported into another +program. For example, to export your contact information to a \fBmutt\fR +address book file, you can use something like: + +.nf + \fB$ mu cfind --format=mutt-alias > ~/mutt-aliases \fR +.fi + +Then, you can use them in \fBmutt\fR if you add something like \fBsource +~/mutt-aliases\fR to your \fImuttrc\fR. + +.SH AUTHOR +Dirk-Jan C. Binnema + +.SH "SEE ALSO" +.BR mu (1), +.BR mu-init (1), +.BR mu-index (1), +.BR mu-find (1), +.BR mu-mfind (1), +.BR mu-mkdir (1), +.BR mu-view (1), +.BR mu-extract (1) diff --git a/man/mu-extract.1 b/man/mu-extract.1 new file mode 100644 index 0000000..35d96ce --- /dev/null +++ b/man/mu-extract.1 @@ -0,0 +1,100 @@ +.TH MU EXTRACT 1 "July 2012" "User Manuals" + +.SH NAME + +\fBmu extract\fR is the \fBmu\fR command to display and save message parts +(attachments), and open them with other tools. + +.SH SYNOPSIS + +.B mu extract [options] + +.B mu extract [options] + +.SH DESCRIPTION + +\fBmu extract\fR is the \fBmu\fR sub-command for extracting MIME-parts (e.g., +attachments) from mail messages. The sub-command works on message files, and +does not require the message to be indexed in the database. + +For attachments, the file name used when saving it is the name of the +attachment in the message. If there is no such name, or when saving +non-attachment MIME-parts, a name is derived from the message-id of the +message. + +If you specify a pattern (a case-insensitive regular expression) as the second +argument, all attachments with filenames matching that pattern will be +extracted. The regular expressions are Perl-compatible (as per the +PCRE-library). + +Without any options, \fBmu extract\fR simply outputs the list of leaf +MIME-parts in the message. Only 'leaf' MIME-parts (including RFC822 +attachments) are considered, \fBmultipart/*\fR etc. are ignored. + +.SH OPTIONS + +.TP +\fB\-a\fR, \fB\-\-save\-attachments\fR +save all MIME-parts that look like attachments. + +.TP +\fB\-\-save\-all\fR +save all non-multipart MIME-parts. + +.TP +\fB\-\-parts\fR= +only consider the following numbered parts +(comma-separated list). The numbers for the parts can be seen from running +\fBmu extract\fR without any options but only the message file. + +.TP +\fB\-\-target\-dir\fR= +save the parts in the target directory rather than +the current working directory. + +.TP +\fB\-\-overwrite\fR +overwrite existing files with the same name; by default overwriting is not +allowed. + +.TP +\fB\-\-play\fR Try to 'play' (open) the attachment with the default +application for the particular file type. On MacOS, this uses the \fBopen\fR +program, on other platforms it uses \fBxdg-open\fR. You can choose a different +program by setting the \fBMU_PLAY_PROGRAM\fR environment variable. + +.SH EXAMPLES + +To display information about all the MIME-parts in a message file: +.nf + $ mu extract msgfile +.fi + +To extract MIME-part 3 and 4 from this message, overwriting existing files +with the same name: +.nf + $ mu extract --parts=3,4 --overwrite msgfile +.fi + +To extract all files ending in '.jpg' (case-insensitive): +.nf + $ mu extract msgfile '.*\.jpg' +.fi + +To extract an mp3-file, and play it in the default mp3-playing application: +.nf + $ mu extract --play msgfile 'whoopsididitagain.mp3' +.fi + +.SH BUGS + +Please report bugs if you find them: +.BR https://github.com/djcb/mu/issues + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR mu (1) diff --git a/man/mu-find.1 b/man/mu-find.1 new file mode 100644 index 0000000..5e46487 --- /dev/null +++ b/man/mu-find.1 @@ -0,0 +1,389 @@ +.TH MU FIND 1 "19 April 2015" "User Manuals" + +.SH NAME + +mu find \- find e-mail messages in the \fBmu\fR database. + +mu mfind \- find e-mail messages in the \fBmu\fR database with mu4e defaults. + +.SH SYNOPSIS + +.B mu find [options] + +.SH DESCRIPTION + +\fBmu find\fR is the \fBmu\fR command for searching e-mail message +that were stored earlier using \fBmu index\fR(1). + +\fBmu mfind\fR is a version of \fBmu find\fR that defaults to +\f--include-related\fR and \fB--skip-dups\fR, just like \fBmu4e\fR does. + +.SH SEARCHING MAIL + +\fBmu find\fR starts a search for messages in the database that match +some search pattern. The search patterns are described in detail in +.BR mu-query (7). +. + +For example: + +.nf + $ mu find subject:snow and date:2017.. +.fi + +would find all messages in 2017 with 'snow' in the subject field, e.g: + +.nf + 2009-03-05 17:57:33 EET Lucia running in the snow + 2009-03-05 18:38:24 EET Marius Re: running in the snow +.fi + +Note, this the default, plain-text output, which is the default, so you don't +have to use \fB--format=plain\fR. For other types of output (such as symlinks, +XML or s-expressions), see the discussion in the \fBOPTIONS\fR-section +below about \fB--format\fR. + +The search pattern is taken as a command-line parameter. If the search +parameter consists of multiple parts (as in the example) they are +treated as if there were a logical \fBand\fR between them. + +For details on the possible queries, see +.BR mu-query (7). + +.SH OPTIONS + +Note, some of the important options are described in the \fBmu\fR(1) man-page +and not here, as they apply to multiple mu-commands. + +The \fBfind\fR-command has various options that influence the way \fBmu\fR +displays the results. If you don't specify anything, the defaults are +\fI\-\-fields="d f s"\fR, \fI\-\-sortfield=date\fR and \fI\-\-reverse\fR. + +.TP +\fB\-f\fR, \fB\-\-fields\fR=\fI\fR +specifies a string that determines which fields are shown in the output. This +string consists of a number of characters (such as 's' for subject or 'f' for +from), which will replace with the actual field in the output. Fields that are +not known will be output as-is, allowing for some simple formatting. + +For example: + +.nf + $ mu find subject:snow --fields "d f s" +.fi + +would list the date, subject and sender of all messages with 'snow' in the +their subject. + +The table of replacement characters is superset of the list mentions for +search parameters; the complete list: + +.nf + t \fBt\fRo: recipient + c \fBc\fRc: (carbon-copy) recipient + h Bcc: (blind carbon-copy, \fBh\fRidden) recipient + d Sent \fBd\fRate of the message + f Message sender (\fBf\fRrom:) + g Message flags (fla\fBg\fRs) + l Full path to the message (\fBl\fRocation) + p Message \fBp\fRriority (high, normal, low) + s Message \fBs\fRubject + i Message-\fBi\fRd + m \fBm\fRaildir + v Mailing-list Id +.fi + + +The message flags are described in \fBmu-query\fR(7). As an example, a +message which is 'seen', has an attachment and is signed would +have 'asz' as its corresponding output string, while an encrypted new +message would have 'nx'. + +.TP +\fB\-s\fR, \fB\-\-sortfield\fR \fR=\fI\fR and \fB\-z\fR, +\fB\-\-reverse\fR specifies the field to sort the search results by, and the +direction (i.e., 'reverse' means that the sort should be reverted - Z-A). The +following fields are supported: + +.nf + cc,c Cc (carbon-copy) recipient(s) + bcc,h Bcc (blind-carbon-copy) recipient(s) + date,d Message sent date + from,f Message sender + maildir,m Maildir + msgid,i Message id + prio,p Nessage priority + subject,s Message subject + to,t To:-recipient(s) + list,v Mailing-list id +.fi + +Thus, for example, to sort messages by date, you could specify: + +.nf + $ mu find fahrrad --fields "d f s" --sortfield=date --reverse +.fi + +Note, if you specify a sortfield, by default, messages are sorted in reverse +(descending) order (e.g., from lowest to highest). This is usually a good +choice, but for dates it may be more useful to sort in the opposite direction. + +.TP +\fB\-n\fR, \fB\-\-maxnum=\fR +If > 0, display maximally that number of entries. If not specified, all matching entries are displayed. + +.TP +\fB\-\-summary-len=\fR +If > 0, use that number of lines of the message to provide a summary. + +.TP +\fB\-\-format\fR=\fIplain|links|xquery|xml|sexp\fR +output results in the specified format. + +The default is \fBplain\fR, i.e normal output with one line per message. + +\fBlinks\fR outputs the results as a maildir with symbolic links to the found +messages. This enables easy integration with mail-clients (see below for more +information). + +\fBxml\fR formats the search results as XML. + +\fBsexp\fR formats the search results as an s-expression as used in Lisp +programming environments. + +\fBxquery\fR shows the Xapian query corresponding to your search terms. This +is meant for for debugging purposes. + +.TP +\fB\-\-linksdir\fR \fR=\fI\fR and \fB\-c\fR, \fB\-\-clearlinks\fR +output the results as a maildir with symbolic links to the found +messages. This enables easy integration with mail-clients (see below +for more information). \fBmu\fR will create the maildir if it does not +exist yet. + +If you specify \fB\-\-clearlinks\fR, all existing symlinks will be +cleared from the target directories; this allows for re-use of the +same maildir. However, this option will delete any symlink it finds, +so be careful. + +.nf + $ mu find grolsch --linksdir=~/Maildir/search --clearlinks +.fi + +will store links to found messages in \fI~/Maildir/search\fR. If the directory +does not exist yet, it will be created. + +Note: when \fBmu\fR creates a Maildir for these links, it automatically +inserts a \fI.noindex\fR file, to exclude the directory from \fBmu +index\fR. + +.TP +\fB\-\-after=\fR\fI\fR only show messages whose message files were +last modified (\fBmtime\fR) after \fI\fR. \fI\fR is a +UNIX \fBtime_t\fR value, the number of seconds since 1970-01-01 (in UTC). + +From the command line, you can use the \fBdate\fR command to get this +value. For example, only consider messages modified (or created) in the last 5 +minutes, you could specify +.nf + --after=`date +%s --date='5 min ago'` +.fi +This is assuming the GNU \fBdate\fR command. + + +.TP +\fB\-\-exec\fR=\fI\fR +the \fB\-\-exec\fR command causes the \fIcommand\fR to be executed on each +matched message; for example, to see the raw text of all messages +matching 'milkshake', you could use: +.nf + $ mu find milkshake --exec='less' +.fi +which is roughly equivalent to: +.nf + $ mu find milkshake --fields="l" | xargs less +.fi + + +.TP +\fB\-b\fR, \fB\-\-bookmark\fR=\fI\fR +use a bookmarked search query. Using this option, a query from your bookmark +file will be prepended to other search queries. See \fBmu-bookmarks\fR(1) for the +details of the bookmarks file. + + +.TP +\fB\-\-skip\-dups\fR,\fB-u\fR whenever there are multiple messages with the +same name, only show the first one. This is useful if you have copies of the +same message, which is a common occurrence when using e.g. Gmail together with +\fBofflineimap\fR. + +.TP +\fB\-\-include\-related\fR,\fB-r\fR also include messages being referred to by +the matched messages -- i.e.. include messages that are part of the same +message thread as some matched messages. This is useful if you want +Gmail-style 'conversations'. Note, finding these related messages make +searches slower. + +.TP +\fB\-t\fR, \fB\-\-threads\fR show messages in a 'threaded' format -- that is, +with indentation and arrows showing the conversation threads in the list of +matching messages. + +Messages in the threaded list are indented based on the depth in the +discussion, and are prefix with a kind of arrow with thread-related +information about the message, as in the following table: + +.nf +| | normal | orphan | duplicate | +|-------------+--------+--------+-----------| +| first child | `-> | `*> | `=> | +| other | |-> | |*> | |=> | +.fi + +Here, an 'orphan' is a message without a parent message (in the list of +matches), and a duplicate is a message whose message-id was already seen +before; not this may not really be the same message, if the message-id was +copied. + +The algorithm used for determining the threads is based on Jamie Zawinksi's +description: +.BR http://www.jwz.org/doc/threading.html + + +.SS Integrating mu find with mail clients + +.TP + +\fBmutt\fR + +For \fBmutt\fR you can use the following in your \fImuttrc\fR; pressing the F8 +key will start a search, and F9 will take you to the results. + +.nf +# mutt macros for mu +macro index "mu find --clearlinks --format=links --linksdir=~/Maildir/search " \\ + "mu find" +macro index "~/Maildir/search" \\ + "mu find results" +.fi + + +.TP + +\fBWanderlust\fR + +\fBSam B\fR suggested the following on the \fBmu\fR-mailing list. First add +the following to your Wanderlust configuration file: + +.nf +(require 'elmo-search) +(elmo-search-register-engine + 'mu 'local-file + :prog "/usr/local/bin/mu" ;; or wherever you've installed it + :args '("find" pattern "--fields" "l") :charset 'utf-8) + +(setq elmo-search-default-engine 'mu) +;; for when you type "g" in folder or summary. +(setq wl-default-spec "[") +.fi + +Now, you can search using the \fBg\fR key binding; you can also create +permanent virtual folders when the messages matching some expression by adding +something like the following to your \fIfolders\fR file. + +.nf +VFolders { + [date:today..now]!mu "Today" + + [size:1m..100m]!mu "Big" + + [flag:unread]!mu "Unread" +} +.fi + +After restarting Wanderlust, the virtual folders should appear. + + +\fBWanderlust (old)\fR + +Another way to integrate \fBmu\fR and \fBwanderlust\fR is shown below; the +aforementioned method is recommended, but if that does not work for some +reason, the below can be an alternative. + +.nf +(defvar mu-wl-mu-program "/usr/local/bin/mu") +(defvar mu-wl-search-folder "search") + +(defun mu-wl-search () + "search for messages with `mu', and jump to the results" + (let* ((muexpr (read-string "Find messages matching: ")) + (sfldr (concat elmo-maildir-folder-path "/" + mu-wl-search-folder)) + (cmdline (concat mu-wl-mu-program " find " + "--clearlinks --format=links --linksdir='" sfldr "' " + muexpr)) + (rv (shell-command cmdline))) + (cond + ((= rv 0) (message "Query succeeded")) + ((= rv 2) (message "No matches found")) + (t (message "Error running query"))) + (= rv 0))) + +(defun mu-wl-search-and-goto () + "search and jump to the folder with the results" + (interactive) + (when (mu-wl-search) + (wl-summary-goto-folder-subr + (concat "." mu-wl-search-folder) + 'force-update nil nil t) + (wl-summary-sort-by-date))) + +;; querying both in summary and folder +(define-key wl-summary-mode-map (kbd "Q") ;; => query + '(lambda()(interactive)(mu-wl-search-and-goto))) +(define-key wl-folder-mode-map (kbd "Q") ;; => query + '(lambda()(interactive)(mu-wl-search-and-goto))) + +.fi + + +.SH RETURN VALUE + +\fBmu find\fR returns 0 upon successful completion; if the search was +performed, there needs to be a least one match. Anything else leads to a +non-zero return value, for example: + +.nf +| code | meaning | +|------+--------------------------------| +| 0 | ok | +| 1 | general error | +| 2 | no matches (for 'mu find') | +| 4 | database is corrupted | +.fi + + +.SH ENCODING + +\fBmu find\fR output is encoded according the locale for \fI--format=plain\fR +(the default), and UTF-8 for all other formats (\fIsexp\fR, +\fIxml\fR). + + +.SH BUGS + +Please report bugs if you find them: +.BR https://github.com/djcb/mu/issues +If you have specific messages which are not matched correctly, please attach +them (appropriately censored if needed). + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR mu (1), +.BR mu-index (1), +.BR mu-query (7) diff --git a/man/mu-help.1 b/man/mu-help.1 new file mode 100644 index 0000000..80ba090 --- /dev/null +++ b/man/mu-help.1 @@ -0,0 +1,34 @@ +.TH MU HELP 1 "July 2012" "User Manuals" + +.SH NAME + +\fBmu help\fR is a \fBmu\fR command that gives help information about mu +commands. + +.SH SYNOPSIS + +.B mu help + +.SH DESCRIPTION + +\fBmu help\fR provides help information about mu commands. + +.SH BUGS + +Please report bugs if you find them: +.BR https://github.com/djcb/mu/issues + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR mu-index (1), +.BR mu-find (1), +.BR mu-cfind (1), +.BR mu-mkdir (1), +.BR mu-view (1), +.BR mu-extract (1), +.BR mu-easy (1), +.BR mu-bookmarks (5) diff --git a/man/mu-index.1 b/man/mu-index.1 new file mode 100644 index 0000000..c5b6008 --- /dev/null +++ b/man/mu-index.1 @@ -0,0 +1,188 @@ +.TH MU-INDEX 1 "February 2020" "User Manuals" + +.SH NAME + +mu index \- index e-mail messages stored in Maildirs + +.SH SYNOPSIS + +.B mu index [options] + +.SH DESCRIPTION + +\fBmu index\fR is the \fBmu\fR command for scanning the contents of Maildir +directories and storing the results in a Xapian database. The data can then be +queried using +.BR mu-find (1)\. + +Note that before the first time you run \fBmu index\fR, you must run \fBmu +init\fR to initialize the database. + +\fBindex\fR understands Maildirs as defined by Daniel Bernstein for +\fBqmail\fR(7). In addition, it understands recursive Maildirs (Maildirs +within Maildirs), Maildir++. It can also deal with VFAT-based Maildirs +which use '!' as the separators instead of ':'. + +E-mail messages which are not stored in something resembling a maildir +leaf-directory (\fIcur\fR and \fInew\fR) are ignored, as are the cache +directories for \fInotmuch\fR and \fIgnus\fR, and any dot-directory. + +The maildir must be on a single file-system; symlinks are not followed. + +If there is a file called \fI.noindex\fR in a directory, the contents of that +directory and all of its subdirectories will be ignored. This can be useful to +exclude certain directories from the indexing process, for example directories +with spam-messages. + +If there is a file called \fI.noupdate\fR in a directory, the contents of that +directory and all of its subdirectories will be ignored, unless we do a full +rebuild (with \fBmu init\fR). This can be useful to speed up things you have +some maildirs that never change. Note that you can still search for these +messages, this only affects updating the database. + +There also the \fB--lazy-check\fR which can greatly speed up indexing; +see below for details. + +The first run of \fBmu index\fR may take a few minutes if you have a +lot of mail (tens of thousands of messages). Fortunately, such a full +scan needs to be done only once; after that it suffices to index the +changes, which goes much faster. See the 'Note on performance +(i,ii,iii)' below for more information. + +The optional 'phase two' of the indexing-process is the removal of messages +from the database for which there is no longer a corresponding file in the +Maildir. If you do not want this, you can use \fB\-n\fR, \fB\-\-nocleanup\fR. + +When \fBmu index\fR catches one of the signals \fBSIGINT\fR, \fBSIGHUP\fR or +\fBSIGTERM\fR (e.g., when you press Ctrl-C during the indexing process), it +tries to shutdown gracefully; it tries to save and commit data, and close the +database etc. If it receives another signal (e.g., when pressing Ctrl-C once +more), \fBmu index\fR will terminate immediately. + +.SH OPTIONS + +Note, some of the general options are described in the \fBmu(1)\fR man-page +and not here, as they apply to multiple mu commands. + +.TP +\fB\-\-lazy-check\fR +in lazy-check mode, \fBmu\fR does not consider messages for which the +time-stamp (ctime) of the directory they reside in has not changed +since the previous indexing run. This is much faster than the non-lazy +check, but won't update messages that have change (rather than having +been added or removed), since merely editing a message does not update +the directory time-stamp. Of course, you can run \fBmu-index\fR +occasionally without \fB\-\-lazy-check\fR, to pick up such messages. + +.TP +\fB\-\-nocleanup\fR +disables the database cleanup that \fBmu\fR does by default after indexing. + +.SS A note on performance (i) +As a non-scientific benchmark, a simple test on the author's machine (a +Thinkpad X61s laptop using Linux 2.6.35 and an ext3 file system) with no +existing database, and a maildir with 27273 messages: + +.nf + $ sudo sh -c 'sync && echo 3 > /proc/sys/vm/drop_caches' + $ time mu index --quiet + 66,65s user 6,05s system 27% cpu 4:24,20 total +.fi +(about 103 messages per second) + +A second run, which is the more typical use case when there is a database +already, goes much faster: + +.nf + $ sudo sh -c 'sync && echo 3 > /proc/sys/vm/drop_caches' + $ time mu index --quiet + 0,48s user 0,76s system 10% cpu 11,796 total +.fi +(more than 56818 messages per second) + +Note that each test flushes the caches first; a more common use case might +be to run \fBmu index\fR when new mail has arrived; the cache may stay +quite 'warm' in that case: + +.nf + $ time mu index --quiet + 0,33s user 0,40s system 80% cpu 0,905 total +.fi +which is more than 30000 messages per second. + + +.SS A note on performance (ii) +As per June 2012, we did the same non-scientific benchmark, this time with an +Intel i5-2500 CPU @ 3.30GHz, an ext4 file system and a maildir with 22589 +messages. We start without an existing database. + +.nf + $ sudo sh -c 'sync && echo 3 > /proc/sys/vm/drop_caches' + $ time mu index --quiet + 27,79s user 2,17s system 48% cpu 1:01,47 total +.fi +(about 813 messages per second) + +A second run, which is the more typical use case when there is a database +already, goes much faster: + +.nf + $ sudo sh -c 'sync && echo 3 > /proc/sys/vm/drop_caches' + $ time mu index --quiet + 0,13s user 0,30s system 19% cpu 2,162 total +.fi +(more than 173000 messages per second) + + +.SS A note on performance (iii) +As per July 2016, we did the same non-scientific benchmark, again with +the Intel i5-2500 CPU @ 3.30GHz, an ext4 file system. This time, the +maildir contains 72525 messages. + +.nf + $ sudo sh -c 'sync && echo 3 > /proc/sys/vm/drop_caches' + $ time mu index --quiet + 40,34s user 2,56s system 64% cpu 1:06,17 total +.fi +(about 1099 messages per second). + +As shown, \fBmu\fR has been getting faster with each release, even +with relatively expensive new features such as text-normalization (for +case-insensitve/accent-insensitive matching). The profiles are +dominated by operations in the Xapian database now. + +.SH FILES +\fBmu\fR stores logs of its operations and queries in \fI/mu.log\fR +(by default, this is \fI~/.cache/mu/mu.log\fR). Upon startup, \fBmu\fR checks the +size of this log file. If it exceeds 1 MB, it will be moved to +\fI~/.cache/mu/mu.log.old\fR, overwriting any existing file of that name, and start +with an empty log file. This scheme allows for continued use of \fBmu\fR +without the need for any manual maintenance of log files. + +.SH ENVIRONMENT + +\fBmu index\fR uses \fBMAILDIR\fR to find the user's Maildir if it has not +been specified explicitly with \fB\-\-maildir\fR=\fI\fR. If +\fBMAILDIR\fR is not set, \fBmu index\fR will try \fI~/Maildir\fR. + +.SH RETURN VALUE + +\fBmu index\fR return 0 upon successful completion, and any other number +greater than 0 signals an error. + +.SH BUGS + +Please report bugs if you find them: +.BR https://github.com/djcb/mu/issues + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR maildir (5), +.BR mu (1), +.BR mu-init (1), +.BR mu-find (1), +.BR mu-cfind (1) diff --git a/man/mu-info.1 b/man/mu-info.1 new file mode 100644 index 0000000..43032be --- /dev/null +++ b/man/mu-info.1 @@ -0,0 +1,46 @@ +.TH MU-INFO 1 "February 2020" "User Manuals" + +.SH NAME + +mu info \- show information about the mu database + +.SH SYNOPSIS + +.B mu info [options] + +.SH DESCRIPTION + +\fBmu info\fR is the \fBmu\fR command for getting information about the mu +database. + +.SH OPTIONS + +Note, some of the general options are described in the \fBmu(1)\fR man-page and +not here, as they apply to multiple mu commands. + +.TP +\fB\-\-muhome\fR +use an alternative directory to store and read the database, write the logs, +etc. By default, \fBmu\fR uses XDG Base Directory Specification (e.g. on Linux +this defaults to \fI~/.cache/mu\fR, \fI~/.config/mu\fR). Earlier versions of +\fBmu\fR defaulted to \fI~/.mu\fR, which now requires \fI\-\-muhome=~/.mu\fR. + +.SH RETURN VALUE + +\fBmu init\fR returns 0 upon successful completion, or a non-zero exit code if +there was some error. + +.SH BUGS + +Please report bugs if you find them: +.BR https://github.com/djcb/mu/issues + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR maildir (5), +.BR mu (1), +.BR mu-index (1) diff --git a/man/mu-init.1 b/man/mu-init.1 new file mode 100644 index 0000000..34f95d8 --- /dev/null +++ b/man/mu-init.1 @@ -0,0 +1,69 @@ +.TH MU-INIT 1 "February 2020" "User Manuals" + +.SH NAME + +mu init \- initialize the mu message database + +.SH SYNOPSIS + +.B mu init [options] + +.SH DESCRIPTION + +\fBmu init\fR is the \fBmu\fR command for setting up the mu message +database. After \fBmu init\fR has completed, you can run \fBmu index\fR + +.SH OPTIONS + +Note, some of the general options are described in the \fBmu(1)\fR man-page and +not here, as they apply to multiple mu commands. + +.TP +\fB\-\-muhome\fR +use an alternative directory to store and read the database, write the logs, +etc. By default, \fBmu\fR uses XDG Base Directory Specification (e.g. on Linux +this defaults to \fI~/.cache/mu\fR, \fI~/.config/mu\fR). Earlier versions of +\fBmu\fR defaulted to \fI~/.mu\fR, which now requires \fI\-\-muhome=~/.mu\fR. + +.TP +\fB\-m\fR, \fB\-\-maildir\fR=\fI\fR +starts searching at \fI\fR. By default, \fBmu\fR uses whatever the +\fBMAILDIR\fR environment variable is set to; if it is not set, it tries +\fI~/Maildir\fR. The maildir must be on a single file-system; and symbolic links +are not supported. + +.TP +\fB\-\-my-address\fR=\fI\fR + +specifies that some e-mail addresses are 'my-address' (\fB\-\-my-address\fR can +be used multiple times). This is used by \fBmu cfind\fR -- any e-mail address +found in the address fields of a message which also has \fI\fR +in one of its address fields is considered a \fIpersonal\fR e-mail address. This +allows you, for example, to filter out (\fBmu cfind --personal\fR) addresses +which were merely seen in mailing list messages. + +.SH ENVIRONMENT + +\fBmu init\fR uses \fBMAILDIR\fR to find the user's Maildir if it has not been +specified explicitly with \fB\-\-maildir\fR=\fI\fR. If \fBMAILDIR\fR is +not set, \fBmu init\fR uses \fI~/Maildir\fR. + +.SH RETURN VALUE + +\fBmu init\fR returns 0 upon successful completion, or a non-zero exit code if +there was some error. + +.SH BUGS + +Please report bugs if you find them: +.BR https://github.com/djcb/mu/issues + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR maildir (5), +.BR mu (1), +.BR mu-index (1) diff --git a/man/mu-mkdir.1 b/man/mu-mkdir.1 new file mode 100644 index 0000000..6f9ddd2 --- /dev/null +++ b/man/mu-mkdir.1 @@ -0,0 +1,45 @@ +.TH MU MKDIR 1 "July 2012" "User Manuals" + +.SH NAME + +mu mkdir\- create a new Maildir + +.SH SYNOPSIS + +.B mu mkdir [options] [] + +.SH DESCRIPTION + +\fBmu mkdir\fR is the \fBmu\fR command for creating Maildirs. It does +\fBnot\fR use the mu database. With the \fBmkdir\fR command, you can create +new Maildirs with permissions 0755. For example, + +.nf + mu mkdir tom dick harry +.fi + +creates three maildirs, \fItom\fR, \fIdick\fR and \fIharry\fR. + +If creation fails for any reason, \fBno\fR attempt is made to remove any parts +that were created. This is for safety reasons. + +.SH OPTIONS + +.TP +\fB\-\-mode\fR= +set the file access mode for the new maildir(s) as in \fBchmod(1)\fR. + +.SH BUGS + +Please report bugs if you find them: +.BR https://github.com/djcb/mu/issues + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR maildir (5), +.BR mu (1), +.BR chmod (1) diff --git a/man/mu-query.7 b/man/mu-query.7 new file mode 100644 index 0000000..c3f3f5c --- /dev/null +++ b/man/mu-query.7 @@ -0,0 +1,358 @@ +.TH MU QUERY 7 "28 December 2017" "User Manuals" + +.SH NAME + +mu query language \- a language for finding messages in \fBmu\fR +databases. + +.SH DESCRIPTION + +The mu query language is a language used by \fBmu find\fR and +\fBmu4e\fR to find messages in \fBmu\fR's Xapian databases. The +language is quite similar to Xapian's default query-parser, but is an +independent implementation that is customized for the mu/mu4e +use-case. + +In this article, we give a structured but informal overview of the +query language and provide examples. + +\fBNOTE:\fR t if you use queries on the command-line (say, for \fBmu +find\fR), you need to quote any characters that would otherwise be +interpreted by the shell, such as \fB""\fR, \fB(\fR and \fB)\fR and +whitespace. + +.de EX1 +.nf +.RS +.. + +.de EX2 +.RE +.fi +.. + +.SH TERMS + +The basic building blocks of a query are \fBterms\fR; these are just +normal words like 'banana' or 'hello', or words prefixed with a +field-name which make them apply to just that field. See +.BR mu find +for all the available fields. + +Some example queries: +.EX1 +vacation +subject:capybara +maildir:/inbox +.EX2 + +Terms without an explicit field-prefix, (like 'vacation' above) are +interpreted like: +.EX1 +to:vacation or subject:vacation or body:vacation or ... +.EX2 + +The language is case-insensitive for terms and attempts to 'flatten' +any diacritics, so \fIangtrom\fR matches \fIÅngström\fR. + +.PP +If terms contain whitespace, they need to be quoted: +.EX1 +subject:"hi there" +.EX2 +This is a so-called \fIphrase query\fR, which means that we match +against subjects that contain the literal phrase "hi there". + +Remember that you need to escape those quotes when using this from the +command-line: +.EX1 +mu find subject:\\"hi there\\" +.EX2 + +.SH LOGICAL OPERATORS + +We can combine terms with logical operators -- binary ones: \fBand\fR, +\fBor\fR, \fBxor\fR and the unary \fBnot\fR, with the conventional +rules for precedence and association, and are case-insensitive. + +.PP +You can also group things with \fB(\fR and \fB)\fR, so you can do +things like: +.EX1 +(subject:beethoven or subject:bach) and not body:elvis +.EX2 + +If you do not explicitly specify an operator between terms, \fBand\fR +is implied, so the queries +.EX1 +subject:chip subject:dale +.EX2 +.EX1 +subject:chip AND subject:dale +.EX2 +are equivalent. For readability, we recommend the second version. + +Note that a \fIpure not\fR - e.g. searching for \fBnot apples\fR is +quite a 'heavy' query. + +.SH REGULAR EXPRESSIONS AND WILDCARDS + +The language supports matching regular expressions that follow +ECMAScript; for details, see + +.BR http://www.cplusplus.com/reference/regex/ECMAScript/ + +Regular expressions must be enclosed in \fB//\fR. Some examples: +.EX1 +subject:/h.llo/ # match hallo, hello, ... +subject:/ +.EX2 + +Note the difference between 'maildir:/foo' and 'maildir:/foo/'; the +former matches messages in the '/foo' maildir, while the latter +matches all messages in all maildirs that match 'foo', such +as '/foo', '/bar/cuux/foo', '/fooishbar' etc. + +Wildcards are an older mechanism for matching where a term with a +rightmost \fB*\fR (and \fIonly\fR in that position) matches any term +that starts with the part before the \fB*\fR; they are supported for +backward compatibility and \fBmu\fR translates them to regular +expressions internally: +.EX1 +foo* +.EX2 +is equivalent to +.EX1 +/foo.*/ +.EX2 + +As a note of caution, certain wild-cards and regular expression can +take quite a bit longer than 'normal' queries. + +.SH FIELDS + +We already saw a number of search fields, such as \fBsubject:\fR and +\fBbody:\fR. Here is the full table, a shortcut character and a +description. +.EX1 + cc,c Cc (carbon-copy) recipient(s) + bcc,h Bcc (blind-carbon-copy) recipient(s) + from,f Message sender + to,t To: recipient(s) + subject,s Message subject + body,b Message body + maildir,m Maildir + msgid,i Message-ID + prio,p Message priority (\fIlow\fR, \fInormal\fR or \fIhigh\fR) + flag,g Message Flags + date,d Date range + size,z Message size range + embed,e Search inside embedded text parts + file,j Attachment filename + mime,y MIME-type of one or more message parts + tag,x Tags for the message + list,v Mailing list (e.g. the List-Id value) +.EX2 +The shortcut character can be used instead of the full name: +.EX1 +f:foo@bar +.EX2 +is the same as +.EX1 +from:foo@bar +.EX2 +For queries that are not one-off, we would recommend the longer name +for readability. + +There are also the special fields \fBcontact:\fR, which matches all +contact-fields (\fIfrom\fR, \fIto\fR, \fIcc\fR and \fIbcc\fR), and +\fBrecip\fR, which matches all recipient-fields (\fIto\fR, \fIcc\fR +and \fIbcc\fR). Hence, for instance, +.EX1 +contact:fnorb@example.com +.EX2 +is equivalent to +.EX1 +(from:fnorb@example.com or to:fnorb@example.com or + cc:from:fnorb@example.com or bcc:fnorb@example.com) +.EX2 + +.SH DATE RANGES + +The \fBdate:\fR field takes a date-range, expressed as the lower and +upper bound, separated by \fB..\fR. Either lower or upper (but not +both) can be omitted to create an open range. + +Dates are expressed in local time and using ISO-8601 format +(YYYY-MM-DD HH:MM:SS); you can leave out the right part, and \fBmu\fR +adds the rest, depending on whether this is the beginning or end of +the range (e.g., as a lower bound, '2015' would be interpreted as the +start of that year; as an upper bound as the end of the year). + +You can use '/' , '.', '-' and 'T' to make dates more human readable. + +Some examples: +.EX1 +date:20170505..20170602 +date:2017-05-05..2017-06-02 +date:..2017-10-01T12:00 +date:2015-06-01.. +date:2016..2016 +.EX2 + +You can also use the special 'dates' \fBnow\fR and \fBtoday\fR: +.EX1 +date:20170505..now +date:today.. +.EX2 + +Finally, you can use relative 'ago' times which express some time +before now and consist of a number followed by a unit, with units +\fBs\fR for seconds, \fBM\fR for minutes, \fBh\fR for hours, \fBd\fR +for days, \fBw\fR for week, \fBm\fR for months and \fBy\fR for years. +Some examples: + +.EX1 +date:3m.. +date:2017.01.01..5w +.EX2 + +.SH SIZE RANGES + +The \fBsize\fR or \fBz\fR field allows you to match \fIsize ranges\fR +-- that is, match messages that have a byte-size within a certain +range. Units (b (for bytes), K (for 1000 bytes) and M (for 1000 * 1000 +bytes) are supported). Some examples: + +.EX1 +size:10k..2m +size:10m.. +.EX2 + +.SH FLAG FIELDS + +The \fBflag\fR/\fBg\fR field allows you to match message flags. The +following fields are available: +.EX1 + a,attach Message with attachment + d,draft Draft Message + f,flagged Flagged + l,list Mailing-list message + n,new New message (in new/ Maildir) + p,passed Passed ('Handled') + r,replied Replied + s,seen Seen + t,trashed Marked for deletion + u,unread new OR NOT seen + x,encrypted Encrypted message + z,signed Signed message +.EX2 + +Some examples: +.EX1 +flag:attach +flag:replied +g:x +.EX2 + +Encrypted messages may be signed as well, but this is only visible +after decrypting and thus, invisible to \fBmu\fR. + +.SH PRIORITY FIELD + +The message priority field (\fBprio:\fR) has three possible values: +\fBlow\fR, \fBnormal\fR or \fBhigh\fR. For instance, to match +high-priority messages: +.EX1 + prio:high +.EX2 + +.SH MAILDIR + +The Maildir field describes the directory path starting \fBafter\fR +the Maildir-base path, and before the \fI/cur/\fR or \fI/new/\fR part. +So for example, if there's a message with the file name +\fI~/Maildir/lists/running/cur/1234.213:2,\fR, you could find it (and +all the other messages in the same maildir) with: +.EX1 +maildir:/lists/running +.EX2 + +Note the starting '/'. If you want to match mails in the 'root' +maildir, you can do with a single '/': +.EX1 +maildir:/ +.EX2 + +If you have maildirs (or any fields) that include spaces, you need to +quote them, ie. +.EX1 +maildir:"/Sent Items" +.EX2 + +Note that from the command-line, such queries must be quoted: +.EX1 +mu find 'maildir:"/Sent Items"' +.EX2 + +.SH MORE EXAMPLES + +Here are some simple examples of \fBmu\fR queries; you can make many +more complicated queries using various logical operators, parentheses +and so on, but in the author's experience, it's usually faster to find +a message with a simple query just searching for some words. + +Find all messages with both 'bee' and 'bird' (in any field) +.EX1 +bee AND bird +.EX2 + +Find all messages with either Frodo or Sam: +.EX1 +Frodo OR Sam +.EX2 + +Find all messages with the 'wombat' as subject, and 'capibara' anywhere: +.EX1 +subject:wombat and capibara +.EX2 + +Find all messages in the 'Archive' folder from Fred: +.EX1 +from:fred and maildir:/Archive +.EX2 + +Find all unread messages with attachments: +.EX1 +flag:attach and flag:unread +.EX2 + + +Find all messages with PDF-attachments: +.EX1 +mime:application/pdf +.EX2 + +Find all messages with attached images: +.EX1 +mime:image/* +.EX2 + +.SH CAVEATS + +With current Xapian versions, the apostroph character is considered +part of a word. Thus, you cannot find \fID'Artagnan\fR by searching +for \fIArtagnan\fR. So, include the apostroph in search or use a +regexp search. + +Matching on spaces has changed compared to the old query-parser; this +applies e.g. to Maildirs that have spaces in their name, such as +\fISent Items\fR. See \fBMAILDIR\fR above. + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR mu-find (1) diff --git a/man/mu-remove.1 b/man/mu-remove.1 new file mode 100644 index 0000000..36c25c2 --- /dev/null +++ b/man/mu-remove.1 @@ -0,0 +1,49 @@ +.TH MU REMOVE 1 "July 2012" "User Manuals" + +.SH NAME + +\fBmu remove\fR is the \fBmu\fR command to remove messages from the database. + +.SH SYNOPSIS + +.B mu remove [options] [] + +.SH DESCRIPTION + +\fBmu remove\fR removes specific messages from the database, each of them +specified by their filename. The files do not have to exist in the file +system. + +.SH OPTIONS + +\fBmu remove\fR does not have its own options, but the general options for +determining the location of the database (\fI--muhome\fR) are available. See +\fBmu-index(1)\fR for more information. + +.SH RETURN VALUE + +\fBmu remove\fR returns 0 upon success; in general, the following error codes are +returned: + +.nf +| code | meaning | +|------+-----------------------------------| +| 0 | ok | +| 1 | general error | +| 5 | some database update error | +.fi + +.SH BUGS + +Please report bugs if you find them: +.BR https://github.com/djcb/mu/issues + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR mu (1), +.BR mu-index (1), +.BR mu-add (1) diff --git a/man/mu-script.1 b/man/mu-script.1 new file mode 100644 index 0000000..aa4159b --- /dev/null +++ b/man/mu-script.1 @@ -0,0 +1,83 @@ +.TH MU SCRIPT 1 "June 2013" "User Manuals" + +.SH NAME + +mu script\- show the available mu scripts, and run them. + +.SH SYNOPSIS + +.B mu script [options] [] + +.B mu [] + +.SH DESCRIPTION + +\fBmu script\fR is the \fBmu\fR command to list available \fBmu\fR scripts. +The scripts are to be implemented in the Guile programming language, and +therefore only work if your \fBmu\fR is built with support for Guile. In +addition, many scripts require you to have \fBgnuplot\fR installed. + +Without any parameters, \fBmu script\fR lists the available scripts. If you +provide a pattern (a regular expression), only the scripts whose name or +one-line description match this pattern are listed. See the examples below. + +\fBmu\fR ships with a number of scripts. + +.SH OPTIONS + +.TP +\fB\-\-verbose\fR,\fB\-v\fR +when listing the available scripts, show the long descriptions. + +\fB\-\-\fR +all options on the right side of the \fB\-\-\fR are passed to the script. + +.SH EXAMPLES + +List all available scripts (one-line descriptions): +.nf + $ mu script +.fi + +List all available scripts matching \fImonth\fR (long descriptions): +.nf + $ mu script -v month +.fi + +Run the \fImsgs-per-month\fR script for messages matching 'hello', and pass it +the \fI--textonly\fR parameter: +.nf + $ mu msgs-per-month --query=hello --textonly +.fi + +.SH RETURN VALUE + +\fBmu script\fR returns 0 when all went well, and returns some non-zero error +code when this is not the case. + +.SH FILES + +You can make your own Scheme scripts accessible through \fBmu script\fR by +putting them in \fI/scripts\fR (which is typically +\fI~/.mu/scripts\fR). It is a good idea to document the scripts by using some +special comments in the source code: +.nf +;; INFO: this is my script -- one-line description +;; INFO: (longer description) +;; INFO: --option1= (describe option1) +;; INFO: etc. +.fi + +.SH BUGS + +Please report bugs if you find them: +.BR https://github.com/djcb/mu/issues + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR mu (1), +.BR guile (1) diff --git a/man/mu-server.1 b/man/mu-server.1 new file mode 100644 index 0000000..087483c --- /dev/null +++ b/man/mu-server.1 @@ -0,0 +1,61 @@ +.TH MU-SERVER 1 "January 2020" "User Manuals" + +.SH NAME + +mu server \- the mu backend for the mu4e e-mail client + +.SH SYNOPSIS + +.B mu server [options] + +.SH DESCRIPTION + +\fBmu server\fR starts a simple shell in which one can query and manipulate the +mu database. The output uses s-expressions. \fBmu server\fR is not meant for use +by humans, except for debugging purposes. Instead, it is designed specifically +for the \fBmu4e\fR e-mail client. + +In this man-page, we document the commands \fBmu server\fR accepts, as well as +their responses. In general, the commands sent to the server are s-expressions +of the form: + +.nf + ( :param1 value1 :param2 value2) +.fi + +For example, to view a certain message, the command would be: + +.nf + (view :docid 12345) +.fi + +Parameters can be sent in any order; they must be of the correct type though. +See \fBlib/utils/mu-sexp-parser.hh\fR and \fBlib/utils/mu-sexp-parser.cc\fR in +source-tree for the details. + + +.SH OUTPUT FORMAT + +\fBmu server\fR accepts a number of commands, and delivers its results in +the form: + +.nf + \\376\\377 +.fi + +\\376 (one byte 0xfe), followed by the length of the s-expression expressed as +an hexadecimal number, followed by another \\377 (one byte 0xff), followed by +the actual s-expression. + +By prefixing the expression with its length, it can be processed more +efficiently. The \\376 and \\377 were chosen since they never occur in valid +UTF-8 (in which the s-expressions are encoded). + +.sh COMMANDS + + +.SH AUTHOR +Dirk-Jan C. Binnema + +.SH "SEE ALSO" +.BR mu (1) diff --git a/man/mu-verify.1 b/man/mu-verify.1 new file mode 100644 index 0000000..38640f7 --- /dev/null +++ b/man/mu-verify.1 @@ -0,0 +1,79 @@ +.TH MU VERIFY 1 "June 2015" "User Manuals" + +.SH NAME + +mu verify\- verify message signatures and display information about them + +.SH SYNOPSIS + +.B mu verify [options] + +.SH DESCRIPTION + +\fBmu verify\fR is the \fBmu\fR command for verifying message signatures (such +as PGP/GPG signatures) and displaying information about them. The sub-command +works on message files, and does not require the message to be indexed in the +database. + +\fBmu verify\fR depends on \fBgpg\fR, and uses the one it finds in your +\fBPATH\fR. If you want to use another one, you need to set \fBMU_GPG_PATH\fB +to the full path to the desired \fBgpg\fR. + +.SH OPTIONS + +.TP +\fB\-r\fR, \fB\-\-auto\-retrieve\fR +attempt to find keys online (see the \fBauto-key-retrieve\fR option in the +\fBgnupg(1)\fR documentation). + +\" .TP +\" \fB\-u\fR, \fB\-\-use\-agent\fR attempt to use the GPG-agent (see the the +\" \fBgnupg-agent(1)\fR documentation). Note that GPG-agent is running many +\" desktop-evironment; you can check whether this is the case using: +\" .nf +\" $ env | grep GPG_AGENT_INFO +\" .fi + +.SH EXAMPLES + +To display aggregated (one-line) information about the signatures in a message: +.nf + $ mu verify msgfile +.fi + +To display information about all the signatures: +.nf + $ mu verify --verbose msgfile +.fi + +If you only want to use the exit code, you can use: +.nf + $ mu verify --quiet msgfile +.fi +which does not give any output. + +.SH RETURN VALUE + +\fBmu verify\fR returns 0 when all signatures could be verified to be good, +and returns some non-zero error code when this is not the case. + +.nf +| code | meaning | +|------+--------------------------------| +| 0 | ok | +| 1 | some non-verified signature(s) | +.fi + +.SH BUGS + +Please report bugs if you find them: +.BR https://github.com/djcb/mu/issues + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR mu (1), +.BR gpg (1) diff --git a/man/mu-view.1 b/man/mu-view.1 new file mode 100644 index 0000000..05ecd7d --- /dev/null +++ b/man/mu-view.1 @@ -0,0 +1,54 @@ +.TH MU VIEW 1 "June 2013" "User Manuals" + +.SH NAME + +mu view\- display an e-mail message file + +.SH SYNOPSIS + +.B mu view [options] [] + +.SH DESCRIPTION + +\fBmu view\fR is the \fBmu\fR command for displaying e-mail message files. It +works on message files and does \fInot\fR require the message to be indexed in +the database. + +The command shows some common headers (From:, To:, Cc:, Bcc:, Subject: and +Date:), the list of attachments and the plain-text body of the message (if +any). + +.SH OPTIONS + +.TP +\fB\-\-summary-len\fR=\fI\fR +instead of displaying the full message, output a summary based upon the first +\fI\fR lines of the message. + +.TP +\fB\-\-terminate\fR +terminate messages with \\f (\fIform-feed\fR) characters when displaying +them. This is useful when you want to further process them. + +.TP +\fB\-\-decrypt\fR +attempt to decrypt encrypted message bodies. This is only possible if \fBmu\fR +was built with crypto-support. Users are strongly recommended to use +\fBgpg-agent\fR; however, if needed, \fBmu\fR will request the user password +from the console. + +.SH BUGS + +Please report bugs if you find them: +.BR https://github.com/djcb/mu/issues + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" + +.BR mu (1), +.BR mu-index (1), +.BR gpg (1), +.BR gpg-agent (1) diff --git a/man/mu.1 b/man/mu.1 new file mode 100644 index 0000000..6998f33 --- /dev/null +++ b/man/mu.1 @@ -0,0 +1,182 @@ +.TH MU 1 "February 2020" "User Manuals" + +.SH NAME + +mu \- a set of tools to deal with Maildirs and message files, in particular to +index and search e-mail messages. + +.SH SYNOPSIS + +In alphabetical order: + +.B mu [options] +general mu command. + +.B mu add +add specific messages to the database. See +.BR mu-add(1) + +.B mu cfind [options] [] +find contacts. See +.BR mu-cfind(1) + +.B mu extract [options] [] [] +extract attachments and other MIME-parts. See +.BR mu-extract(1) + +.B mu find [options] +find messages. See +.BR mu-find(1) + +.B mu help [command] +get help for some command. See +.BR mu-help(1) + +.B mu index [options] +(re)index the messages in a Maildir. See +.BR mu-index(1) + +.B mu info [options] +show information about the mu database +.BR mu-info(1) + +.B mu init [options] +initialize the mu database +.BR mu-init(1) + +.B mu mkdir [options] [] +create a new Maildir. See +.BR mu-mkdir(1) + +.B mu remove [options] +remove specific messages from the database. See +.BR mu-remove(1) + +.B mu script [options] +run a mu (Guile) script. See +.BR mu-script(1) + +.B mu server [options] +start a server process (for \fBmu4e\fR-internal use). See +.BR mu-server(1) + +.B mu view [] +view a specific message. See +.BR mu-view(1) + +.SH DESCRIPTION + +\fBmu\fR is a set of tools for dealing with Maildirs and the e-mail messages +in them. + +\fBmu\fR's main purpose is to enable searching of e-mail messages. It +does so by periodically scanning a Maildir directory tree and +analyzing the e-mail messages found (this is called 'indexing'). The +results of this analysis are stored in a database, which can then be +queried. + +In addition to indexing and searching, \fBmu\fR also offers +functionality for viewing messages, extracting attachments and +creating maildirs, and searching and exporting contact information. + +\fBmu\fR can be used from the command line or can be integrated with various +e-mail clients. + +This manpage gives a general overview of the available commands +(\fBindex\fR, \fBfind\fR, etc.); each \fBmu\fR command has its own +man-page as well. + +.SH COLORS + +Some \fBmu\fR sub-commands support colorized output, and do so by +default. If you don't want colors, you can use \fI--nocolor\fR. + +Currently, \fBmu find\fR, \fBmu view\fR, \fBmu cfind\fR and \fBmu extract\fR +support colors. + +.SH ENCODING + +\fBmu\fR's output is in the current locale, with the exceptions of the output +specifically meant for output to UTF8-encoded files. In practice, this means +that the output of commands \fBindex\fR, \fBview\fR, +\fBextract\fR is always encoded according to the current locale. + +The same is true for \fBfind\fR and \fBcfind\fR, with some exceptions, where +the output is always UTF-8, regardless of the locale. + +For \fBcfind\fR the exception is \fI--format=bbdb\fR. This is hard-coded to +UTF-8, and as such specified in the output-file, so emacs/bbdb can handle it +correctly without guessing. + +For \fBfind\fR the output is encoded according the locale for +\fI--format=plain\fR (the default), and UTF-8 for all other formats +(\fIjson\fR, \fIsexp\fR, \fIxml\fR). + +.SH DATABASE AND FILE + +Commands \fBmu index\fR and \fBfind\fR and \fBcfind\fR work with the database, +while the other ones work on individual mail files. Hence, running \fBview\fR, +\fBmkdir\fR and \fBextract\fR does not require the mu database. + +The various commands are discussed in more detail in their own separate +man-pages; here the general options are discussed. + +.SH OPTIONS + +\fBmu\fR offers several general options that apply to all commands, +including \fBmu\fR without any command. + +.TP +\fB\-\-muhome\fR +use an alternative directory to store and read the database, write the logs, +etc. By default, \fBmu\fR uses XDG Base Directory Specification (e.g. on Linux +by default \fI~/.cache/mu\fR, \fI~/.config/mu\fR). Earlier versions of \fBmu\fR defaulted +to \fI~/.mu\fR, which now requires \fI\-\-muhome=~/.mu\fR. + +.TP +\fB\-d\fR, \fB\-\-debug\fR +makes \fBmu\fR generate extra debug information, +useful for debugging the program itself. By default, debug information goes to +the log file, \fI~/.cache/mu/mu.log\fR. It can safely be deleted when \fBmu\fR is +not running. When running with \fB--debug\fR option, the log file can grow +rather quickly. See the note on logging below. + +.TP +\fB\-q\fR, \fB\-\-quiet\fR +causes \fBmu\fR not to output informational +messages and progress information to standard output, but only to the log +file. Error messages will still be sent to standard error. Note that \fBmu +index\fR is \fBmuch\fR faster with \fB\-\-quiet\fR, so it is recommended you +use this option when using \fBmu\fR from scripts etc. + +.TP +\fB\-\-log-stderr\fR +causes \fBmu\fR to \fBnot\fR output log messages to standard error, in +addition to sending them to the log file. + +.TP +\fB\-v\fR, \fB\-\-version\fR +prints \fBmu\fR version and copyright information. + +.TP +\fB\-h\fR, \fB\-\-help\fR +lists the various command line options. + +.SH ERROR CODES + +The various mu subcommands typically exit with 0 (zero) upon success, and +non-zero when some error occurred. + +.SH BUGS + +Please report bugs if you find them: +.BR https://github.com/djcb/mu/issues + +.SH AUTHOR + +Dirk-Jan C. Binnema + +.SH "SEE ALSO" +.BR mu-index (1), mu-find (1), mu-cfind (1), mu-mkdir (1), mu-view (1), +.BR mu-extract (1), mu-easy (1), mu-bookmarks (5), mu-query (7) +.BR https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html diff --git a/mu/Makefile.am b/mu/Makefile.am new file mode 100644 index 0000000..b0f8d8a --- /dev/null +++ b/mu/Makefile.am @@ -0,0 +1,120 @@ +## Copyright (C) 2010-2020 Dirk-Jan C. Binnema +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +AM_CPPFLAGS= \ + -I${top_srcdir}/lib \ + $(GLIB_CFLAGS) \ + $(CODE_COVERAGE_CFLAGS) + +# don't use -Werror, as it might break on other compilers +# use -Wno-unused-parameters, because some callbacks may not +# really need all the params they get +AM_CFLAGS= \ + $(JSON_GLIB_CFLAGS) \ + $(ASAN_CFLAGS) \ + $(WARN_CFLAGS) \ + $(CODE_COVERAGE_CFLAGS) \ + -Wno-switch-enum \ + -DMU_SCRIPTS_DIR="\"$(pkgdatadir)/scripts/\"" + +AM_CXXFLAGS= \ + $(ASAN_CXXCFLAGS) \ + $(WARN_CXXFLAGS) \ + $(CODE_COVERAGE_CFLAGS) + +AM_LDFLAGS= \ + $(ASAN_LDFLAGS) + +bin_PROGRAMS= \ + mu + +# note, mu.cc is only '.cc' and not '.c' because libmu must explicitly +# be linked as c++, not c. +mu_SOURCES= \ + mu.cc \ + mu-cmd-cfind.c \ + mu-config.c \ + mu-config.h \ + mu-cmd-extract.c \ + mu-cmd-find.c \ + mu-cmd-index.c \ + mu-cmd-server.cc \ + mu-cmd-script.c \ + mu-cmd.c \ + mu-cmd.h + +BUILT_SOURCES= \ + mu-help-strings.h + +mu-help-strings.h: mu-help-strings.txt mu-help-strings.awk + $(AM_V_GEN) $(AWK) -f ${top_srcdir}/mu/mu-help-strings.awk < $< > $@ + +mu_LDADD= \ + ${top_builddir}/lib/libmu.la \ + ${top_builddir}/lib/utils/libmu-utils.la \ + $(GLIB_LIBS) \ + $(READLINE_LIBS) \ + $(CODE_COVERAGE_LIBS) + +EXTRA_DIST= \ + mu-help-strings.awk \ + mu-help-strings.txt + +noinst_PROGRAMS= $(TEST_PROGS) + +test_cflags= \ + ${AM_CFLAGS} \ + -DMU_TESTMAILDIR=\"${abs_top_srcdir}/lib/testdir\" \ + -DMU_TESTMAILDIR2=\"${abs_top_srcdir}/lib/testdir2\" \ + -DMU_TESTMAILDIR3=\"${abs_top_srcdir}/lib/testdir3\" \ + -DMU_TESTMAILDIR4=\"${abs_top_srcdir}/lib/testdir4\" \ + -DMU_PROGRAM=\"${abs_top_builddir}/mu/mu\" \ + -DABS_CURDIR=\"${abs_builddir}\" \ + -DABS_SRCDIR=\"${abs_srcdir}\" + +TEST_PROGS += test-mu-query +test_mu_query_SOURCES= test-mu-query.c dummy.cc +test_mu_query_CFLAGS=$(test_cflags) +test_mu_query_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS) + +TEST_PROGS += test-mu-cmd +test_mu_cmd_SOURCES= test-mu-cmd.c dummy.cc +test_mu_cmd_CFLAGS=$(test_cflags) +test_mu_cmd_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS) + +TEST_PROGS += test-mu-cmd-cfind +test_mu_cmd_cfind_SOURCES= test-mu-cmd-cfind.c dummy.cc +test_mu_cmd_cfind_CFLAGS=$(test_cflags) +test_mu_cmd_cfind_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS) + +TEST_PROGS += test-mu-threads +test_mu_threads_SOURCES= test-mu-threads.c dummy.cc +test_mu_threads_CFLAGS=$(test_cflags) +test_mu_threads_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS) + +# we need to use dummy.cc to enforce c++ linking... +BUILT_SOURCES+= \ + dummy.cc +dummy.cc: + touch dummy.cc + +TESTS=$(TEST_PROGS) +include $(top_srcdir)/aminclude_static.am + +CLEANFILES= \ + $(BUILT_SOURCES) diff --git a/mu/mu-cmd-cfind.c b/mu/mu-cmd-cfind.c new file mode 100644 index 0000000..4157bb0 --- /dev/null +++ b/mu/mu-cmd-cfind.c @@ -0,0 +1,470 @@ +/* +** Copyright (C) 2011-2019 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +** details. +** +** You should have received a copy of the GNU General Public License along with +** this program; if not, write to the Free Software Foundation, Inc., 51 +** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include "config.h" + +#include +#include +#include +#include + +#include "mu-cmd.h" +#include "mu-contacts.hh" +#include "mu-runtime.h" + +#include "utils/mu-util.h" +#include "utils/mu-str.h" +#include "utils/mu-date.h" + +/** + * guess the last name for the given name; clearly, + * this is just a rough guess for setting an initial value. + * + * @param name a name + * + * @return the last name, as a newly allocated string (free with + * g_free) + */ +static gchar* +guess_last_name (const char *name) +{ + const gchar *lastsp; + + if (!name) + return g_strdup (""); + + lastsp = g_strrstr (name, " "); + + return g_strdup (lastsp ? lastsp + 1 : ""); +} + +/** + * guess the first name for the given name; clearly, + * this is just a rough guess for setting an initial value. + * + * @param name a name + * + * @return the first name, as a newly allocated string (free with + * g_free) + */ +static gchar* +guess_first_name (const char *name) +{ + const gchar *lastsp; + + if (!name) + return g_strdup (""); + + lastsp = g_strrstr (name, " "); + + if (lastsp) + return g_strndup (name, lastsp - name); + else + return g_strdup (name); +} + +/** + * guess some nick name for the given name; if we can determine an + * first name, last name, the nick will be first name + the first char + * of the last name. otherwise, it's just the first name. clearly, + * this is just a rough guess for setting an initial value for nicks. + * + * @param name a name + * + * @return the guessed nick, as a newly allocated string (free with g_free) + */ +static gchar* +cleanup_str (const char* str) +{ + gchar *s; + const gchar *cur; + unsigned i; + + if (mu_str_is_empty(str)) + return g_strdup (""); + + s = g_new0 (char, strlen(str) + 1); + + for (cur = str, i = 0; *cur; ++cur) { + if (ispunct(*cur) || isspace(*cur)) + continue; + else + s[i++] = *cur; + } + + return s; +} + +static char* +uniquify_nick (const char *nick, GHashTable *nicks) +{ + guint u; + + for (u = 2; u != 1000; ++u) { + char *cand; + cand = g_strdup_printf ("%s%u", nick, u); + if (!g_hash_table_contains (nicks, cand)) + return cand; + } + + return g_strdup (nick); /* if all else fails */ +} + + +static gchar* +guess_nick (const char* name, GHashTable *nicks) +{ + gchar *fname, *lname, *nick; + gchar initial[7]; + + fname = guess_first_name (name); + lname = guess_last_name (name); + + /* if there's no last name, use first name as the nick */ + if (mu_str_is_empty(fname) || mu_str_is_empty(lname)) { + g_free (lname); + nick = fname; + goto leave; + } + + memset (initial, 0, sizeof(initial)); + /* couldn't we get an initial for the last name? */ + if (g_unichar_to_utf8 (g_utf8_get_char (lname), initial) == 0) { + g_free (lname); + nick = fname; + goto leave; + } + + nick = g_strdup_printf ("%s%s", fname, initial); + g_free (fname); + g_free (lname); + +leave: + { + gchar *tmp; + tmp = cleanup_str (nick); + g_free (nick); + nick = tmp; + } + + if (g_hash_table_contains (nicks, nick)) { + char *tmp; + tmp = uniquify_nick (nick, nicks); + g_free (nick); + nick = tmp; + } + + g_hash_table_add (nicks, g_strdup(nick)); + + return nick; +} + + + +static void +print_header (MuConfigFormat format) +{ + switch (format) { + case MU_CONFIG_FORMAT_BBDB: + g_print (";; -*-coding: utf-8-emacs;-*-\n" + ";;; file-version: 6\n"); + break; + case MU_CONFIG_FORMAT_MUTT_AB: + g_print ("Matching addresses in the mu database:\n"); + break; + default: + break; + } +} + +static void +each_contact_bbdb (const char *email, const char *name, time_t tstamp) +{ + char *fname, *lname, *now, *timestamp; + + fname = guess_first_name (name); + lname = guess_last_name (name); + now = mu_date_str ("%Y-%m-%d", time(NULL)); + timestamp = mu_date_str ("%Y-%m-%d", tstamp); + + g_print ("[\"%s\" \"%s\" nil nil nil nil (\"%s\") " + "((creation-date . \"%s\") (time-stamp . \"%s\")) nil]\n", + fname, lname, email, now, timestamp); + + g_free (now); + g_free (timestamp); + g_free (fname); + g_free (lname); +} + + +static void +each_contact_mutt_alias (const char *email, const char *name, + GHashTable *nicks) +{ + + gchar *nick; + + if (!name) + return; + + nick = guess_nick (name, nicks); + mu_util_print_encoded ("alias %s %s <%s>\n", + nick, name, email); + g_free (nick); + +} + + +static void +each_contact_wl (const char *email, const char *name, GHashTable *nicks) +{ + gchar *nick; + + if (!name) + return; + + nick = guess_nick (name, nicks); + mu_util_print_encoded ("%s \"%s\" \"%s\"\n", + email, nick, name); + g_free (nick); +} + + +static void +each_contact_org_contact (const char *email, const char *name) +{ + if (name) + mu_util_print_encoded ( + "* %s\n:PROPERTIES:\n:EMAIL: %s\n:END:\n\n", + name, email); +} + + +static void +print_csv_field (const char *str) +{ + char *s; + + if (!str) + return; + + s = mu_str_replace (str, "\"", "\"\""); + if (strchr (s, ',')) + mu_util_print_encoded ("\"%s\"", s); + else + mu_util_print_encoded ("%s", s); + + g_free (s); +} + +static void +each_contact_csv (const char *email, const char *name) +{ + print_csv_field (name); + mu_util_print_encoded (","); + print_csv_field (email); + mu_util_print_encoded ("\n"); +} + + + +static void +print_plain (const char *email, const char *name, gboolean color) +{ + if (name) { + if (color) fputs (MU_COLOR_MAGENTA, stdout); + mu_util_fputs_encoded (name, stdout); + fputs (" ", stdout); + } + + if (color) + fputs (MU_COLOR_GREEN, stdout); + + mu_util_fputs_encoded (email, stdout); + + if (color) + fputs (MU_COLOR_DEFAULT, stdout); + + fputs ("\n", stdout); +} + +typedef struct { + MuConfigFormat format; + gboolean color, personal; + time_t after; + GRegex *rx; + GHashTable *nicks; + size_t n; +} ECData; + + +static void +each_contact (const char *full_address, + const char *email, const char *name, gboolean personal, + time_t last_seen, size_t freq, gint64 tstamp, + ECData *ecdata) +{ + if (ecdata->personal && !personal) + return; + + if (tstamp < ecdata->after) + return; + + if (ecdata->rx && + !g_regex_match (ecdata->rx, email, 0, NULL) && + !g_regex_match (ecdata->rx, name ? name : "", 0, NULL)) + return; + + ++ecdata->n; + + switch (ecdata->format) { + case MU_CONFIG_FORMAT_MUTT_ALIAS: + each_contact_mutt_alias (email, name, ecdata->nicks); + break; + case MU_CONFIG_FORMAT_MUTT_AB: + mu_util_print_encoded ("%s\t%s\t\n", + email, name ? name : ""); + break; + case MU_CONFIG_FORMAT_WL: + each_contact_wl (email, name, ecdata->nicks); + break; + case MU_CONFIG_FORMAT_ORG_CONTACT: + each_contact_org_contact (email, name); + break; + case MU_CONFIG_FORMAT_BBDB: + each_contact_bbdb (email, name, last_seen); + break; + case MU_CONFIG_FORMAT_CSV: + each_contact_csv (email, name); + break; + case MU_CONFIG_FORMAT_DEBUG: { + char datebuf[32]; + strftime(datebuf, sizeof(datebuf), "%F %T", + gmtime(&last_seen)); + g_print ("%s\n\tname: %s\n\t%s\n\tpersonal: %s\n\tfreq: %zu\n" + "\tlast-seen: %s\n", + email, + name ? name : "", + full_address, + personal ? "yes" : "no", + freq, + datebuf); + } break; + default: + print_plain (email, name, ecdata->color); + } +} + + +static MuError +run_cmd_cfind (MuStore *store, + const char* pattern, + gboolean personal, + time_t after, + MuConfigFormat format, + gboolean color, + GError **err) +{ + gboolean rv; + ECData ecdata; + + memset(&ecdata, 0, sizeof(ecdata)); + + if (pattern) { + ecdata.rx = g_regex_new (pattern, + G_REGEX_CASELESS|G_REGEX_OPTIMIZE, + 0, err); + if (!ecdata.rx) + return MU_ERROR_CONTACTS; + } + + ecdata.personal = personal; + ecdata.n = 0; + ecdata.after = after; + ecdata.format = format; + ecdata.color = color; + ecdata.nicks = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + + print_header (format); + rv = mu_contacts_foreach (mu_store_contacts(store), + (MuContactsForeachFunc)each_contact, &ecdata); + g_hash_table_unref (ecdata.nicks); + + if (ecdata.rx) + g_regex_unref (ecdata.rx); + + if (ecdata.n == 0) { + g_warning ("no matching contacts found"); + return MU_ERROR_NO_MATCHES; + } + + return rv ? MU_OK : MU_ERROR_CONTACTS; +} + +static gboolean +cfind_params_valid (MuConfig *opts) +{ + switch (opts->format) { + case MU_CONFIG_FORMAT_PLAIN: + case MU_CONFIG_FORMAT_MUTT_ALIAS: + case MU_CONFIG_FORMAT_MUTT_AB: + case MU_CONFIG_FORMAT_WL: + case MU_CONFIG_FORMAT_BBDB: + case MU_CONFIG_FORMAT_CSV: + case MU_CONFIG_FORMAT_ORG_CONTACT: + case MU_CONFIG_FORMAT_DEBUG: + break; + default: + g_warning ("invalid output format %s", + opts->formatstr ? opts->formatstr : ""); + return FALSE; + } + + /* only one pattern allowed */ + if (opts->params[1] && opts->params[2]) { + g_warning ("usage: mu cfind [options] []"); + return FALSE; + } + + return TRUE; +} + +MuError +mu_cmd_cfind (MuStore *store, MuConfig *opts, GError **err) +{ + g_return_val_if_fail (store, MU_ERROR_INTERNAL); + g_return_val_if_fail (opts, MU_ERROR_INTERNAL); + g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_CFIND, + MU_ERROR_INTERNAL); + + if (!cfind_params_valid (opts)) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_IN_PARAMETERS, + "invalid parameters"); + return MU_ERROR_IN_PARAMETERS; + } + + return run_cmd_cfind (store, + opts->params[1], + opts->personal, + opts->after, + opts->format, + !opts->nocolor, + err); +} diff --git a/mu/mu-cmd-extract.c b/mu/mu-cmd-extract.c new file mode 100644 index 0000000..f0b90bc --- /dev/null +++ b/mu/mu-cmd-extract.c @@ -0,0 +1,428 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2010-2013 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include +#include + +#include "mu-msg.h" +#include "mu-msg-part.h" +#include "mu-cmd.h" +#include "utils/mu-util.h" +#include "utils/mu-str.h" + + +static gboolean +save_part (MuMsg *msg, const char *targetdir, guint partidx, MuConfig *opts) +{ + GError *err; + gchar *filepath; + gboolean rv; + MuMsgOptions msgopts; + + err = NULL; + rv = FALSE; + + msgopts = mu_config_get_msg_options (opts); + + filepath = mu_msg_part_get_path (msg, msgopts, targetdir, partidx, &err); + if (!filepath) + goto exit; + + if (!mu_msg_part_save (msg, msgopts, filepath, partidx, &err)) + goto exit; + + if (opts->play) + rv = mu_util_play (filepath, TRUE, FALSE, &err); + else + rv = TRUE; +exit: + if (err) { + g_warning ("error with MIME-part: %s", err->message); + g_clear_error (&err); + } + + g_free (filepath); + return rv; +} + + + +static gboolean +save_numbered_parts (MuMsg *msg, MuConfig *opts) +{ + gboolean rv; + char **parts, **cur; + + parts = g_strsplit (opts->parts, ",", 0); + + for (rv = TRUE, cur = parts; cur && *cur; ++cur) { + + unsigned idx; + int i; + char *endptr; + + idx = (unsigned)(i = strtol (*cur, &endptr, 10)); + if (i < 0 || *cur == endptr) { + g_warning ("invalid MIME-part index '%s'", *cur); + rv = FALSE; + break; + } + + if (!save_part (msg, opts->targetdir, idx, opts)) { + g_warning ("failed to save MIME-part %d", idx); + rv = FALSE; + break; + } + } + + g_strfreev (parts); + return rv; +} + +static GRegex* +anchored_regex (const char* pattern) +{ + GRegex *rx; + GError *err; + gchar *anchored; + + + anchored = g_strdup_printf + ("%s%s%s", + pattern[0] == '^' ? "" : "^", + pattern, + pattern[strlen(pattern)-1] == '$' ? "" : "$"); + + err = NULL; + rx = g_regex_new (anchored, G_REGEX_CASELESS|G_REGEX_OPTIMIZE, 0, + &err); + g_free (anchored); + + if (!rx) { + g_warning ("error in regular expression '%s': %s", + pattern, err->message ? err->message : "error"); + g_error_free (err); + return NULL; + } + + return rx; +} + + +static gboolean +save_part_with_filename (MuMsg *msg, const char *pattern, MuConfig *opts) +{ + GSList *lst, *cur; + GRegex *rx; + gboolean rv; + MuMsgOptions msgopts; + + msgopts = mu_config_get_msg_options (opts); + + /* 'anchor' the pattern with '^...$' if not already */ + rx = anchored_regex (pattern); + if (!rx) + return FALSE; + + lst = mu_msg_find_files (msg, msgopts, rx); + g_regex_unref (rx); + if (!lst) { + g_warning ("no matching attachments found"); + return FALSE; + } + + for (cur = lst, rv = TRUE; cur; cur = g_slist_next (cur)) + rv = rv && save_part (msg, opts->targetdir, + GPOINTER_TO_UINT(cur->data), opts); + g_slist_free (lst); + + return rv; +} + +struct _SaveData { + gboolean result; + guint saved_num; + MuConfig *opts; +}; +typedef struct _SaveData SaveData; + + +static gboolean +ignore_part (MuMsg *msg, MuMsgPart *part, SaveData *sd) +{ + /* something went wrong somewhere; stop */ + if (!sd->result) + return TRUE; + + /* only consider leaf parts */ + if (!(part->part_type & MU_MSG_PART_TYPE_LEAF)) + return TRUE; + + /* filter out non-attachments? */ + if (!sd->opts->save_all && + !(mu_msg_part_maybe_attachment (part))) + return TRUE; + + return FALSE; +} + + +static void +save_part_if (MuMsg *msg, MuMsgPart *part, SaveData *sd) +{ + gchar *filepath; + gboolean rv; + GError *err; + MuMsgOptions msgopts; + + if (ignore_part (msg, part, sd)) + return; + + rv = FALSE; + filepath = NULL; + err = NULL; + + msgopts = mu_config_get_msg_options (sd->opts); + filepath = mu_msg_part_get_path (msg, msgopts, + sd->opts->targetdir, + part->index, &err); + if (!filepath) + goto exit; + + if (!mu_msg_part_save (msg, msgopts, filepath, part->index, &err)) + goto exit; + + if (sd->opts->play) + rv = mu_util_play (filepath, TRUE, FALSE, &err); + else + rv = TRUE; + + ++sd->saved_num; +exit: + if (err) + g_warning ("error saving MIME part: %s", err->message); + + g_free (filepath); + g_clear_error (&err); + + sd->result = rv; + +} + +static gboolean +save_certain_parts (MuMsg *msg, MuConfig *opts) +{ + SaveData sd; + MuMsgOptions msgopts; + + sd.result = TRUE; + sd.saved_num = 0; + sd.opts = opts; + + msgopts = mu_config_get_msg_options (opts); + mu_msg_part_foreach (msg, msgopts, + (MuMsgPartForeachFunc)save_part_if, &sd); + + if (sd.saved_num == 0) { + g_warning ("no %s extracted from this message", + opts->save_attachments ? "attachments" : "parts"); + sd.result = FALSE; + } + + return sd.result; +} + + +static gboolean +save_parts (const char *path, const char *filename, MuConfig *opts) +{ + MuMsg* msg; + gboolean rv; + GError *err; + + err = NULL; + msg = mu_msg_new_from_file (path, NULL, &err); + if (!msg) { + if (err) { + g_warning ("error: %s", err->message); + g_error_free (err); + } + return FALSE; + } + + /* note, mu_cmd_extract already checks whether what's in opts + * is somewhat, so no need for extensive checking here */ + + /* should we save some explicit parts? */ + if (opts->parts) + rv = save_numbered_parts (msg, opts); + else if (filename) + rv = save_part_with_filename (msg, filename, opts); + else + rv = save_certain_parts (msg, opts); + + mu_msg_unref (msg); + + return rv; +} + +#define color_maybe(C) do{ if (color) fputs ((C),stdout);}while(0) + +static const char* +disp_str (MuMsgPartType ptype) +{ + if (ptype & MU_MSG_PART_TYPE_ATTACHMENT) + return "attach"; + if (ptype & MU_MSG_PART_TYPE_INLINE) + return "inline"; + return ""; +} + +static void +each_part_show (MuMsg *msg, MuMsgPart *part, gboolean color) +{ + /* index */ + g_print (" %u ", part->index); + + /* filename */ + color_maybe (MU_COLOR_GREEN); { + gchar *fname; + fname = mu_msg_part_get_filename (part, FALSE); + mu_util_fputs_encoded (fname ? fname : "", stdout); + g_free (fname); + } + /* content-type */ + color_maybe (MU_COLOR_BLUE); + mu_util_print_encoded ( + " %s/%s ", + part->type ? part->type : "", + part->subtype ? part->subtype : ""); + + /* /\* disposition *\/ */ + color_maybe (MU_COLOR_MAGENTA); + mu_util_print_encoded ("[%s]", disp_str(part->part_type)); + + /* size */ + if (part->size > 0) { + color_maybe (MU_COLOR_CYAN); + g_print (" (%s)", mu_str_size_s (part->size)); + } + + color_maybe (MU_COLOR_DEFAULT); + fputs ("\n", stdout); +} + + +static gboolean +show_parts (const char* path, MuConfig *opts, GError **err) +{ + MuMsg *msg; + MuMsgOptions msgopts; + + msg = mu_msg_new_from_file (path, NULL, err); + if (!msg) + return FALSE; + + msgopts = mu_config_get_msg_options (opts); + + /* TODO: update this for crypto */ + g_print ("MIME-parts in this message:\n"); + mu_msg_part_foreach + (msg, msgopts, + (MuMsgPartForeachFunc)each_part_show, + GUINT_TO_POINTER(!opts->nocolor)); + + mu_msg_unref (msg); + + return TRUE; + +} + + +static gboolean +check_params (MuConfig *opts, GError **err) +{ + size_t param_num; + + param_num = mu_config_param_num (opts); + + if (param_num < 2) { + mu_util_g_set_error + (err, MU_ERROR_IN_PARAMETERS, + "parameters missing"); + return FALSE; + } + + if (opts->save_attachments || opts->save_all) + if (opts->parts || param_num == 3) { + mu_util_g_set_error + (err, MU_ERROR_IN_PARAMETERS, + "--save-attachments and --save-all don't " + "accept a filename pattern or --parts"); + return FALSE; + } + + if (opts->save_attachments && opts->save_all) { + mu_util_g_set_error + (err, MU_ERROR_IN_PARAMETERS, + "only one of --save-attachments and" + " --save-all is allowed"); + return FALSE; + } + + return TRUE; +} + +MuError +mu_cmd_extract (MuConfig *opts, GError **err) +{ + int rv; + + g_return_val_if_fail (opts, MU_ERROR_INTERNAL); + g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_EXTRACT, + MU_ERROR_INTERNAL); + + if (!check_params (opts, err)) + return MU_ERROR_IN_PARAMETERS; + + if (!opts->params[2] && !opts->parts && + !opts->save_attachments && !opts->save_all) + /* show, don't save */ + rv = show_parts (opts->params[1], opts, err); + else { + rv = mu_util_check_dir(opts->targetdir, FALSE, TRUE); + if (!rv) + mu_util_g_set_error + (err, MU_ERROR_FILE_CANNOT_WRITE, + "target '%s' is not a writable directory", + opts->targetdir); + else + rv = save_parts (opts->params[1], + opts->params[2], + opts); /* save */ + } + + return rv ? MU_OK : MU_ERROR; +} diff --git a/mu/mu-cmd-find.c b/mu/mu-cmd-find.c new file mode 100644 index 0000000..47e2d13 --- /dev/null +++ b/mu/mu-cmd-find.c @@ -0,0 +1,768 @@ +/* +** Copyright (C) 2008-2013 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include +#include +#include +#include +#include +#include + +#include "mu-msg.h" +#include "mu-maildir.h" +#include "mu-index.h" +#include "mu-query.h" +#include "mu-msg-iter.h" +#include "mu-bookmarks.h" +#include "mu-runtime.h" + +#include "utils/mu-util.h" +#include "utils/mu-str.h" +#include "utils/mu-date.h" + +#include "mu-cmd.h" +#include "mu-threader.h" + +#ifdef HAVE_JSON_GLIB +#include +#endif /*HAVE_JSON_GLIB*/ + +typedef gboolean (OutputFunc) (MuMsg *msg, MuMsgIter *iter, + MuConfig *opts, GError **err); + +static gboolean +print_internal (MuQuery *query, const gchar *expr, gboolean xapian, + gboolean warn, GError **err) +{ + char *str; + + if (xapian) + str = mu_query_internal_xapian (query, expr, err); + else + str = mu_query_internal (query, expr, warn, err); + + if (str) { + g_print ("%s\n", str); + g_free (str); + } + + return str != NULL; +} + + +/* returns MU_MSG_FIELD_ID_NONE if there is an error */ +static MuMsgFieldId +sort_field_from_string (const char* fieldstr, GError **err) +{ + MuMsgFieldId mfid; + + mfid = mu_msg_field_id_from_name (fieldstr, FALSE); + + /* not found? try a shortcut */ + if (mfid == MU_MSG_FIELD_ID_NONE && + strlen(fieldstr) == 1) + mfid = mu_msg_field_id_from_shortcut(fieldstr[0], + FALSE); + if (mfid == MU_MSG_FIELD_ID_NONE) + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_IN_PARAMETERS, + "not a valid sort field: '%s'\n", fieldstr); + return mfid; +} + +static MuMsg* +get_message (MuMsgIter *iter, time_t after) +{ + MuMsg *msg; + + if (mu_msg_iter_is_done (iter)) + return NULL; + + msg = mu_msg_iter_get_msg_floating (iter); + if (!msg) + return NULL; /* error */ + + if (!mu_msg_is_readable (msg)) { + mu_msg_iter_next (iter); + return get_message (iter, after); + } + + if (after != 0 && after > mu_msg_get_timestamp (msg)) { + mu_msg_iter_next (iter); + return get_message (iter, after); + } + + return msg; +} + +static MuMsgIter* +run_query (MuQuery *xapian, const gchar *query, MuConfig *opts, GError **err) +{ + MuMsgIter *iter; + MuMsgFieldId sortid; + MuQueryFlags qflags; + + sortid = MU_MSG_FIELD_ID_NONE; + if (opts->sortfield) { + sortid = sort_field_from_string (opts->sortfield, err); + if (sortid == MU_MSG_FIELD_ID_NONE) /* error occurred? */ + return FALSE; + } + + qflags = MU_QUERY_FLAG_NONE; + if (opts->reverse) + qflags |= MU_QUERY_FLAG_DESCENDING; + if (opts->skip_dups) + qflags |= MU_QUERY_FLAG_SKIP_DUPS; + if (opts->include_related) + qflags |= MU_QUERY_FLAG_INCLUDE_RELATED; + if (opts->threads) + qflags |= MU_QUERY_FLAG_THREADS; + + iter = mu_query_run (xapian, query, sortid, opts->maxnum, qflags, err); + return iter; +} + +static gboolean +exec_cmd (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err) +{ + gint status; + char *cmdline, *escpath; + gboolean rv; + + escpath = g_shell_quote (mu_msg_get_path (msg)); + cmdline = g_strdup_printf ("%s %s", opts->exec, escpath); + + rv = g_spawn_command_line_sync (cmdline, NULL, NULL, &status, err); + + g_free (cmdline); + g_free (escpath); + + return rv; +} + +static gchar* +resolve_bookmark (MuConfig *opts, GError **err) +{ + MuBookmarks *bm; + char* val; + const gchar *bmfile; + + bmfile = mu_runtime_path (MU_RUNTIME_PATH_BOOKMARKS); + bm = mu_bookmarks_new (bmfile); + if (!bm) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE_CANNOT_OPEN, + "failed to open bookmarks file '%s'", bmfile); + return FALSE; + } + + val = (gchar*)mu_bookmarks_lookup (bm, opts->bookmark); + if (!val) + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_NO_MATCHES, + "bookmark '%s' not found", opts->bookmark); + else + val = g_strdup (val); + + mu_bookmarks_destroy (bm); + return val; +} + +static gchar* +get_query (MuConfig *opts, GError **err) +{ + gchar *query, *bookmarkval; + + /* params[0] is 'find', actual search params start with [1] */ + if (!opts->bookmark && !opts->params[1]) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_IN_PARAMETERS, + "error in parameters"); + return NULL; + } + + bookmarkval = NULL; + if (opts->bookmark) { + bookmarkval = resolve_bookmark (opts, err); + if (!bookmarkval) + return NULL; + } + + query = g_strjoinv (" ", &opts->params[1]); + if (bookmarkval) { + gchar *tmp; + tmp = g_strdup_printf ("%s %s", bookmarkval, query); + g_free (query); + query = tmp; + } + + g_free (bookmarkval); + + return query; +} + +static MuQuery* +get_query_obj (MuStore *store, GError **err) +{ + MuQuery *mquery; + unsigned count; + + count = mu_store_count (store, err); + + if (count == (unsigned)-1) + return NULL; + + if (count == 0) { + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN_NEEDS_REINDEX, + "the database is empty"); + return NULL; + } + + mquery = mu_query_new (store, err); + if (!mquery) + return NULL; + + return mquery; +} + +static gboolean +prepare_links (MuConfig *opts, GError **err) +{ + /* note, mu_maildir_mkdir simply ignores whatever part of the + * mail dir already exists */ + + if (!mu_maildir_mkdir (opts->linksdir, 0700, TRUE, err)) { + mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_MKDIR, + "error creating %s", opts->linksdir); + return FALSE; + } + + if (opts->clearlinks && + !mu_maildir_clear_links (opts->linksdir, err)) { + mu_util_g_set_error (err, MU_ERROR_FILE, + "error clearing links under %s", + opts->linksdir); + return FALSE; + } + + return TRUE; +} + +static gboolean +output_link (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err) +{ + if (mu_msg_iter_is_first (iter) && !prepare_links (opts, err)) + return FALSE; + + return mu_maildir_link (mu_msg_get_path (msg), + opts->linksdir, err); +} + +static void +ansi_color_maybe (MuMsgFieldId mfid, gboolean color) +{ + const char* ansi; + + if (!color) + return; /* nothing to do */ + + switch (mfid) { + + case MU_MSG_FIELD_ID_FROM: + ansi = MU_COLOR_CYAN; break; + + case MU_MSG_FIELD_ID_TO: + case MU_MSG_FIELD_ID_CC: + case MU_MSG_FIELD_ID_BCC: + ansi = MU_COLOR_BLUE; break; + + case MU_MSG_FIELD_ID_SUBJECT: + ansi = MU_COLOR_GREEN; break; + + case MU_MSG_FIELD_ID_DATE: + ansi = MU_COLOR_MAGENTA; break; + + default: + if (mu_msg_field_type(mfid) == MU_MSG_FIELD_TYPE_STRING) + ansi = MU_COLOR_YELLOW; + else + ansi = MU_COLOR_RED; + } + + fputs (ansi, stdout); +} + +static void +ansi_reset_maybe (MuMsgFieldId mfid, gboolean color) +{ + if (!color) + return; /* nothing to do */ + + fputs (MU_COLOR_DEFAULT, stdout); + +} + +static const char* +field_string_list (MuMsg *msg, MuMsgFieldId mfid) +{ + char *str; + const GSList *lst; + static char buf[80]; + + lst = mu_msg_get_field_string_list (msg, mfid); + if (!lst) + return NULL; + + str = mu_str_from_list (lst, ','); + if (str) { + strncpy (buf, str, sizeof(buf)-1); + buf[sizeof(buf)-1]='\0'; + g_free (str); + return buf; + } + + return NULL; +} + +static const char* +display_field (MuMsg *msg, MuMsgFieldId mfid) +{ + gint64 val; + + switch (mu_msg_field_type(mfid)) { + case MU_MSG_FIELD_TYPE_STRING: { + const gchar *str; + str = mu_msg_get_field_string (msg, mfid); + return str ? str : ""; + } + case MU_MSG_FIELD_TYPE_INT: + + if (mfid == MU_MSG_FIELD_ID_PRIO) { + val = mu_msg_get_field_numeric (msg, mfid); + return mu_msg_prio_name ((MuMsgPrio)val); + } else if (mfid == MU_MSG_FIELD_ID_FLAGS) { + val = mu_msg_get_field_numeric (msg, mfid); + return mu_str_flags_s ((MuFlags)val); + } else /* as string */ + return mu_msg_get_field_string (msg, mfid); + + case MU_MSG_FIELD_TYPE_TIME_T: + val = mu_msg_get_field_numeric (msg, mfid); + return mu_date_str_s ("%c", (time_t)val); + + case MU_MSG_FIELD_TYPE_BYTESIZE: + val = mu_msg_get_field_numeric (msg, mfid); + return mu_str_size_s ((unsigned)val); + case MU_MSG_FIELD_TYPE_STRING_LIST: { + const char *str; + str = field_string_list (msg, mfid); + return str ? str : ""; + } + default: + g_return_val_if_reached (NULL); + } +} + +static void +print_summary (MuMsg *msg, MuConfig *opts) +{ + const char* body; + char *summ; + MuMsgOptions msgopts; + + msgopts = mu_config_get_msg_options (opts); + body = mu_msg_get_body_text(msg, msgopts); + + if (body) + summ = mu_str_summarize (body, (unsigned)opts->summary_len); + else + summ = NULL; + + g_print ("Summary: "); + mu_util_fputs_encoded (summ ? summ : "", stdout); + g_print ("\n"); + + g_free (summ); +} + +static void +thread_indent (MuMsgIter *iter) +{ + const MuMsgIterThreadInfo *ti; + const char* threadpath; + int i; + gboolean is_root, first_child, empty_parent, is_dup; + + ti = mu_msg_iter_get_thread_info (iter); + if (!ti) { + g_warning ("cannot get thread-info for message %u", + mu_msg_iter_get_docid (iter)); + return; + } + + threadpath = ti->threadpath; + /* fputs (threadpath, stdout); */ + /* fputs (" ", stdout); */ + + is_root = ti->prop & MU_MSG_ITER_THREAD_PROP_ROOT; + first_child = ti->prop & MU_MSG_ITER_THREAD_PROP_FIRST_CHILD; + empty_parent = ti->prop & MU_MSG_ITER_THREAD_PROP_EMPTY_PARENT; + is_dup = ti->prop & MU_MSG_ITER_THREAD_PROP_DUP; + + /* FIXME: count the colons... */ + for (i = 0; *threadpath; ++threadpath) + i += (*threadpath == ':') ? 1 : 0; + + /* indent */ + while (i --> 0) + fputs (" ", stdout); + + if (!is_root) { + fputs (first_child ? "`" : "|", stdout); + fputs (empty_parent ? "*> " : is_dup ? "=> " : "-> ", stdout); + } +} + +static void +output_plain_fields (MuMsg *msg, const char *fields, + gboolean color, gboolean threads) +{ + const char* myfields; + int nonempty; + + g_return_if_fail (fields); + + for (myfields = fields, nonempty = 0; *myfields; ++myfields) { + + MuMsgFieldId mfid; + mfid = mu_msg_field_id_from_shortcut (*myfields, FALSE); + + if (mfid == MU_MSG_FIELD_ID_NONE || + (!mu_msg_field_xapian_value (mfid) && + !mu_msg_field_xapian_contact (mfid))) + nonempty += printf ("%c", *myfields); + + else { + ansi_color_maybe (mfid, color); + nonempty += mu_util_fputs_encoded + (display_field (msg, mfid), stdout); + ansi_reset_maybe (mfid, color); + } + } + + if (nonempty) + fputs ("\n", stdout); +} + +static gboolean +output_plain (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err) +{ + /* we reuse the color (whatever that may be) + * for message-priority for threads, too */ + ansi_color_maybe (MU_MSG_FIELD_ID_PRIO, !opts->nocolor); + if (opts->threads) + thread_indent (iter); + + output_plain_fields (msg, opts->fields, !opts->nocolor, opts->threads); + + if (opts->summary_len > 0) + print_summary (msg, opts); + + return TRUE; +} + +static gboolean +output_sexp (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err) +{ + char *sexp; + const MuMsgIterThreadInfo *ti; + + ti = opts->threads ? mu_msg_iter_get_thread_info (iter) : NULL; + sexp = mu_msg_to_sexp (msg, mu_msg_iter_get_docid (iter), + ti, MU_MSG_OPTION_HEADERS_ONLY); + fputs (sexp, stdout); + g_free (sexp); + + return TRUE; +} + +static gboolean +output_json (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err) +{ +#ifdef HAVE_JSON_GLIB + JsonNode *node; + const MuMsgIterThreadInfo *ti; + char *s; + + if (mu_msg_iter_is_first(iter)) + g_print ("[\n"); + + ti = opts->threads ? mu_msg_iter_get_thread_info (iter) : NULL; + node = mu_msg_to_json (msg, mu_msg_iter_get_docid (iter), + ti, MU_MSG_OPTION_HEADERS_ONLY); + + s = json_to_string (node, TRUE); + json_node_free (node); + + fputs (s, stdout); + g_free (s); + + if (mu_msg_iter_is_last(iter)) + fputs("]\n", stdout); + else + fputs (",\n", stdout); + + return TRUE; +#else + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_IN_PARAMETERS, + "this mu was built without json support"); + return FALSE; +#endif /*HAVE_JSON_GLIB*/ + +} + +static void +print_attr_xml (const char* elm, const char *str) +{ + gchar *esc; + + if (mu_str_is_empty(str)) + return; /* empty: don't include */ + + esc = g_markup_escape_text (str, -1); + g_print ("\t\t<%s>%s\n", elm, esc, elm); + g_free (esc); +} + +static gboolean +output_xml (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err) +{ + if (mu_msg_iter_is_first(iter)) { + g_print ("\n"); + g_print ("\n"); + } + + g_print ("\t\n"); + print_attr_xml ("from", mu_msg_get_from (msg)); + print_attr_xml ("to", mu_msg_get_to (msg)); + print_attr_xml ("cc", mu_msg_get_cc (msg)); + print_attr_xml ("subject", mu_msg_get_subject (msg)); + g_print ("\t\t%u\n", + (unsigned)mu_msg_get_date (msg)); + g_print ("\t\t%u\n", (unsigned)mu_msg_get_size (msg)); + print_attr_xml ("msgid", mu_msg_get_msgid (msg)); + print_attr_xml ("path", mu_msg_get_path (msg)); + print_attr_xml ("maildir", mu_msg_get_maildir (msg)); + g_print ("\t\n"); + + if (mu_msg_iter_is_last(iter)) + g_print ("\n"); + + return TRUE; +} + +static OutputFunc* +get_output_func (MuConfig *opts, GError **err) +{ + switch (opts->format) { + case MU_CONFIG_FORMAT_LINKS: return output_link; + case MU_CONFIG_FORMAT_EXEC: return exec_cmd; + case MU_CONFIG_FORMAT_PLAIN: return output_plain; + case MU_CONFIG_FORMAT_XML: return output_xml; + case MU_CONFIG_FORMAT_SEXP: return output_sexp; + case MU_CONFIG_FORMAT_JSON: return output_json; + + default: + g_return_val_if_reached (NULL); + return NULL; + } +} + +static gboolean +output_query_results (MuMsgIter *iter, MuConfig *opts, GError **err) +{ + int count; + gboolean rv; + OutputFunc *output_func; + + output_func = get_output_func (opts, err); + if (!output_func) + return FALSE; + + for (count = 0, rv = TRUE; !mu_msg_iter_is_done(iter); + mu_msg_iter_next (iter)) { + + MuMsg *msg; + + if (count == opts->maxnum) + break; + msg = get_message (iter, opts->after); + if (!msg) + break; + /* { */ + /* const char* thread_id; */ + /* thread_id = mu_msg_iter_get_thread_id (iter); */ + /* g_print ("%s ", thread_id ? thread_id : ""); */ + + /* } */ + rv = output_func (msg, iter, opts, err); + if (!rv) + break; + else + ++count; + } + + if (rv && count == 0) { + mu_util_g_set_error (err, MU_ERROR_NO_MATCHES, + "no matches for search expression"); + return FALSE; + } + + return rv; +} + +static gboolean +process_query (MuQuery *xapian, const gchar *query, MuConfig *opts, GError **err) +{ + MuMsgIter *iter; + gboolean rv; + + iter = run_query (xapian, query, opts, err); + if (!iter) + return FALSE; + + rv = output_query_results (iter, opts, err); + mu_msg_iter_destroy (iter); + + return rv; +} + +static gboolean +execute_find (MuStore *store, MuConfig *opts, GError **err) +{ + char *query_str; + MuQuery *oracle; + gboolean rv; + + oracle = get_query_obj (store, err); + if (!oracle) + return FALSE; + + query_str = get_query (opts, err); + if (!query_str) { + mu_query_destroy (oracle); + return FALSE; + } + + if (opts->format == MU_CONFIG_FORMAT_XQUERY) + rv = print_internal (oracle, query_str, TRUE, FALSE, err); + else if (opts->format == MU_CONFIG_FORMAT_MQUERY) + rv = print_internal (oracle, query_str, FALSE, + opts->verbose, err); + else + rv = process_query (oracle, query_str, opts, err); + + mu_query_destroy (oracle); + g_free (query_str); + + return rv; +} + +static gboolean +format_params_valid (MuConfig *opts, GError **err) +{ + switch (opts->format) { + case MU_CONFIG_FORMAT_EXEC: + break; + case MU_CONFIG_FORMAT_PLAIN: + case MU_CONFIG_FORMAT_SEXP: + case MU_CONFIG_FORMAT_JSON: + case MU_CONFIG_FORMAT_LINKS: + case MU_CONFIG_FORMAT_XML: + case MU_CONFIG_FORMAT_XQUERY: + case MU_CONFIG_FORMAT_MQUERY: + if (opts->exec) { + mu_util_g_set_error + (err, MU_ERROR_IN_PARAMETERS, + "--exec and --format cannot be combined"); + return FALSE; + } + break; + default: mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "invalid output format %s", + opts->formatstr ? opts->formatstr : ""); + return FALSE; + } + + if (opts->format == MU_CONFIG_FORMAT_LINKS && !opts->linksdir) { + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "missing --linksdir argument"); + return FALSE; + } + + if (opts->linksdir && opts->format != MU_CONFIG_FORMAT_LINKS) { + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "--linksdir is only valid with --format=links"); + return FALSE; + } + + return TRUE; +} + +static gboolean +query_params_valid (MuConfig *opts, GError **err) +{ + const gchar *xpath; + + if (!opts->params[1]) { + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "missing query"); + return FALSE; + } + + xpath = mu_runtime_path (MU_RUNTIME_PATH_XAPIANDB); + if (mu_util_check_dir (xpath, TRUE, FALSE)) + return TRUE; + + mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_READ, + "'%s' is not a readable Xapian directory", + xpath); + return FALSE; +} + +MuError +mu_cmd_find (MuStore *store, MuConfig *opts, GError **err) +{ + g_return_val_if_fail (opts, MU_ERROR_INTERNAL); + g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_FIND, + MU_ERROR_INTERNAL); + + if (opts->exec) + opts->format = MU_CONFIG_FORMAT_EXEC; /* pseudo format */ + + if (!query_params_valid (opts, err) || + !format_params_valid(opts, err)) + return MU_G_ERROR_CODE (err); + + if (!execute_find (store, opts, err)) + return MU_G_ERROR_CODE(err); + else + return MU_OK; +} diff --git a/mu/mu-cmd-index.c b/mu/mu-cmd-index.c new file mode 100644 index 0000000..5508463 --- /dev/null +++ b/mu/mu-cmd-index.c @@ -0,0 +1,318 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2008-2016 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include "mu-cmd.h" + +#include +#include +#include +#include +#include + +#include "mu-msg.h" +#include "mu-index.h" +#include "mu-store.hh" +#include "mu-runtime.h" + +#include "utils/mu-util.h" +#include "utils/mu-log.h" + +static gboolean MU_CAUGHT_SIGNAL; + +static void +sig_handler (int sig) +{ + if (!MU_CAUGHT_SIGNAL && sig == SIGINT) { /* Ctrl-C */ + g_print ("\n"); + g_warning ("shutting down gracefully, " + "press again to kill immediately"); + } + + MU_CAUGHT_SIGNAL = TRUE; +} + +static void +install_sig_handler (void) +{ + struct sigaction action; + int i, sigs[] = { SIGINT, SIGHUP, SIGTERM }; + + MU_CAUGHT_SIGNAL = FALSE; + + action.sa_handler = sig_handler; + sigemptyset(&action.sa_mask); + action.sa_flags = SA_RESETHAND; + + for (i = 0; i != G_N_ELEMENTS(sigs); ++i) + if (sigaction (sigs[i], &action, NULL) != 0) + g_critical ("set sigaction for %d failed: %s", + sigs[i], strerror (errno));; +} + + +static gboolean +check_params (MuConfig *opts, GError **err) +{ + /* param[0] == 'index' there should be no param[1] */ + if (opts->params[1]) { + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "unexpected parameter"); + return FALSE; + } + + if (opts->max_msg_size < 0) { + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "the maximum message size must >= 0"); + return FALSE; + } + + return TRUE; +} + +static MuError +index_msg_silent_cb (MuIndexStats* stats, void *user_data) +{ + return MU_CAUGHT_SIGNAL ? MU_STOP: MU_OK; +} + + + +static void +print_stats (MuIndexStats* stats, gboolean clear, gboolean color) +{ + const char *kars="-\\|/"; + char output[120]; + + static unsigned i = 0; + + if (clear) + fputs ("\r", stdout); + + if (color) + g_snprintf + (output, sizeof(output), + MU_COLOR_YELLOW "%c " MU_COLOR_DEFAULT + "processing mail; " + "processed: " MU_COLOR_GREEN "%u; " MU_COLOR_DEFAULT + "updated/new: " MU_COLOR_GREEN "%u" MU_COLOR_DEFAULT + ", cleaned-up: " MU_COLOR_GREEN "%u" MU_COLOR_DEFAULT, + (unsigned)kars[++i % 4], + (unsigned)stats->_processed, + (unsigned)stats->_updated, + (unsigned)stats->_cleaned_up); + else + g_snprintf + (output, sizeof(output), + "%c processing mail; processed: %u; " + "updated/new: %u, cleaned-up: %u", + (unsigned)kars[++i % 4], + (unsigned)stats->_processed, + (unsigned)stats->_updated, + (unsigned)stats->_cleaned_up); + + fputs (output, stdout); + fflush (stdout); +} + + +struct _IndexData { + gboolean color; +}; +typedef struct _IndexData IndexData; + + +static MuError +index_msg_cb (MuIndexStats* stats, IndexData *idata) +{ + if (stats->_processed % 75) + return MU_OK; + + print_stats (stats, TRUE, idata->color); + + return MU_CAUGHT_SIGNAL ? MU_STOP: MU_OK; +} + +static void +show_time (unsigned t, unsigned processed, gboolean color) +{ + if (color) { + if (t) + g_print ("elapsed: " + MU_COLOR_GREEN "%u" MU_COLOR_DEFAULT + " second(s), ~ " + MU_COLOR_GREEN "%u" MU_COLOR_DEFAULT + " msg/s", + t, processed/t); + else + g_print ("elapsed: " + MU_COLOR_GREEN "%u" MU_COLOR_DEFAULT + " second(s)", t); + } else { + if (t) + g_print ("elapsed: %u second(s), ~ %u msg/s", + t, processed/t); + else + g_print ("elapsed: %u second(s)", t); + } + + g_print ("\n"); +} + +/* when logging to console, print a newline before doing so; this + * makes it more clear when something happens during the + * indexing/cleanup progress output */ +#define newline_before_on() \ + mu_log_options_set(mu_log_options_get() | MU_LOG_OPTIONS_NEWLINE) +#define newline_before_off() \ + mu_log_options_set(mu_log_options_get() & ~MU_LOG_OPTIONS_NEWLINE) + +static MuError +cleanup_missing (MuIndex *midx, MuConfig *opts, MuIndexStats *stats, + GError **err) +{ + MuError rv; + time_t t; + IndexData idata; + gboolean show_progress; + + if (!opts->quiet) + g_print ("cleaning up messages [%s]\n", + mu_runtime_path (MU_RUNTIME_PATH_XAPIANDB)); + + show_progress = !opts->quiet && isatty(fileno(stdout)); + mu_index_stats_clear (stats); + + t = time (NULL); + idata.color = !opts->nocolor; + newline_before_on(); + rv = mu_index_cleanup + (midx, stats, + show_progress ? + (MuIndexCleanupDeleteCallback)index_msg_cb : + (MuIndexCleanupDeleteCallback)index_msg_silent_cb, + &idata, err); + newline_before_off(); + + if (!opts->quiet) { + print_stats (stats, TRUE, !opts->nocolor); + g_print ("\n"); + show_time ((unsigned)(time(NULL)-t),stats->_processed, + !opts->nocolor); + } + + return (rv == MU_OK || rv == MU_STOP) ? MU_OK: MU_G_ERROR_CODE(err); +} + +static MuError +cmd_index (MuIndex *midx, MuConfig *opts, MuIndexStats *stats, GError **err) +{ + IndexData idata; + MuError rv; + gboolean show_progress; + + show_progress = !opts->quiet && isatty(fileno(stdout)); + idata.color = !opts->nocolor; + + newline_before_on(); + + rv = mu_index_run (midx, + opts->rebuild, + opts->lazycheck, stats, + show_progress ? + (MuIndexMsgCallback)index_msg_cb : + (MuIndexMsgCallback)index_msg_silent_cb, + NULL, &idata); + newline_before_off(); + + if (rv == MU_OK || rv == MU_STOP) { + MU_WRITE_LOG ("index: processed: %u; updated/new: %u", + stats->_processed, stats->_updated); + } else + mu_util_g_set_error (err, rv, "error while indexing"); + + return rv; +} + + +static MuIndex* +init_mu_index (MuStore *store, MuConfig *opts, GError **err) +{ + MuIndex *midx; + + if (!check_params (opts, err)) + return NULL; + + midx = mu_index_new (store, err); + if (!midx) + return NULL; + + mu_index_set_max_msg_size (midx, opts->max_msg_size); + + return midx; +} + +MuError +mu_cmd_index (MuStore *store, MuConfig *opts, GError **err) +{ + MuIndex *midx; + MuIndexStats stats; + gboolean rv; + time_t t; + + g_return_val_if_fail (opts, FALSE); + g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_INDEX, + FALSE); + + /* create, and do error handling if needed */ + midx = init_mu_index (store, opts, err); + if (!midx) + return MU_G_ERROR_CODE(err); + + mu_index_stats_clear (&stats); + install_sig_handler (); + + if (!opts->quiet) + mu_store_print_info (store, opts->nocolor); + + t = time (NULL); + rv = cmd_index (midx, opts, &stats, err); + + if (rv == MU_OK && !opts->nocleanup) { + if (!opts->quiet) + g_print ("\n"); + rv = cleanup_missing (midx, opts, &stats, err); + } + + if (!opts->quiet) { + print_stats (&stats, TRUE, !opts->nocolor); + g_print ("\n"); + show_time ((unsigned)(time(NULL)-t), + stats._processed, !opts->nocolor); + } + + mu_index_destroy (midx); + + return rv; +} diff --git a/mu/mu-cmd-script.c b/mu/mu-cmd-script.c new file mode 100644 index 0000000..e1180c1 --- /dev/null +++ b/mu/mu-cmd-script.c @@ -0,0 +1,204 @@ +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ + +/* +** Copyright (C) 2012-2013 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include +#include +#include +#include +#include + +#include "mu-cmd.h" +#include "mu-script.h" +#include "mu-runtime.h" + + +#include "utils/mu-util.h" +#include "utils/mu-str.h" + + +#define MU_GUILE_EXT ".scm" +#define MU_GUILE_DESCR_PREFIX ";; INFO: " + +#define COL(C) ((color)?C:"") + +static void +print_script (const char *name, const char *oneline, const char *descr, + gboolean color, gboolean verbose) +{ + g_print ("%s%s%s%s%s%s%s%s", + verbose ? "\n" : " * ", + COL(MU_COLOR_GREEN),name,COL(MU_COLOR_DEFAULT), + oneline ? ": " : "", + COL(MU_COLOR_BLUE),oneline ? oneline :"",MU_COLOR_DEFAULT); + + if (verbose && descr) + g_print ("%s%s%s", + COL(MU_COLOR_MAGENTA),descr,COL(MU_COLOR_DEFAULT)); +} + + +static gboolean +print_scripts (GSList *scripts, gboolean color, + gboolean verbose, const char *rxstr, GError **err) +{ + GSList *cur; + const char *verb; + + if (!scripts) { + g_print ("No scripts available\n"); + return TRUE; /* not an error */ + } + + verb = verbose ? "" : " (use --verbose for details)"; + + if (rxstr) + g_print ("Available scripts matching '%s'%s:\n", + rxstr, verb); + else + g_print ("Available scripts%s:\n", verb); + + for (cur = scripts; cur; cur = g_slist_next (cur)) { + + MuScriptInfo *msi; + const char* descr, *oneline, *name; + + msi = (MuScriptInfo*)cur->data; + name = mu_script_info_name (msi); + oneline = mu_script_info_one_line (msi); + descr = mu_script_info_description (msi); + + /* if rxstr is provide, only consider matching scriptinfos */ + if (rxstr && !mu_script_info_matches_regex (msi, rxstr, err)) { + if (err && *err) + return FALSE; + continue; + } + + print_script (name, oneline, descr, color, verbose); + } + + return TRUE; +} + + +static GSList* +get_script_info_list (const char *muhome, GError **err) +{ + GSList *scripts, *userscripts, *last; + char *userpath; + + scripts = mu_script_get_script_info_list + (MU_SCRIPTS_DIR, MU_GUILE_EXT, + MU_GUILE_DESCR_PREFIX, + err); + + if (err && *err) + return NULL; + + userpath = g_strdup_printf ("%s%c%s", + muhome, G_DIR_SEPARATOR, "scripts"); + + /* is there are userdir for scripts? */ + if (!mu_util_check_dir (userpath, TRUE, FALSE)) { + g_free (userpath); + return scripts; + } + + /* append it to the list we already have */ + userscripts = mu_script_get_script_info_list (userpath, MU_GUILE_EXT, + MU_GUILE_DESCR_PREFIX, + err); + g_free (userpath); + + /* some error, return nothing */ + if (err && *err) { + mu_script_info_list_destroy (userscripts); + mu_script_info_list_destroy (scripts); + return NULL; + } + + /* append the user scripts */ + last = g_slist_last (scripts); + if (last) { + last->next = userscripts; + return scripts; + } else + return userscripts; /* apparently, scripts was NULL */ +} + + + +static gboolean +check_params (MuConfig *opts, GError **err) +{ + if (!mu_util_supports (MU_FEATURE_GUILE)) { + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "the 'script' command is not available " + "in this version of mu"); + return FALSE; + } + + return TRUE; +} + + +MuError +mu_cmd_script (MuConfig *opts, GError **err) +{ + MuScriptInfo *msi; + GSList *scripts; + + g_return_val_if_fail (opts, MU_ERROR_INTERNAL); + g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_SCRIPT, + MU_ERROR_INTERNAL); + + if (!check_params (opts, err)) + return MU_ERROR; + + scripts = get_script_info_list (opts->muhome, err); + if (err && *err) + goto leave; + + if (g_strcmp0 (opts->cmdstr, "script") == 0) { + print_scripts (scripts, !opts->nocolor, opts->verbose, + opts->script_params[0], err); + goto leave; + } + + msi = mu_script_find_script_with_name (scripts, opts->script); + if (!msi) { + mu_util_g_set_error (err, MU_ERROR_SCRIPT_NOT_FOUND, + "command or script not found"); + goto leave; + } + + /* do it! */ + mu_script_guile_run (msi, mu_runtime_path(MU_RUNTIME_PATH_CACHE), + opts->script_params, err); +leave: + /* this won't be reached, unless there is some error */ + mu_script_info_list_destroy (scripts); + return (err && *err) ? MU_ERROR : MU_OK; +} diff --git a/mu/mu-cmd-server.cc b/mu/mu-cmd-server.cc new file mode 100644 index 0000000..bce9025 --- /dev/null +++ b/mu/mu-cmd-server.cc @@ -0,0 +1,1334 @@ +/* +** Copyright (C) 2020 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include "config.h" +#include "mu-cmd.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "mu-runtime.h" +#include "mu-cmd.h" +#include "mu-maildir.h" +#include "mu-query.h" +#include "mu-index.h" +#include "mu-store.hh" +#include "mu-msg-part.h" +#include "mu-contacts.hh" + +#include "utils/mu-str.h" +#include "utils/mu-utils.hh" +#include "utils/mu-command-parser.hh" + +using namespace Mu; +using namespace Command; +using namespace Sexp; + +using DocId = unsigned; + +static std::atomic MuTerminate{false}; + +static void +sig_handler (int sig) +{ + MuTerminate = true; +} + +static void +install_sig_handler (void) +{ + struct sigaction action; + int i, sigs[] = { SIGINT, SIGHUP, SIGTERM, SIGPIPE }; + + MuTerminate = false; + + action.sa_handler = sig_handler; + sigemptyset(&action.sa_mask); + action.sa_flags = SA_RESETHAND; + + for (i = 0; i != G_N_ELEMENTS(sigs); ++i) + if (sigaction (sigs[i], &action, NULL) != 0) + g_critical ("set sigaction for %d failed: %s", + sigs[i], g_strerror (errno));; +} + + +/* + * Markers for/after the length cookie that precedes the expression we write to + * output. We use octal 376, 377 (ie, 0xfe, 0xff) as they will never occur in + * utf8 */ + + +#define COOKIE_PRE '\376' +#define COOKIE_POST '\377' + +static void G_GNUC_PRINTF(1, 2) +print_expr (const char* frm, ...) +{ + char *expr, *expr_orig; + va_list ap; + ssize_t rv; + size_t exprlen, lenlen; + char cookie[16]; + static int outfd = 0; + +#if defined(__CYGWIN__ )&& !defined (_WIN32) + const size_t writestep = 4096 * 16; + size_t bytestowrite = 0; +#endif + + if (outfd == 0) + outfd = fileno (stdout); + + expr = NULL; + + va_start (ap, frm); + exprlen = g_vasprintf (&expr, frm, ap); + va_end (ap); + + /* this cookie tells the frontend where to expect the next + * expression */ + + cookie[0] = COOKIE_PRE; + lenlen = sprintf(cookie + 1, "%x", + (unsigned)exprlen + 1); /* + 1 for \n */ + cookie[lenlen + 1] = COOKIE_POST; + + /* write the cookie, ie. + * COOKIE_PRE COOKIE_POST + */ + rv = write (outfd, cookie, lenlen + 2); + if (rv != -1) { + expr_orig = expr; +#if defined (__CYGWIN__) && !defined(_WIN32) + /* CYGWIN doesn't like big packets */ + while (exprlen > 0) { + bytestowrite = exprlen > writestep ? writestep : exprlen; + rv = write(outfd, expr, bytestowrite); + expr += bytestowrite; + exprlen -= bytestowrite; + } +#else + rv = write (outfd, expr, exprlen); +#endif + g_free (expr_orig); + } + if (rv != -1) + rv = write (outfd, "\n", 1); + if (rv == -1) { + g_critical ("%s: write() failed: %s", + __func__, g_strerror(errno)); + /* terminate ourselves */ + raise (SIGTERM); + } +} + + +G_GNUC_PRINTF(2,3) static MuError +print_error (MuError errcode, const char* frm, ...) +{ + char *msg; + va_list ap; + + va_start (ap, frm); + g_vasprintf (&msg, frm, ap); + va_end (ap); + + print_expr ("(:error %u :message %s)", errcode, quote(msg).c_str()); + g_free (msg); + + return errcode; +} + +static unsigned +print_sexps (MuMsgIter *iter, unsigned maxnum) +{ + unsigned u; + u = 0; + + while (!mu_msg_iter_is_done (iter) && u < maxnum) { + + MuMsg *msg; + msg = mu_msg_iter_get_msg_floating (iter); + + if (mu_msg_is_readable (msg)) { + char *sexp; + const MuMsgIterThreadInfo* ti; + ti = mu_msg_iter_get_thread_info (iter); + sexp = mu_msg_to_sexp (msg, + mu_msg_iter_get_docid (iter), + ti, MU_MSG_OPTION_HEADERS_ONLY); + print_expr ("%s", sexp); + g_free (sexp); + ++u; + } + mu_msg_iter_next (iter); + } + return u; +} + + +struct Context { + Context(){} + Context (MuConfig *opts) { + const auto dbpath{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB)}; + GError *gerr{}; + store = mu_store_new_writable (dbpath, NULL); + if (!store) { + const auto mu_init = format("mu init %s%s", + opts->muhome ? "--muhome=" : "", + opts->muhome ? opts->muhome : ""); + + if (gerr) { + if ((MuError)gerr->code == MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK) + print_error(MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK, + "mu database already locked; " + "some other mu running?"); + else + print_error((MuError)gerr->code, + "cannot open database @ %s:%s; already running? " + "if not, please try '%s", dbpath, + gerr->message ? gerr->message : "something went wrong", + mu_init.c_str()); + } else + print_error(MU_ERROR, + "cannot open database @ %s; already running? if not, please try '%s'", + dbpath, mu_init.c_str()); + + throw Mu::Error (Error::Code::Store, &gerr/*consumed*/, + "failed to open database @ %s; already running? if not, please try '%s'", + dbpath, mu_init.c_str()); + } + + query = mu_query_new (store, &gerr); + if (!query) + throw Error(Error::Code::Store, &gerr, "failed to create query"); + } + + ~Context() { + if (query) + mu_query_destroy(query); + if (store) { + mu_store_flush(store); + mu_store_unref(store); + } + } + + Context(const Context&) = delete; + + MuStore *store{}; + MuQuery *query{}; + bool do_quit{}; + + CommandMap command_map; +}; + + +static MuMsgOptions +message_options (const Parameters& params) +{ + const auto extract_images{get_bool_or(params, "extract-images", false)}; + const auto decrypt{get_bool_or(params, "decrypt", false)}; + const auto verify{get_bool_or(params, "verify", false)}; + + int opts{MU_MSG_OPTION_NONE}; + if (extract_images) + opts |= MU_MSG_OPTION_EXTRACT_IMAGES; + if (verify) + opts |= MU_MSG_OPTION_VERIFY | MU_MSG_OPTION_USE_AGENT; + if (decrypt) + opts |= MU_MSG_OPTION_DECRYPT | MU_MSG_OPTION_USE_AGENT; + + return (MuMsgOptions)opts; +} + +/* 'add' adds a message to the database, and takes two parameters: 'path', which + * is the full path to the message, and 'maildir', which is the maildir this + * message lives in (e.g. "/inbox"). response with an (:info ...) message with + * information about the newly added message (details: see code below) + */ +static void +add_handler (Context& context, const Parameters& params) +{ + const auto path{get_string_or(params, "path")}; + + GError *gerr{}; + const auto docid{mu_store_add_path (context.store, path.c_str(), &gerr)}; + if (docid == MU_STORE_INVALID_DOCID) + throw Error(Error::Code::Store, &gerr, "failed to add message at %s", + path.c_str()); + + print_expr ("(:info add :path %s :docid %u)", quote(path).c_str(), docid); + + auto msg{mu_store_get_msg(context.store, docid, &gerr)}; + if (!msg) + throw Error(Error::Code::Store, &gerr, "failed to get message at %s", + path.c_str()); + + auto sexp{mu_msg_to_sexp (msg, docid, NULL, MU_MSG_OPTION_VERIFY)}; + print_expr ("(:update %s :move nil)", sexp); + mu_msg_unref(msg); + g_free (sexp); +} + + +struct _PartInfo { + GSList *attlist; + MuMsgOptions opts; +}; +typedef struct _PartInfo PartInfo; + +static void +each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo) +{ + char *att, *cachefile; + + /* exclude things that don't look like proper attachments, + * unless they're images */ + if (!mu_msg_part_maybe_attachment(part)) + return; + + GError *gerr{}; + cachefile = mu_msg_part_save_temp (msg, + (MuMsgOptions)(pinfo->opts|MU_MSG_OPTION_OVERWRITE), + part->index, &gerr); + if (!cachefile) + throw Error (Error::Code::File, &gerr, "failed to save part"); + + att = g_strdup_printf ("(:file-name %s :mime-type \"%s/%s\")", + quote(cachefile).c_str(), part->type, part->subtype); + pinfo->attlist = g_slist_append (pinfo->attlist, att); + + g_free (cachefile); + +} + + +/* take the attachments of msg, save them as tmp files, and return + * as sexp (as a string) describing them + * + * ((:name :mime-type :disposition + * ) ... ) + * + */ +static gchar* +include_attachments (MuMsg *msg, MuMsgOptions opts) +{ + GSList *cur; + GString *gstr; + PartInfo pinfo; + + pinfo.attlist = NULL; + pinfo.opts = opts; + mu_msg_part_foreach (msg, opts, + (MuMsgPartForeachFunc)each_part, + &pinfo); + + gstr = g_string_sized_new (512); + gstr = g_string_append_c (gstr, '('); + for (cur = pinfo.attlist; cur; cur = g_slist_next (cur)) + g_string_append (gstr, (gchar*)cur->data); + gstr = g_string_append_c (gstr, ')'); + + mu_str_free_list (pinfo.attlist); + + return g_string_free (gstr, FALSE); +} + +enum { NEW, REPLY, FORWARD, EDIT, RESEND, INVALID_TYPE }; +static unsigned +compose_type (const char *typestr) +{ + if (g_str_equal (typestr, "reply")) + return REPLY; + else if (g_str_equal (typestr, "forward")) + return FORWARD; + else if (g_str_equal (typestr, "edit")) + return EDIT; + else if (g_str_equal (typestr, "resend")) + return RESEND; + else if (g_str_equal (typestr, "new")) + return NEW; + else + return INVALID_TYPE; +} + +/* 'compose' produces the un-changed *original* message sexp (ie., the message + * to reply to, forward or edit) for a new message to compose). It takes two + * parameters: 'type' with the compose type (either reply, forward or + * edit/resend), and 'docid' for the message to reply to. Note, type:new does + * not have an original message, and therefore does not need a docid + * + * In returns a (:compose [:original ] [:include] ) + * message (detals: see code below) + * + * Note ':include' t or nil determines whether to include attachments + */ +static void +compose_handler (Context& context, const Parameters& params) +{ + const auto typestr{get_symbol_or(params, "type")}; + const auto ctype{compose_type(typestr.c_str())}; + if (ctype == INVALID_TYPE) + throw Error(Error::Code::InvalidArgument, "invalid compose type"); + + // message optioss below checks extract-images / extract-encrypted + + char *sexp{}, *atts{}; + if (ctype == REPLY || ctype == FORWARD || ctype == EDIT || ctype == RESEND) { + + GError *gerr{}; + const unsigned docid{(unsigned)get_int_or(params, "docid")}; + auto msg{mu_store_get_msg (context.store, docid, &gerr)}; + if (!msg) + throw Error{Error::Code::Store, &gerr, "failed to get message %u", docid}; + + const auto opts{message_options(params)}; + sexp = mu_msg_to_sexp (msg, docid, NULL, opts); + atts = (ctype == FORWARD) ? include_attachments (msg, opts) : NULL; + mu_msg_unref (msg); + } + print_expr ("(:compose %s :original %s :include %s)", + typestr.c_str(), sexp ? sexp : "nil", atts ? atts : "nil"); + + g_free (sexp); + g_free (atts); +} + + +struct SexpData { + GString *gstr; + gboolean personal; + time_t last_seen; + gint64 tstamp; + size_t rank; +}; + + +static void +each_contact_sexp (const char* full_address, + const char *email, const char *name, gboolean personal, + time_t last_seen, unsigned freq, + gint64 tstamp, SexpData *sdata) +{ + sdata->rank++; + + /* since the last time we got some contacts */ + if (sdata->tstamp > tstamp) + return; + + /* (maybe) only include 'personal' contacts */ + if (sdata->personal && !personal) + return; + + /* only include newer-than-x contacts */ + if (sdata->last_seen > last_seen) + return; + + /* only include *real* e-mail addresses (ignore local + * addresses... there's little to complete there anyway...) */ + if (!email || !strstr (email, "@")) + return; + + g_string_append_printf (sdata->gstr, "(%s . %zu)\n", + quote(full_address).c_str(), sdata->rank); +} + +/** + * get all contacts as an s-expression + * + * @param self contacts object + * @param personal_only whether to restrict the list to 'personal' email + * addresses + * + * @return the sexp + */ +static char* +contacts_to_sexp (const MuContacts *contacts, bool personal, + int64_t last_seen, gint64 tstamp) +{ + + g_return_val_if_fail (contacts, NULL); + + SexpData sdata{}; + sdata.personal = personal; + sdata.last_seen = last_seen; + sdata.tstamp = tstamp; + sdata.rank = 0; + + /* make a guess for the initial size */ + sdata.gstr = g_string_sized_new (mu_contacts_count(contacts) * 128); + g_string_append (sdata.gstr, "(:contacts ("); + + const auto cutoff{g_get_monotonic_time()}; + mu_contacts_foreach (contacts, (MuContactsForeachFunc)each_contact_sexp, &sdata); + /* pass a string, elisp doesn't like 64-bit nums */ + g_string_append_printf (sdata.gstr, + ") :tstamp \"%" G_GINT64_FORMAT "\")", cutoff); + + return g_string_free (sdata.gstr, FALSE); +} + + +static void +contacts_handler (Context& context, const Parameters& params) +{ + const auto personal = get_bool_or(params, "personal"); + const auto afterstr = get_string_or(params, "after"); + const auto tstampstr = get_string_or(params, "tstamp"); + + const auto after{afterstr.empty() ? 0 : + g_ascii_strtoll(date_to_time_t_string(afterstr, true).c_str(), {}, 10)}; + const auto tstamp = g_ascii_strtoll (tstampstr.c_str(), NULL, 10); + + const auto contacts{mu_store_contacts(context.store)}; + if (!contacts) + throw Error{Error::Code::Internal, "failed to get contacts"}; + + /* dump the contacts cache as a giant sexp */ + auto sexp = contacts_to_sexp (contacts, personal, after, tstamp); + print_expr ("%s\n", sexp); + g_free (sexp); +} + +static void +save_part (MuMsg *msg, unsigned docid, unsigned index, + MuMsgOptions opts, const Parameters& params) +{ + const auto path{get_string_or(params, "path")}; + if (path.empty()) + throw Error{Error::Code::Command, "missing path"}; + + GError *gerr{}; + if (!mu_msg_part_save (msg, (MuMsgOptions)(opts | (int)MU_MSG_OPTION_OVERWRITE), + path.c_str(), index, &gerr)) + throw Error{Error::Code::File, &gerr, "failed to save part"}; + + print_expr ("(:info save :message %s)", quote(path + " has been saved").c_str()); +} + + +static void +open_part (MuMsg *msg, unsigned docid, unsigned index, MuMsgOptions opts) +{ + GError *gerr{}; + char *targetpath{mu_msg_part_get_cache_path (msg, opts, index, &gerr)}; + if (!targetpath) + throw Error{Error::Code::File, &gerr, "failed to get cache-path"}; + + if (!mu_msg_part_save (msg, (MuMsgOptions)(opts | MU_MSG_OPTION_USE_EXISTING), + targetpath, index, &gerr)) { + g_free(targetpath); + throw Error{Error::Code::File, &gerr, "failed to save to cache-path"}; + } + + if (!mu_util_play (targetpath, TRUE,/*allow local*/ + FALSE/*allow remote*/, &gerr)) { + g_free(targetpath); + throw Error{Error::Code::File, &gerr, "failed to play"}; + } + + print_expr ("(:info open :message %s)", + quote(std::string{targetpath} + " has been opened").c_str()); + g_free (targetpath); +} + +static void +temp_part (MuMsg *msg, unsigned docid, unsigned index, + MuMsgOptions opts, const Parameters& params) +{ + const auto what{get_symbol_or(params, "what")}; + if (what.empty()) + throw Error{Error::Code::Command, "missing 'what'"}; + + const auto param{get_string_or(params, "param")}; + + GError *gerr{}; + char *path{mu_msg_part_get_cache_path (msg, opts, index, &gerr)}; + if (!path) + throw Error{Error::Code::File, &gerr, "could not get cache path"}; + + if (!mu_msg_part_save (msg, (MuMsgOptions)(opts | MU_MSG_OPTION_USE_EXISTING), + path, index, &gerr)) { + g_free(path); + throw Error{Error::Code::File, &gerr, "saving failed"}; + } + + const auto qpath{quote(path)}; + g_free(path); + + if (!param.empty()) + print_expr ("(:temp %s" + " :what \"%s\"" + " :docid %u" + " :param %s" + ")", + qpath.c_str(), what.c_str(), docid, quote(param).c_str()); + else + print_expr ("(:temp %s :what \"%s\" :docid %u)", + qpath.c_str(), what.c_str(), docid); +} + + + +/* 'extract' extracts some mime part from a message */ +static void +extract_handler (Context& context, const Parameters& params) +{ + const auto docid{get_int_or(params, "docid")}; + const auto index{get_int_or(params, "index")}; + const auto opts{message_options(params)}; + + GError *gerr{}; + auto msg{mu_store_get_msg (context.store, docid, &gerr)}; + if (!msg) + throw Error{Error::Code::Store, "failed to get message"}; + + try { + const auto action{get_symbol_or(params, "action")}; + if (action == "save") + save_part (msg, docid, index, opts, params); + else if (action == "open") + open_part (msg, docid, index, opts); + else if (action == "temp") + temp_part (msg, docid, index, opts, params); + else { + throw Error{Error::Code::InvalidArgument, + "unknown action '%s'", action.c_str()}; + } + + } catch (...) { + mu_msg_unref (msg); + throw; + } +} + + +/* get a *list* of all messages with the given message id */ +static std::vector +docids_for_msgid (MuQuery *query, const std::string& msgid, size_t max=100) +{ + if (msgid.size() > MU_STORE_MAX_TERM_LENGTH - 1) { + throw Error(Error::Code::InvalidArgument, + "invalid message-id '%s'", msgid.c_str()); + } + + const auto xprefix{mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_MSGID)}; + /*XXX this is a bit dodgy */ + auto tmp{g_ascii_strdown(msgid.c_str(), -1)}; + auto rawq{g_strdup_printf("%c%s", xprefix, tmp)}; + g_free(tmp); + + GError *gerr{}; + auto iter{mu_query_run (query, rawq, MU_MSG_FIELD_ID_NONE, max, MU_QUERY_FLAG_RAW, &gerr)}; + g_free (rawq); + if (!iter) + throw Error(Error::Code::Store, &gerr, "failed to run msgid-query"); + if (mu_msg_iter_is_done (iter)) + throw Error(Error::Code::NotFound, + "could not find message(s) for msgid %s", msgid.c_str()); + std::vector docids; + do { + docids.emplace_back(mu_msg_iter_get_docid (iter)); + } while (mu_msg_iter_next (iter)); + mu_msg_iter_destroy (iter); + + return docids; +} + +/* + * creating a message object just to get a path seems a bit excessive maybe + * mu_store_get_path could be added if this turns out to be a problem + */ +static std::string +path_from_docid (MuStore *store, unsigned docid) +{ + GError *gerr{}; + auto msg{mu_store_get_msg (store, docid, &gerr)}; + if (!msg) + throw Error(Error::Code::Store, &gerr, "could not get message from store"); + + auto p{mu_msg_get_path(msg)}; + if (!p) { + mu_msg_unref(msg); + throw Error(Error::Code::Store, + "could not get path for message %u", docid); + } + + std::string msgpath{p}; + mu_msg_unref (msg); + + return msgpath; +} + + +static std::vector +determine_docids (MuQuery *query, const Parameters& params) +{ + auto docid{get_int_or(params, "docid", 0)}; + const auto msgid{get_string_or(params, "msgid")}; + + if ((docid == 0) == msgid.empty()) + throw Error(Error::Code::InvalidArgument, + "precisely one of docid and msgid must be specified"); + + if (docid != 0) + return { (unsigned)docid }; + else + return docids_for_msgid (query, msgid.c_str()); +} + + +static void +find_handler (Context& context, const Parameters& params) +{ + const auto query{get_string_or(params, "query")}; + const auto threads{get_bool_or(params, "threads", false)}; + const auto sortfieldstr{get_symbol_or(params, "sortfield")}; + const auto descending{get_bool_or(params, "descending", false)}; + const auto maxnum{get_int_or(params, "maxnum", -1/*unlimited*/)}; + const auto skip_dups{get_bool_or(params, "skip-dups", false)}; + const auto include_related{get_bool_or(params, "include-related", false)}; + + MuMsgFieldId sort_field{MU_MSG_FIELD_ID_NONE}; + if (!sortfieldstr.empty()) { + sort_field = mu_msg_field_id_from_name ( + sortfieldstr.c_str() + 1, FALSE); // skip ':' + if (sort_field == MU_MSG_FIELD_ID_NONE) + throw Error{Error::Code::InvalidArgument, "invalid sort field %s", + sortfieldstr.c_str()}; + } + + int qflags{MU_QUERY_FLAG_NONE/*UNREADABLE*/}; + if (descending) + qflags |= MU_QUERY_FLAG_DESCENDING; + if (skip_dups) + qflags |= MU_QUERY_FLAG_SKIP_DUPS; + if (include_related) + qflags |= MU_QUERY_FLAG_INCLUDE_RELATED; + if (threads) + qflags |= MU_QUERY_FLAG_THREADS; + + GError *gerr{}; + auto miter{mu_query_run(context.query, query.c_str(), sort_field, maxnum, + (MuQueryFlags)qflags, &gerr)}; + if (!miter) + throw Error(Error::Code::Query, &gerr, "failed to run query"); + + /* before sending new results, send an 'erase' message, so the frontend + * knows it should erase the headers buffer. this will ensure that the + * output of two finds will not be mixed. */ + print_expr ("(:erase t)"); + const auto foundnum{print_sexps (miter, maxnum)}; + print_expr ("(:found %u)", foundnum); + mu_msg_iter_destroy (miter); +} + + +static void +help_handler (Context& context, const Parameters& params) +{ + const auto command{get_symbol_or(params, "command", "")}; + const auto full{get_bool_or(params, "full")}; + + if (command.empty()) { + std::cout << ";; Commands are s-expressions of the form\n" + << ";; ( :param1 val1 :param2 val2 ...)\n" + << ";; For instance:\n;; (help :command quit)\n" + << ";; to get information about the 'quit' command\n;;\n"; + std::cout << ";; The following commands are available:\n"; + } + + std::vector names; + for (auto&& name_cmd: context.command_map) + names.emplace_back(name_cmd.first); + std::sort(names.begin(), names.end()); + + for (auto&& name: names) { + const auto& info{context.command_map.find(name)->second}; + + if (!command.empty() && name != command) + continue; + + if (!command.empty()) + std::cout << ";; " << format("%-10s -- %s\n", name.c_str(), + info.docstring.c_str()); + else + std::cout << ";; " << name.c_str() << ": " + << info.docstring.c_str() << '\n'; + + if (!full) + continue; + + for (auto&& argname: info.sorted_argnames()) { + const auto& arg{info.args.find(argname)}; + std::cout << ";; " + << format("%-17s : %-24s ", arg->first.c_str(), + to_string(arg->second).c_str()); + std::cout << " " << arg->second.docstring << "\n"; + } + std::cout << ";;\n"; + } +} + +static MuError +index_msg_cb (MuIndexStats *stats, void *user_data) +{ + if (MuTerminate) + return MU_STOP; + + if (stats->_processed % 1000) + return MU_OK; + + print_expr ("(:info index :status running " + ":processed %u :updated %u)", + stats->_processed, stats->_updated); + + return MU_OK; +} + + +static MuError +index_and_maybe_cleanup (MuIndex *index, bool cleanup, bool lazy_check) +{ + MuIndexStats stats{}, stats2{}; + mu_index_stats_clear (&stats); + auto rv = mu_index_run (index, FALSE, lazy_check, &stats, + index_msg_cb, NULL, NULL); + if (rv != MU_OK && rv != MU_STOP) + throw Error{Error::Code::Store, "indexing failed"}; + + mu_index_stats_clear (&stats2); + if (cleanup) { + GError *gerr{}; + rv = mu_index_cleanup (index, &stats2, NULL, NULL, &gerr); + if (rv != MU_OK && rv != MU_STOP) + throw Error{Error::Code::Store, &gerr, "cleanup failed"}; + } + + print_expr ("(:info index :status complete " + ":processed %u :updated %u :cleaned-up %u)", + stats._processed, stats._updated, stats2._cleaned_up); + + return rv; +} + + +static void +index_handler (Context& context, const Parameters& params) +{ + GError *gerr{}; + const auto cleanup{get_bool_or(params, "cleanup")}; + const auto lazy_check{get_bool_or(params, "lazy-check")}; + auto index{mu_index_new (context.store, &gerr)}; + if (!index) + throw Error(Error::Code::Index, &gerr, "failed to create index object"); + + try { + index_and_maybe_cleanup (index, cleanup, lazy_check); + } catch (...) { + mu_index_destroy(index); + throw; + } + mu_index_destroy(index); + mu_store_flush(context.store); +} + +static void +mkdir_handler (Context& context, const Parameters& params) +{ + const auto path{get_string_or(params, "path")}; + + GError *gerr{}; + if (!mu_maildir_mkdir(path.c_str(), 0755, FALSE, &gerr)) + throw Error{Error::Code::File, &gerr, "failed to create maildir"}; + + print_expr ("(:info mkdir :message \"%s has been created\")", path.c_str()); +} + + +static MuFlags +get_flags (const std::string& path, const std::string& flagstr) +{ + if (flagstr.empty()) + return MU_FLAG_NONE; /* ie., ignore flags */ + else { + /* if there's a '+' or '-' sign in the string, it must + * be a flag-delta */ + if (strstr (flagstr.c_str(), "+") || strstr (flagstr.c_str(), "-")) { + auto oldflags = mu_maildir_get_flags_from_path (path.c_str()); + return mu_flags_from_str_delta (flagstr.c_str(), oldflags, MU_FLAG_TYPE_ANY); + } else + return mu_flags_from_str (flagstr.c_str(), MU_FLAG_TYPE_ANY, + TRUE /*ignore invalid*/); + } +} + +static void +do_move (MuStore *store, DocId docid, MuMsg *msg, const std::string& maildirarg, + MuFlags flags, bool new_name, bool no_view) +{ + bool different_mdir{}; + auto maildir{maildirarg}; + if (maildir.empty()) { + maildir = mu_msg_get_maildir (msg); + different_mdir = FALSE; + } else /* are we moving to a different mdir, or is it just flags? */ + different_mdir = maildir != mu_msg_get_maildir(msg); + + GError* gerr{}; + if (!mu_msg_move_to_maildir (msg, maildir.c_str(), flags, TRUE, new_name, &gerr)) + throw Error{Error::Code::File, &gerr, "failed to move message"}; + + /* after mu_msg_move_to_maildir, path will be the *new* path, and flags and maildir fields + * will be updated as wel */ + auto rv = mu_store_update_msg (store, docid, msg, &gerr); + if (rv == MU_STORE_INVALID_DOCID) + throw Error{Error::Code::Store, &gerr, "failed to store updated message"}; + + char *sexp = mu_msg_to_sexp (msg, docid, NULL, MU_MSG_OPTION_VERIFY); + /* note, the :move t thing is a hint to the frontend that it + * could remove the particular header */ + print_expr ("(:update %s :move %s :maybe-view %s)", sexp, + different_mdir ? "t" : "nil", + no_view ? "nil" : "t"); + g_free (sexp); +} + +static void +move_docid (MuStore *store, DocId docid, const std::string& flagstr, + bool new_name, bool no_view) +{ + if (docid == MU_STORE_INVALID_DOCID) + throw Error{Error::Code::InvalidArgument, "invalid docid"}; + + GError *gerr{}; + auto msg{mu_store_get_msg (store, docid, &gerr)}; + + try { + if (!msg) + throw Error{Error::Code::Store, &gerr, "failed to get message from store"}; + + const auto flags = flagstr.empty() ? mu_msg_get_flags (msg) : + get_flags (mu_msg_get_path(msg), flagstr); + if (flags == MU_FLAG_INVALID) + throw Error{Error::Code::InvalidArgument, "invalid flags '%s'", flagstr.c_str()}; + + do_move (store, docid, msg, "", flags, new_name, no_view); + + } catch (...) { + if (msg) + mu_msg_unref (msg); + throw; + } + + mu_msg_unref (msg); +} + +/* + * 'move' moves a message to a different maildir and/or changes its + * flags. parameters are *either* a 'docid:' or 'msgid:' pointing to + * the message, a 'maildir:' for the target maildir, and a 'flags:' + * parameter for the new flags. + * + * returns an (:update ) + * + */ +static void +move_handler (Context& context, const Parameters& params) +{ + auto maildir{get_string_or(params, "maildir")}; + const auto flagstr{get_string_or(params, "flags")}; + const auto rename{get_bool_or (params, "rename")}; + const auto no_view{get_bool_or (params, "noupdate")}; + const auto docids{determine_docids (context.query, params)}; + + if (docids.size() > 1) { + if (!maildir.empty()) // ie. duplicate message-ids. + throw Mu::Error{Error::Code::Store, + "can't move multiple messages at the same time"}; + // multi. + for (auto&& docid: docids) + move_docid(context.store, docid, flagstr, rename, no_view); + return; + } + auto docid{docids.at(0)}; + + GError *gerr{}; + auto msg{mu_store_get_msg(context.store, docid, &gerr)}; + if (!msg) + throw Error{Error::Code::InvalidArgument, &gerr, "could not create message"}; + + /* if maildir was not specified, take the current one */ + if (maildir.empty()) + maildir = mu_msg_get_maildir (msg); + + /* determine the real target flags, which come from the flags-parameter + * we received (ie., flagstr), if any, plus the existing message + * flags. */ + MuFlags flags{}; + if (!flagstr.empty()) + flags = get_flags (mu_msg_get_path(msg), flagstr.c_str()); + else + flags = mu_msg_get_flags (msg); + + if (flags == MU_FLAG_INVALID) { + mu_msg_unref(msg); + throw Error{Error::Code::InvalidArgument, "invalid flagse"}; + } + + try { + do_move (context.store, docid, msg, maildir, flags, rename, no_view); + } catch (...) { + mu_msg_unref(msg); + throw; + } + + mu_msg_unref(msg); +} + +static void +ping_handler (Context& context, const Parameters& params) +{ + GError *gerr{}; + const auto storecount = mu_store_count(context.store, &gerr); + if (storecount == (unsigned)-1) + throw Error{Error::Code::Store, &gerr, "failed to read store"}; + + const auto queries = get_string_vec (params, "queries"); + const auto qresults = [&]() -> std::string { + if (queries.empty()) + return {}; + + std::string res{":queries ("}; + for (auto&& q: queries) { + const auto count{mu_query_count_run (context.query, q.c_str())}; + const auto unreadq{format("flag:unread AND (%s)", q.c_str())}; + const auto unread{mu_query_count_run (context.query, unreadq.c_str())}; + res += format("(:query %s :count %zu :unread %zu)", quote(q).c_str(), + count, unread); + } + return res + ")"; + }(); + + const auto personal = [&]() ->std::string { + auto addrs{mu_store_personal_addresses (context.store)}; + std::string res; + if (addrs && g_strv_length(addrs) != 0) { + res = ":personal-addresses ("; + for (int i = 0; addrs[i]; ++i) + res += quote(addrs[i]) + ' '; + res += ")"; + } + g_strfreev(addrs); + return res; + }(); + + print_expr ("(:pong \"mu\" :props (" + ":version \"" VERSION "\" " + "%s " + ":database-path %s " + ":root-maildir %s " + ":doccount %u " + "%s))", + personal.c_str(), + quote(mu_store_database_path(context.store)).c_str(), + quote(mu_store_root_maildir(context.store)).c_str(), + storecount, + qresults.c_str()); +} + +static void +quit_handler (Context& context, const Parameters& params) +{ + context.do_quit = true; +} + + +static void +remove_handler (Context& context, const Parameters& params) +{ + const auto docid{get_int_or(params, "docid")}; + const auto path{path_from_docid (context.store, docid)}; + + if (::unlink (path.c_str()) != 0 && errno != ENOENT) + throw Error(Error::Code::File, "could not delete %s: %s", + path.c_str(), strerror (errno)); + + if (!mu_store_remove_path (context.store, path.c_str())) + throw Error(Error::Code::Store, + "failed to remove message @ %s (%d) from store", + path.c_str(), docid); + + print_expr ("(:remove %u)", docid); +} + + +static void +sent_handler (Context& context, const Parameters& params) +{ + GError *gerr{}; + const auto path{get_string_or(params, "path")}; + const auto docid{mu_store_add_path(context.store, path.c_str(), &gerr)}; + if (docid == MU_STORE_INVALID_DOCID) + throw Error{Error::Code::Store, &gerr, "failed to add path"}; + + print_expr ("(:sent t :path %s :docid %u)", quote(path).c_str(), docid); +} + + +static void +view_handler (Context& context, const Parameters& params) +{ + DocId docid{}; + const auto path{get_string_or(params, "path")}; + + GError *gerr{}; + MuMsg *msg{}; + + if (!path.empty()) + msg = mu_msg_new_from_file (path.c_str(), NULL, &gerr); + else { + docid = determine_docids(context.query, params).at(0); + msg = mu_store_get_msg (context.store, docid, &gerr); + } + + if (!msg) + throw Error{Error::Code::Store, &gerr, "failed to find message for view"}; + + auto sexp{mu_msg_to_sexp(msg, docid, {}, message_options(params))}; + mu_msg_unref(msg); + + print_expr ("(:view %s)\n", sexp); + g_free (sexp); +} + + +static CommandMap +make_command_map (Context& context) +{ + CommandMap cmap; + + cmap.emplace("add", + CommandInfo{ + ArgMap{ {"path", ArgInfo{Type::String, true, "file system path to the message" }}}, + "add a message to the store", + [&](const auto& params){add_handler(context, params);}}); + + cmap.emplace("compose", + CommandInfo{ + ArgMap{{"type", ArgInfo{Type::Symbol, true, + "type of composition: reply/forward/edit/resend/new"}}, + {"docid", ArgInfo{Type::Integer, false,"document id of parent-message, if any"}}, + {"decrypt", ArgInfo{Type::Symbol, false, "whether to decrypt encrypted parts (if any)" }}}, + "get contact information", + [&](const auto& params){compose_handler(context, params);}}); + + cmap.emplace("contacts", + CommandInfo{ + ArgMap{ {"personal", ArgInfo{Type::Symbol, false, + "only personal contacts" }}, + {"after", ArgInfo{Type::String, false, + "only contacts seen after time_t string" }}, + {"tstamp", ArgInfo{Type::String, false, + "return changes since tstamp" }}}, + "get contact information", + [&](const auto& params){contacts_handler(context, params);}}); + + cmap.emplace("extract", + CommandInfo{ + ArgMap{{"docid", ArgInfo{Type::Integer, true, "document for the message" }}, + {"index", ArgInfo{Type::Integer, true, "index for the part to operate on" }}, + {"action", ArgInfo{Type::Symbol, true, "what to do with the part" }}, + {"decrypt", ArgInfo{Type::Symbol, false, + "whether to decrypt encrypted parts (if any)" }}, + {"path", ArgInfo{Type::String, false, "part for saving (for action: save)" }}, + {"what", ArgInfo{Type::Symbol, false, "what to do with the part (feedback)" }}, + {"param", ArgInfo{Type::String, false, "parameter for 'what'" }}}, + "extract mime-parts from a message", + [&](const auto& params){extract_handler(context, params);}}); + + cmap.emplace("find", + CommandInfo{ + ArgMap{ {"query", ArgInfo{Type::String, true, "search expression" }}, + {"threads", ArgInfo{Type::Symbol, false, + "whether to include threading information" }}, + {"sortfield", ArgInfo{Type::Symbol, false, "the field to sort results by" }}, + {"descending", ArgInfo{Type::Symbol, false, + "whether to sort in descending order" }}, + {"maxnum", ArgInfo{Type::Integer, false, + "maximum number of result (hint)" }}, + {"skip-dups", ArgInfo{Type::Symbol, false, + "whether to skip messages with duplicate message-ids" }}, + {"include-related", ArgInfo{Type::Symbol, false, + "whether to include other message related to matching ones" }}}, + "query the database for messages", + [&](const auto& params){find_handler(context, params);}}); + + cmap.emplace("help", + CommandInfo{ + ArgMap{ {"command", ArgInfo{Type::Symbol, false, + "command to get information for" }}, + {"full", ArgInfo{Type::Symbol, false, + "whether to include information about parameters" }}}, + "get information about one or all commands", + [&](const auto& params){help_handler(context, params);}}); + cmap.emplace("index", + CommandInfo{ + ArgMap{ {"my-addresses", ArgInfo{Type::List, false, "list of 'my' addresses"}}, + {"cleanup", ArgInfo{Type::Symbol, false, + "whether to remove stale messages from the store"}}, + {"lazy-check", ArgInfo{Type::Symbol, false, + "whether to avoid indexing up-to-date directories"}}}, + "scan maildir for new/updated/removed messages", + [&](const auto& params){index_handler(context, params);}}); + + cmap.emplace("move", + CommandInfo{ + ArgMap{{"docid", ArgInfo{Type::Integer, false, "document-id"}}, + {"msgid", ArgInfo{Type::String, false, "message-id"}}, + {"flags", ArgInfo{Type::String, false, "new flags for the message"}}, + {"maildir", ArgInfo{Type::String, false, "the target maildir" }}, + {"rename", ArgInfo{Type::Symbol, false, "change filename when moving" }}, + {"no-view", ArgInfo{Type::Symbol, false, + "if set, do not hint at updating the view"}},}, + "move messages and/or change their flags", + [&](const auto& params){move_handler(context, params);}}); + + cmap.emplace("mkdir", + CommandInfo{ + ArgMap{ {"path", ArgInfo{Type::String, true, + "location for the new maildir" }}}, + "create a new maildir", + [&](const auto& params){mkdir_handler(context, params);}}); + cmap.emplace("ping", + CommandInfo{ + ArgMap{ {"queries", ArgInfo{Type::List, false, + "queries for which to get read/unread numbers"}}, + {"skip-dups", ArgInfo{Type::Symbol, false, + "whether to exclude messages with duplicate message-ids"}},}, + "ping the mu-server and get information in response", + [&](const auto& params){ping_handler(context, params);}}); + + cmap.emplace("quit", + CommandInfo{{}, + "quit the mu server", + [&](const auto& params){quit_handler(context, params);}}); + + cmap.emplace("remove", + CommandInfo{ + ArgMap{ {"docid", ArgInfo{Type::Integer, true, + "document-id for the message to remove" }}}, + "remove a message from filesystem and database", + [&](const auto& params){remove_handler(context, params);}}); + + cmap.emplace("sent", + CommandInfo{ + ArgMap{ {"path", ArgInfo{Type::String, true, + "path to the message file" }} + }, + "tell mu about a message that was sent", + [&](const auto& params){sent_handler(context, params);}}); + + cmap.emplace("view", + CommandInfo{ + ArgMap{{"docid", ArgInfo{Type::Integer, false, "document-id"}}, + {"msgid", ArgInfo{Type::String, false, "message-id"}}, + {"path", ArgInfo{Type::String, false, "message filesystem path"}}, + + {"extract-images", ArgInfo{Type::Symbol, false, + "whether to extract images for this messages (if any)"}}, + {"decrypt", ArgInfo{Type::Symbol, false, + "whether to decrypt encrypted parts (if any)" }}, + {"verify", ArgInfo{Type::Symbol, false, + "whether to verify signatures (if any)" }} + + }, + "view a message. exactly one of docid/msgid/path must be specified", + [&](const auto& params){view_handler(context, params);}}); + return cmap; +} + + +static std::string +read_line(bool& do_quit) +{ + std::string line; + std::cout << ";; mu> "; + if (!std::getline(std::cin, line)) + do_quit = true; + return line; +} + +MuError +mu_cmd_server (MuConfig *opts, GError **err) try +{ + if (opts->commands) { + Context ctx{}; + auto cmap = make_command_map(ctx); + invoke(cmap, Sexp::parse("(help :full t)")); + return MU_OK; + } + + Context context{opts}; + context.command_map = make_command_map (context); + + if (opts->eval) { // evaluate command-line command & exit + auto call{Sexp::parse(opts->eval)}; + invoke(context.command_map, call); + return MU_OK; + } + + install_sig_handler(); + std::cout << ";; Welcome to the " << PACKAGE_STRING << " command-server\n" + << ";; Use (help) to get a list of commands, (quit) to quit.\n"; + + while (!MuTerminate && !context.do_quit) { + + std::string line; + try { + line = read_line(context.do_quit); + if (line.find_first_not_of(" \t") == std::string::npos) + continue; // skip whitespace-only lines + + auto call{Sexp::parse(line)}; + + invoke(context.command_map, call); + + } catch (const Error& er) { + std::cerr << ";; error: " << er.what() << "\n"; + print_error ((MuError)er.code(), "%s (line was:'%s')", + er.what(), line.c_str()); + } + } + + return MU_OK; + +} catch (const Error& er) { + g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", er.what()); + return MU_ERROR; +} catch (...) { + g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", "caught exception"); + return MU_ERROR; +} diff --git a/mu/mu-cmd.c b/mu/mu-cmd.c new file mode 100644 index 0000000..6c4c53b --- /dev/null +++ b/mu/mu-cmd.c @@ -0,0 +1,732 @@ +/* +** Copyright (C) 2010-2020 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "mu-msg.h" +#include "mu-msg-part.h" +#include "mu-cmd.h" +#include "mu-maildir.h" +#include "mu-contacts.hh" +#include "mu-runtime.h" +#include "mu-flags.h" + +#include "utils/mu-log.h" +#include "utils/mu-util.h" +#include "utils/mu-str.h" +#include "utils/mu-date.h" + +#define VIEW_TERMINATOR '\f' /* form-feed */ + +static gboolean +view_msg_sexp (MuMsg *msg, MuConfig *opts) +{ + char *sexp; + + sexp = mu_msg_to_sexp (msg, 0, NULL, mu_config_get_msg_options(opts)); + fputs (sexp, stdout); + g_free (sexp); + + return TRUE; +} + + +static void +each_part (MuMsg *msg, MuMsgPart *part, gchar **attach) +{ + char *fname, *tmp; + + if (!mu_msg_part_maybe_attachment (part)) + return; + + fname = mu_msg_part_get_filename (part, FALSE); + if (!fname) + return; + + tmp = *attach; + *attach = g_strdup_printf ("%s%s'%s'", + *attach ? *attach : "", + *attach ? ", " : "", + fname); + g_free (tmp); +} + +/* return comma-sep'd list of attachments */ +static gchar * +get_attach_str (MuMsg *msg, MuConfig *opts) +{ + gchar *attach; + MuMsgOptions msgopts; + + msgopts = mu_config_get_msg_options(opts) | + MU_MSG_OPTION_CONSOLE_PASSWORD; + + attach = NULL; + mu_msg_part_foreach (msg, msgopts, + (MuMsgPartForeachFunc)each_part, &attach); + return attach; +} + +#define color_maybe(C) do { if(color) fputs ((C),stdout);} while(0) + +static void +print_field (const char* field, const char *val, gboolean color) +{ + if (!val) + return; + + color_maybe (MU_COLOR_MAGENTA); + mu_util_fputs_encoded (field, stdout); + color_maybe (MU_COLOR_DEFAULT); + fputs (": ", stdout); + + if (val) { + color_maybe (MU_COLOR_GREEN); + mu_util_fputs_encoded (val, stdout); + } + + color_maybe (MU_COLOR_DEFAULT); + fputs ("\n", stdout); +} + + +/* a summary_len of 0 mean 'don't show summary, show body */ +static void +body_or_summary (MuMsg *msg, MuConfig *opts) +{ + const char *body; + gboolean color; + + color = !opts->nocolor; + body = mu_msg_get_body_text (msg, + mu_config_get_msg_options(opts) | + MU_MSG_OPTION_CONSOLE_PASSWORD); + if (!body) { + if (mu_msg_get_flags (msg) & MU_FLAG_ENCRYPTED) { + color_maybe (MU_COLOR_CYAN); + g_print ("[No body found; " + "message has encrypted parts]\n"); + } else { + color_maybe (MU_COLOR_MAGENTA); + g_print ("[No body found]\n"); + } + color_maybe (MU_COLOR_DEFAULT); + return; + } + + if (opts->summary_len != 0) { + gchar *summ; + summ = mu_str_summarize (body, opts->summary_len); + print_field ("Summary", summ, color); + g_free (summ); + } else { + mu_util_print_encoded ("%s", body); + if (!g_str_has_suffix (body, "\n")) + g_print ("\n"); + } +} + + +/* we ignore fields for now */ +/* summary_len == 0 means "no summary */ +static gboolean +view_msg_plain (MuMsg *msg, MuConfig *opts) +{ + gchar *attachs; + time_t date; + const GSList *lst; + gboolean color; + + color = !opts->nocolor; + + print_field ("From", mu_msg_get_from (msg), color); + print_field ("To", mu_msg_get_to (msg), color); + print_field ("Cc", mu_msg_get_cc (msg), color); + print_field ("Bcc", mu_msg_get_bcc (msg), color); + print_field ("Subject", mu_msg_get_subject (msg), color); + + if ((date = mu_msg_get_date (msg))) + print_field ("Date", mu_date_str_s ("%c", date), + color); + + if ((lst = mu_msg_get_tags (msg))) { + gchar *tags; + tags = mu_str_from_list (lst,','); + print_field ("Tags", tags, color); + g_free (tags); + } + + if ((attachs = get_attach_str (msg, opts))) { + print_field ("Attachments", attachs, color); + g_free (attachs); + } + + body_or_summary (msg, opts); + + return TRUE; +} + + +static gboolean +handle_msg (const char *fname, MuConfig *opts, GError **err) +{ + MuMsg *msg; + gboolean rv; + + msg = mu_msg_new_from_file (fname, NULL, err); + if (!msg) + return FALSE; + + switch (opts->format) { + case MU_CONFIG_FORMAT_PLAIN: + rv = view_msg_plain (msg, opts); + break; + case MU_CONFIG_FORMAT_SEXP: + rv = view_msg_sexp (msg, opts); + break; + default: + g_critical ("bug: should not be reached"); + rv = FALSE; + } + + mu_msg_unref (msg); + + return rv; +} + +static gboolean +view_params_valid (MuConfig *opts, GError **err) +{ + /* note: params[0] will be 'view' */ + if (!opts->params[0] || !opts->params[1]) { + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "error in parameters"); + return FALSE; + } + + switch (opts->format) { + case MU_CONFIG_FORMAT_PLAIN: + case MU_CONFIG_FORMAT_SEXP: + break; + default: + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "invalid output format"); + return FALSE; + } + + return TRUE; +} + + +static MuError +cmd_view (MuConfig *opts, GError **err) +{ + int i; + gboolean rv; + + g_return_val_if_fail (opts, MU_ERROR_INTERNAL); + g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_VIEW, + MU_ERROR_INTERNAL); + + rv = view_params_valid (opts, err); + if (!rv) + goto leave; + + for (i = 1; opts->params[i]; ++i) { + + rv = handle_msg (opts->params[i], opts, err); + if (!rv) + break; + + /* add a separator between two messages? */ + if (opts->terminator) + g_print ("%c", VIEW_TERMINATOR); + } + +leave: + if (!rv) + return err && *err ? (*err)->code : MU_ERROR; + + return MU_OK; +} + +static MuError +cmd_mkdir (MuConfig *opts, GError **err) +{ + int i; + + g_return_val_if_fail (opts, MU_ERROR_INTERNAL); + g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_MKDIR, + MU_ERROR_INTERNAL); + + if (!opts->params[1]) { + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "missing directory parameter"); + return MU_ERROR_IN_PARAMETERS; + } + + for (i = 1; opts->params[i]; ++i) + if (!mu_maildir_mkdir (opts->params[i], opts->dirmode, + FALSE, err)) + return err && *err ? (*err)->code : + MU_ERROR_FILE_CANNOT_MKDIR; + return MU_OK; +} + + +static gboolean +check_file_okay (const char *path, gboolean cmd_add) +{ + if (!g_path_is_absolute (path)) { + g_warning ("path is not absolute: %s", path); + return FALSE; + } + + if (cmd_add && access(path, R_OK) != 0) { + g_warning ("path is not readable: %s: %s", + path, strerror (errno)); + return FALSE; + } + + return TRUE; +} + + +typedef gboolean (*ForeachMsgFunc) (MuStore *store, const char *path, + GError **err); + + +static MuError +foreach_msg_file (MuStore *store, MuConfig *opts, + ForeachMsgFunc foreach_func, GError **err) +{ + unsigned u; + gboolean all_ok; + + /* note: params[0] will be 'add' */ + if (!opts->params[0] || !opts->params[1]) { + g_print ("usage: mu %s []\n", + opts->params[0] ? opts->params[0] : ""); + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "missing parameters"); + return MU_ERROR_IN_PARAMETERS; + } + + for (u = 1, all_ok = TRUE; opts->params[u]; ++u) { + + const char* path; + + path = opts->params[u]; + + if (!check_file_okay (path, TRUE)) { + all_ok = FALSE; + MU_WRITE_LOG ("not a valid message file: %s", path); + continue; + } + + if (!foreach_func (store, path, err)) { + all_ok = FALSE; + MU_WRITE_LOG ("error with %s: %s", path, + (err&&*err) ? (*err)->message : + "something went wrong"); + g_clear_error (err); + continue; + } + } + + if (!all_ok) { + mu_util_g_set_error (err, MU_ERROR_XAPIAN_STORE_FAILED, + "%s failed for some message(s)", + opts->params[0]); + return MU_ERROR_XAPIAN_STORE_FAILED; + } + + return MU_OK; +} + + +static gboolean +add_path_func (MuStore *store, const char *path, GError **err) +{ + return mu_store_add_path (store, path, err); +} + + +static MuError +cmd_add (MuStore *store, MuConfig *opts, GError **err) +{ + g_return_val_if_fail (store, MU_ERROR_INTERNAL); + g_return_val_if_fail (opts, MU_ERROR_INTERNAL); + g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_ADD, + MU_ERROR_INTERNAL); + + return foreach_msg_file (store, opts, add_path_func, err); +} + +static gboolean +remove_path_func (MuStore *store, const char *path, GError **err) +{ + if (!mu_store_remove_path (store, path)) { + mu_util_g_set_error (err, MU_ERROR_XAPIAN_REMOVE_FAILED, + "failed to remove %s", path); + return FALSE; + } + + return TRUE; +} + +static MuError +cmd_remove (MuStore *store, MuConfig *opts, GError **err) +{ + g_return_val_if_fail (opts, MU_ERROR_INTERNAL); + g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_REMOVE, + MU_ERROR_INTERNAL); + + return foreach_msg_file (store, opts, remove_path_func, err); +} + +static gboolean +tickle_func (MuStore *store, const char *path, GError **err) +{ + MuMsg *msg; + gboolean rv; + + msg = mu_msg_new_from_file (path, NULL, err); + if (!msg) + return FALSE; + + rv = mu_msg_tickle (msg, err); + mu_msg_unref (msg); + + return rv; +} + + +static MuError +cmd_tickle (MuStore *store, MuConfig *opts, GError **err) +{ + g_return_val_if_fail (opts, MU_ERROR_INTERNAL); + g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_TICKLE, + MU_ERROR_INTERNAL); + + return foreach_msg_file (store, opts, tickle_func, err); +} + +struct _VData { + MuMsgPartSigStatus combined_status; + char *report; + gboolean oneline; +}; +typedef struct _VData VData; + +static void +each_sig (MuMsg *msg, MuMsgPart *part, VData *vdata) +{ + MuMsgPartSigStatusReport *report; + + report = part->sig_status_report; + if (!report) + return; + + if (vdata->oneline) + vdata->report = g_strdup_printf + ("%s%s%s", + vdata->report ? vdata->report : "", + vdata->report ? "; " : "", + report->report); + else + vdata->report = g_strdup_printf + ("%s%s\t%s", + vdata->report ? vdata->report : "", + vdata->report ? "\n" : "", + report->report); + + if (vdata->combined_status == MU_MSG_PART_SIG_STATUS_BAD || + vdata->combined_status == MU_MSG_PART_SIG_STATUS_ERROR) + return; + + vdata->combined_status = report->verdict; +} + + +static void +print_verdict (VData *vdata, gboolean color, gboolean verbose) +{ + g_print ("verdict: "); + + switch (vdata->combined_status) { + case MU_MSG_PART_SIG_STATUS_UNSIGNED: + g_print ("no signature found"); + break; + case MU_MSG_PART_SIG_STATUS_GOOD: + color_maybe (MU_COLOR_GREEN); + g_print ("signature(s) verified"); + break; + case MU_MSG_PART_SIG_STATUS_BAD: + color_maybe (MU_COLOR_RED); + g_print ("bad signature"); + break; + case MU_MSG_PART_SIG_STATUS_ERROR: + color_maybe (MU_COLOR_RED); + g_print ("verification failed"); + break; + case MU_MSG_PART_SIG_STATUS_FAIL: + color_maybe(MU_COLOR_RED); + g_print ("error in verification process"); + break; + default: g_return_if_reached (); + } + + color_maybe (MU_COLOR_DEFAULT); + if (vdata->report && verbose) + g_print ("%s%s\n", + (vdata->oneline) ? ";" : "\n", + vdata->report); + else + g_print ("\n"); +} + + +static MuError +cmd_verify (MuConfig *opts, GError **err) +{ + MuMsg *msg; + MuMsgOptions msgopts; + VData vdata; + + g_return_val_if_fail (opts, MU_ERROR_INTERNAL); + g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_VERIFY, + MU_ERROR_INTERNAL); + + if (!opts->params[1]) { + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "missing message-file parameter"); + return MU_ERROR_IN_PARAMETERS; + } + + msg = mu_msg_new_from_file (opts->params[1], NULL, err); + if (!msg) + return MU_ERROR; + + msgopts = mu_config_get_msg_options (opts) + | MU_MSG_OPTION_VERIFY + | MU_MSG_OPTION_CONSOLE_PASSWORD; + + vdata.report = NULL; + vdata.combined_status = MU_MSG_PART_SIG_STATUS_UNSIGNED; + vdata.oneline = FALSE; + + mu_msg_part_foreach (msg, msgopts, + (MuMsgPartForeachFunc)each_sig, &vdata); + + if (!opts->quiet) + print_verdict (&vdata, !opts->nocolor, opts->verbose); + + mu_msg_unref (msg); + g_free (vdata.report); + + return vdata.combined_status == MU_MSG_PART_SIG_STATUS_GOOD ? + MU_OK : MU_ERROR; +} + +static MuError +cmd_info (MuStore *store, MuConfig *opts, GError **err) +{ + mu_store_print_info (store, opts->nocolor); + + return MU_OK; +} + + +static MuError +cmd_init (MuConfig *opts, GError **err) +{ + MuStore *store; + const char *path; + + /* not provided, nor could we find a good default */ + if (!opts->maildir) { + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "missing --maildir parameter and could " + "not determine default"); + return MU_ERROR_IN_PARAMETERS; + } + + path = mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB); + store = mu_store_new_create (path, + opts->maildir, + (const char**)opts->my_addresses, + err); + if (!store) + return MU_G_ERROR_CODE(err); + + if (!opts->quiet) { + mu_store_print_info (store, opts->nocolor); + g_print ("\nstore created.\n" + "use 'mu index' to fill the database " + "with your messages.\n" + "see mu-index(1) for details\n"); + } + + mu_store_unref (store); + return MU_OK; +} + + +static void +show_usage (void) +{ + g_print ("usage: mu command [options] [parameters]\n"); + g_print ("where command is one of index, find, cfind, view, mkdir, " + "extract, add, remove, script, verify or server\n"); + g_print ("see the mu, mu- or mu-easy manpages for " + "more information\n"); +} + +typedef MuError (*store_func) (MuStore *, MuConfig *, GError **err); + + +static MuError +with_store (store_func func, MuConfig *opts, gboolean read_only, GError **err) +{ + MuError merr; + MuStore *store; + const char *path; + + path = mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB); + + if (read_only) + store = mu_store_new_readable (path, err); + else + store = mu_store_new_writable (path, err); + + if (!store) + return MU_G_ERROR_CODE(err); + + merr = func (store, opts, err); + mu_store_unref (store); + + return merr; +} + +static MuError +with_readonly_store (store_func func, MuConfig *opts, GError **err) +{ + return with_store (func, opts, TRUE, err); +} + +static MuError +with_writable_store (store_func func, MuConfig *opts, GError **err) +{ + return with_store (func, opts, FALSE, err); +} + +static gboolean +check_params (MuConfig *opts, GError **err) +{ + if (!opts->params||!opts->params[0]) {/* no command? */ + show_usage (); + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "error in parameters"); + return FALSE; + } + + return TRUE; +} + +static void +set_log_options (MuConfig *opts) +{ + MuLogOptions logopts; + + logopts = MU_LOG_OPTIONS_NONE; + + if (opts->quiet) + logopts |= MU_LOG_OPTIONS_QUIET; + if (!opts->nocolor) + logopts |= MU_LOG_OPTIONS_COLOR; + if (opts->log_stderr) + logopts |= MU_LOG_OPTIONS_STDERR; + if (opts->debug) + logopts |= MU_LOG_OPTIONS_DEBUG; +} + +MuError +mu_cmd_execute (MuConfig *opts, GError **err) +{ + MuError merr; + + g_return_val_if_fail (opts, MU_ERROR_INTERNAL); + + if (!check_params(opts, err)) + return MU_G_ERROR_CODE(err); + + set_log_options (opts); + + switch (opts->cmd) { + + /* already handled in mu-config.c */ + case MU_CONFIG_CMD_HELP: return MU_OK; + + /* no store needed */ + + case MU_CONFIG_CMD_MKDIR: merr = cmd_mkdir (opts, err); break; + case MU_CONFIG_CMD_SCRIPT: merr = mu_cmd_script (opts, err); break; + case MU_CONFIG_CMD_VIEW: merr = cmd_view (opts, err); break; + case MU_CONFIG_CMD_VERIFY: merr = cmd_verify (opts, err); break; + case MU_CONFIG_CMD_EXTRACT: merr = mu_cmd_extract (opts, err); break; + + /* read-only store */ + + case MU_CONFIG_CMD_CFIND: + merr = with_readonly_store (mu_cmd_cfind, opts, err); break; + case MU_CONFIG_CMD_FIND: + merr = with_readonly_store (mu_cmd_find, opts, err); break; + case MU_CONFIG_CMD_INFO: + merr = with_readonly_store (cmd_info, opts, err); break; + + /* writable store */ + + case MU_CONFIG_CMD_ADD: + merr = with_writable_store (cmd_add, opts, err); break; + case MU_CONFIG_CMD_REMOVE: + merr = with_writable_store (cmd_remove, opts, err); break; + case MU_CONFIG_CMD_TICKLE: + merr = with_writable_store (cmd_tickle, opts, err); break; + case MU_CONFIG_CMD_INDEX: + merr = with_writable_store (mu_cmd_index, opts, err); break; + + /* commands instantiate store themselves */ + case MU_CONFIG_CMD_INIT: + merr = cmd_init (opts,err); break; + case MU_CONFIG_CMD_SERVER: + merr = mu_cmd_server (opts, err); break; + + default: + merr = MU_ERROR_IN_PARAMETERS; break; + } + + return merr; +} diff --git a/mu/mu-cmd.h b/mu/mu-cmd.h new file mode 100644 index 0000000..b65cd15 --- /dev/null +++ b/mu/mu-cmd.h @@ -0,0 +1,111 @@ +/* +** Copyright (C) 2008-2020 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_CMD_H__ +#define __MU_CMD_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/** + * execute the 'find' command + * + * @param store store object to use + * @param opts configuration options + * @param err receives error information, or NULL + * + * @return MU_OK (0) if the command succeeds and + * >MU_OK (0) results, MU_EXITCODE_NO_MATCHES if the command + * succeeds but there no matches, some error code for all other errors + */ +MuError mu_cmd_find (MuStore *store, MuConfig *opts, GError **err); + + +/** + * execute the 'extract' command + * + * @param opts configuration options + * @param err receives error information, or NULL + * + * @return MU_OK (0) if the command succeeds, + * some error code otherwise + */ +MuError mu_cmd_extract (MuConfig *opts, GError **err); + + +/** + * execute the 'script' command + * + * @param opts configuration options + * @param err receives error information, or NULL + * + * @return MU_OK (0) if the command succeeds, + * some error code otherwise + */ +MuError mu_cmd_script (MuConfig *opts, GError **err); + +/** + * execute the cfind command + * + * @param store store object to use + * @param opts configuration options + * @param err receives error information, or NULL + * + * @return MU_OK (0) if the command succeeds, + * some error code otherwise + */ +MuError mu_cmd_cfind (MuStore *store, MuConfig *opts, GError **err); + +/** + * execute some mu command, based on 'opts' + * + * @param opts configuration option + * @param err receives error information, or NULL + * + * @return MU_OK if all went wall, some error code otherwise + */ +MuError mu_cmd_execute (MuConfig *opts, GError **err); + +/** + * execute the 'index' command + * + * @param store store object to use + * @param opts configuration options + * @param err receives error information, or NULL + * + * @return MU_OK (0) if the command succeeded, + * some error code otherwise + */ +MuError mu_cmd_index (MuStore *store, MuConfig *opt, GError **err); + +/** + * execute the server command + * @param opts configuration options + * @param err receives error information, or NULL + * + * @return MU_OK (0) if the command succeeds, some error code otherwise + */ +MuError mu_cmd_server (MuConfig *opts, GError **err); + +G_END_DECLS + +#endif /*__MU_CMD_H__*/ diff --git a/mu/mu-config.c b/mu/mu-config.c new file mode 100644 index 0000000..89538cd --- /dev/null +++ b/mu/mu-config.c @@ -0,0 +1,809 @@ +/* +** Copyright (C) 2008-2020 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include +#include /* memset */ +#include +#include + +#include "mu-config.h" +#include "mu-cmd.h" + + +static MuConfig MU_CONFIG; + +#define color_maybe(C) (MU_CONFIG.nocolor ? "" : (C)) + + +static MuConfigFormat +get_output_format (const char *formatstr) +{ + int i; + struct { + const char* name; + MuConfigFormat format; + } formats [] = { + {"mutt-alias", MU_CONFIG_FORMAT_MUTT_ALIAS}, + {"mutt-ab", MU_CONFIG_FORMAT_MUTT_AB}, + {"wl", MU_CONFIG_FORMAT_WL}, + {"csv", MU_CONFIG_FORMAT_CSV}, + {"org-contact", MU_CONFIG_FORMAT_ORG_CONTACT}, + {"bbdb", MU_CONFIG_FORMAT_BBDB}, + {"links", MU_CONFIG_FORMAT_LINKS}, + {"plain", MU_CONFIG_FORMAT_PLAIN}, + {"sexp", MU_CONFIG_FORMAT_SEXP}, + {"json", MU_CONFIG_FORMAT_JSON}, + {"xml", MU_CONFIG_FORMAT_XML}, + {"xquery", MU_CONFIG_FORMAT_XQUERY}, + {"mquery", MU_CONFIG_FORMAT_MQUERY}, + {"debug", MU_CONFIG_FORMAT_DEBUG} + }; + + for (i = 0; i != G_N_ELEMENTS(formats); i++) + if (strcmp (formats[i].name, formatstr) == 0) + return formats[i].format; + + return MU_CONFIG_FORMAT_UNKNOWN; +} + + +#define expand_dir(D) \ + if ((D)) { \ + char *exp; \ + exp = mu_util_dir_expand((D)); \ + if (exp) { \ + g_free((D)); \ + (D) = exp; \ + } \ + } + + +static void +set_group_mu_defaults (void) +{ + /* If muhome is not set, we use the XDG Base Directory Specification + * locations. */ + if (MU_CONFIG.muhome) + expand_dir(MU_CONFIG.muhome); + + /* check for the MU_NOCOLOR or NO_COLOR env vars; but in any case don't + * use colors unless we're writing to a tty */ + if (g_getenv (MU_NOCOLOR) != NULL || g_getenv ("NO_COLOR") != NULL) + MU_CONFIG.nocolor = TRUE; + + if (!isatty(fileno(stdout)) || !isatty(fileno(stderr))) + MU_CONFIG.nocolor = TRUE; +} + +static GOptionGroup* +config_options_group_mu (void) +{ + GOptionGroup *og; + GOptionEntry entries[] = { + {"debug", 'd', 0, G_OPTION_ARG_NONE, &MU_CONFIG.debug, + "print debug output to standard error (false)", NULL}, + {"quiet", 'q', 0, G_OPTION_ARG_NONE, &MU_CONFIG.quiet, + "don't give any progress information (false)", NULL}, + {"version", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.version, + "display version and copyright information (false)", NULL}, + {"muhome", 0, 0, G_OPTION_ARG_FILENAME, &MU_CONFIG.muhome, + "specify an alternative mu directory", ""}, + {"log-stderr", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.log_stderr, + "log to standard error (false)", NULL}, + {"nocolor", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.nocolor, + "don't use ANSI-colors in output (false)", NULL}, + {"verbose", 'v', 0, G_OPTION_ARG_NONE, &MU_CONFIG.verbose, + "verbose output (false)", NULL}, + + {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, + &MU_CONFIG.params, "parameters", NULL}, + {NULL, 0, 0, 0, NULL, NULL, NULL} + }; + + og = g_option_group_new("mu", "general mu options", "", NULL, NULL); + g_option_group_add_entries(og, entries); + + return og; +} + +static void +set_group_init_defaults (void) +{ + if (!MU_CONFIG.maildir) + MU_CONFIG.maildir = mu_util_guess_maildir(); + + expand_dir (MU_CONFIG.maildir); +} + +static GOptionGroup* +config_options_group_init (void) +{ + GOptionGroup *og; + GOptionEntry entries[] = { + {"maildir", 'm', 0, G_OPTION_ARG_FILENAME, &MU_CONFIG.maildir, + "top of the maildir", ""}, + {"my-address", 0, 0, G_OPTION_ARG_STRING_ARRAY, + &MU_CONFIG.my_addresses, "my e-mail address; can be used multiple times", + "
"}, + {NULL, 0, 0, 0, NULL, NULL, NULL} + }; + + og = g_option_group_new("init", "Options for the 'index' command", + "", NULL, NULL); + g_option_group_add_entries(og, entries); + + return og; +} + +static gboolean +index_post_parse_func (GOptionContext *context, GOptionGroup *group, + gpointer data, GError **error) +{ + if (!MU_CONFIG.maildir && !MU_CONFIG.my_addresses) + return TRUE; + + g_printerr ("%sNOTE%s: as of mu 1.3.8, 'mu index' no longer uses the\n" + "--maildir/-m or --my-address options.\n\n", + color_maybe(MU_COLOR_RED), color_maybe(MU_COLOR_DEFAULT)); + g_printerr ("Instead, these options should be passed to 'mu init'.\n"); + g_printerr ("See the mu-init(1) or the mu4e reference manual,\n'Initializing the message store' for details.\n\n"); + + return TRUE; +} + + +static GOptionGroup* +config_options_group_index (void) +{ + GOptionGroup *og; + GOptionEntry entries[] = { + /* only here so we can tell users they are deprecated */ + {"maildir", 'm', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, + &MU_CONFIG.maildir, "top of the maildir", ""}, + {"my-address", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING_ARRAY, + &MU_CONFIG.my_addresses, "my e-mail address; can be used multiple times", + "
"}, + + {"lazy-check", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.lazycheck, + "only check dir-timestamps (false)", NULL}, + {"nocleanup", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.nocleanup, + "don't clean up the database after indexing (false)", NULL}, + {NULL, 0, 0, 0, NULL, NULL, NULL} + }; + + og = g_option_group_new("index", "Options for the 'index' command", + "", NULL, NULL); + g_option_group_add_entries(og, entries); + g_option_group_set_parse_hooks(og, NULL, (GOptionParseFunc)index_post_parse_func); + + return og; +} + +static void +set_group_find_defaults (void) +{ + /* note, when no fields are specified, we use + * date-from-subject, and sort descending by date. If fields + * *are* specified, we sort in ascending order. */ + if (!MU_CONFIG.fields || !*MU_CONFIG.fields) { + MU_CONFIG.fields = g_strdup ("d f s"); + if (!MU_CONFIG.sortfield) + MU_CONFIG.sortfield = g_strdup ("d"); + } + + if (!MU_CONFIG.formatstr) /* by default, use plain output */ + MU_CONFIG.format = MU_CONFIG_FORMAT_PLAIN; + else + MU_CONFIG.format = + get_output_format (MU_CONFIG.formatstr); + + expand_dir (MU_CONFIG.linksdir); +} + +static GOptionGroup* +config_options_group_find (void) +{ + GOptionGroup *og; + GOptionEntry entries[] = { + {"fields", 'f', 0, G_OPTION_ARG_STRING, &MU_CONFIG.fields, + "fields to display in the output", ""}, + {"sortfield", 's', 0, G_OPTION_ARG_STRING, + &MU_CONFIG.sortfield, + "field to sort on", ""}, + {"maxnum", 'n', 0, G_OPTION_ARG_INT, &MU_CONFIG.maxnum, + "number of entries to display in the output", ""}, + {"threads", 't', 0, G_OPTION_ARG_NONE, &MU_CONFIG.threads, + "show message threads", NULL}, + {"bookmark", 'b', 0, G_OPTION_ARG_STRING, &MU_CONFIG.bookmark, + "use a bookmarked query", ""}, + {"reverse", 'z', 0, G_OPTION_ARG_NONE, &MU_CONFIG.reverse, + "sort in reverse (descending) order (z -> a)", NULL}, + {"skip-dups", 'u', 0, G_OPTION_ARG_NONE, + &MU_CONFIG.skip_dups, + "show only the first of messages duplicates (false)", NULL}, + {"include-related", 'r', 0, G_OPTION_ARG_NONE, + &MU_CONFIG.include_related, + "include related messages in results (false)", NULL}, + {"linksdir", 0, 0, G_OPTION_ARG_STRING, &MU_CONFIG.linksdir, + "output as symbolic links to a target maildir", ""}, + {"clearlinks", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.clearlinks, + "clear old links before filling a linksdir (false)", NULL}, + {"format", 'o', 0, G_OPTION_ARG_STRING, &MU_CONFIG.formatstr, + "output format ('plain'(*), 'links', 'xml'," + "'sexp', 'xquery')", ""}, + {"summary-len", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.summary_len, + "use up to lines for the summary, or 0 for none (0)", + ""}, + {"exec", 'e', 0, G_OPTION_ARG_STRING, &MU_CONFIG.exec, + "execute command on each match message", ""}, + {"after", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.after, + "only show messages whose m_time > T (t_time)", + ""}, + {NULL, 0, 0, 0, NULL, NULL, NULL} + }; + + og = g_option_group_new("find", + "Options for the 'find' command", + "", NULL, NULL); + g_option_group_add_entries(og, entries); + + return og; +} + +static GOptionGroup * +config_options_group_mkdir (void) +{ + GOptionGroup *og; + GOptionEntry entries[] = { + {"mode", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.dirmode, + "set the mode (as in chmod), in octal notation", ""}, + {NULL, 0, 0, 0, NULL, NULL, NULL} + }; + + /* set dirmode before, because '0000' is a valid mode */ + MU_CONFIG.dirmode = 0755; + + og = g_option_group_new("mkdir", "Options for the 'mkdir' command", + "", NULL, NULL); + g_option_group_add_entries(og, entries); + + return og; +} + +static void +set_group_cfind_defaults (void) +{ + if (!MU_CONFIG.formatstr) /* by default, use plain output */ + MU_CONFIG.format = MU_CONFIG_FORMAT_PLAIN; + else + MU_CONFIG.format = get_output_format (MU_CONFIG.formatstr); +} + +static GOptionGroup * +config_options_group_cfind (void) +{ + GOptionGroup *og; + GOptionEntry entries[] = { + {"format", 'o', 0, G_OPTION_ARG_STRING, &MU_CONFIG.formatstr, + "output format (plain(*), mutt-alias, mutt-ab, wl, " + "org-contact, bbdb, csv)", ""}, + {"personal", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.personal, + "whether to only get 'personal' contacts", NULL}, + {"after", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.after, + "only get addresses last seen after T", ""}, + {NULL, 0, 0, 0, NULL, NULL, NULL} + }; + + og = g_option_group_new("cfind", "Options for the 'cfind' command", + "", NULL, NULL); + g_option_group_add_entries(og, entries); + + return og; +} + +static GOptionGroup * +config_options_group_script (void) +{ + GOptionGroup *og; + GOptionEntry entries[] = { + {G_OPTION_REMAINING, 0,0, G_OPTION_ARG_STRING_ARRAY, + &MU_CONFIG.params, "script parameters", NULL}, + {NULL, 0, 0, 0, NULL, NULL, NULL} + }; + + og = g_option_group_new("script", "Options for the 'script' command", + "", NULL, NULL); + + g_option_group_add_entries(og, entries); + + return og; +} + +static void +set_group_view_defaults (void) +{ + if (!MU_CONFIG.formatstr) /* by default, use plain output */ + MU_CONFIG.format = MU_CONFIG_FORMAT_PLAIN; + else + MU_CONFIG.format = get_output_format (MU_CONFIG.formatstr); +} + + +/* crypto options are used in a few different commands */ +static GOptionEntry* +crypto_option_entries (void) +{ + static GOptionEntry entries[] = { + {"auto-retrieve", 'r', 0, G_OPTION_ARG_NONE, + &MU_CONFIG.auto_retrieve, + "attempt to retrieve keys online (false)", NULL}, + {"use-agent", 'a', 0, G_OPTION_ARG_NONE, &MU_CONFIG.use_agent, + "attempt to use the GPG agent (false)", NULL}, + {"decrypt", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.decrypt, + "attempt to decrypt the message", NULL}, + {NULL, 0, 0, 0, NULL, NULL, NULL} + }; + + return entries; +} + +static GOptionGroup * +config_options_group_view (void) +{ + GOptionGroup *og; + GOptionEntry entries[] = { + {"summary-len", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.summary_len, + "use up to lines for the summary, or 0 for none (0)", + ""}, + {"terminate", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.terminator, + "terminate messages with ascii-0x07 (\\f, form-feed)", + ""}, + {"format", 'o', 0, G_OPTION_ARG_STRING, &MU_CONFIG.formatstr, + "output format ('plain'(*), 'sexp')", ""}, + {NULL, 0, 0, 0, NULL, NULL, NULL} + }; + + og = g_option_group_new("view", "Options for the 'view' command", + "", NULL, NULL); + + g_option_group_add_entries(og, entries); + g_option_group_add_entries(og, crypto_option_entries()); + + return og; +} + +static void +set_group_extract_defaults (void) +{ + if (!MU_CONFIG.targetdir) + MU_CONFIG.targetdir = g_strdup ("."); + + expand_dir (MU_CONFIG.targetdir); +} + + +static GOptionGroup* +config_options_group_extract (void) +{ + GOptionGroup *og; + GOptionEntry entries[] = { + {"save-attachments", 'a', 0, G_OPTION_ARG_NONE, + &MU_CONFIG.save_attachments, + "save all attachments (false)", NULL}, + {"save-all", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.save_all, + "save all parts (incl. non-attachments) (false)", NULL}, + {"parts", 0, 0, G_OPTION_ARG_STRING, &MU_CONFIG.parts, + "save specific parts (comma-separated list)", ""}, + {"target-dir", 0, 0, G_OPTION_ARG_FILENAME, + &MU_CONFIG.targetdir, + "target directory for saving", ""}, + {"overwrite", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.overwrite, + "overwrite existing files (false)", NULL}, + {"play", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.play, + "try to 'play' (open) the extracted parts", NULL}, + {NULL, 0, 0, 0, NULL, NULL, NULL} + }; + og = g_option_group_new("extract", + "Options for the 'extract' command", + "", NULL, NULL); + g_option_group_add_entries(og, entries); + g_option_group_add_entries(og, crypto_option_entries()); + + return og; +} + + +static GOptionGroup* +config_options_group_verify (void) +{ + GOptionGroup *og; + og = g_option_group_new("verify", + "Options for the 'verify' command", + "", NULL, NULL); + g_option_group_add_entries(og, crypto_option_entries()); + + return og; +} + + +static GOptionGroup* +config_options_group_server (void) +{ + GOptionGroup *og; + GOptionEntry entries[] = { + {"commands", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.commands, + "list the available command and their parameters, then exit", NULL}, + {"eval", 'e', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, + &MU_CONFIG.eval, "expression to evaluate", ""}, + {NULL, 0, 0, 0, NULL, NULL, NULL} + }; + + og = g_option_group_new("server", + "Options for the 'server' command", + "", NULL, NULL); + g_option_group_add_entries(og, entries); + + return og; +} + + +static MuConfigCmd +cmd_from_string (const char *str) +{ + int i; + struct { + const gchar* name; + MuConfigCmd cmd; + } cmd_map[] = { + { "add", MU_CONFIG_CMD_ADD }, + { "cfind", MU_CONFIG_CMD_CFIND }, + { "extract", MU_CONFIG_CMD_EXTRACT }, + { "find", MU_CONFIG_CMD_FIND }, + { "help", MU_CONFIG_CMD_HELP }, + { "index", MU_CONFIG_CMD_INDEX }, + { "info", MU_CONFIG_CMD_INFO }, + { "init", MU_CONFIG_CMD_INIT }, + { "mkdir", MU_CONFIG_CMD_MKDIR }, + { "remove", MU_CONFIG_CMD_REMOVE }, + { "script", MU_CONFIG_CMD_SCRIPT }, + { "server", MU_CONFIG_CMD_SERVER }, + { "tickle", MU_CONFIG_CMD_TICKLE }, + { "verify", MU_CONFIG_CMD_VERIFY }, + { "view", MU_CONFIG_CMD_VIEW } + }; + + if (!str) + return MU_CONFIG_CMD_UNKNOWN; + + for (i = 0; i != G_N_ELEMENTS(cmd_map); ++i) + if (strcmp (str, cmd_map[i].name) == 0) + return cmd_map[i].cmd; +#ifdef BUILD_GUILE + /* if we don't recognize it and it's not an option, it may be + * some script */ + if (str[0] != '-') + return MU_CONFIG_CMD_SCRIPT; +#endif /*BUILD_GUILE*/ + + return MU_CONFIG_CMD_UNKNOWN; +} + + + +static gboolean +parse_cmd (int *argcp, char ***argvp, GError **err) +{ + MU_CONFIG.cmd = MU_CONFIG_CMD_NONE; + MU_CONFIG.cmdstr = NULL; + + if (*argcp < 2) /* no command found at all */ + return TRUE; + else if ((**argvp)[1] == '-') + /* if the first param starts with '-', there is no + * command, just some option (like --version, --help + * etc.)*/ + return TRUE; + + MU_CONFIG.cmdstr = g_strdup ((*argvp)[1]); + MU_CONFIG.cmd = cmd_from_string (MU_CONFIG.cmdstr); + +#ifndef BUILD_GUILE + if (MU_CONFIG.cmd == MU_CONFIG_CMD_SCRIPT) { + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "command 'script' not supported"); + return FALSE; + } +#endif /*!BUILD_GUILE*/ + + if (MU_CONFIG.cmdstr && MU_CONFIG.cmdstr[0] != '-' && + MU_CONFIG.cmd == MU_CONFIG_CMD_UNKNOWN) { + mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, + "unknown command '%s'", + MU_CONFIG.cmdstr); + return FALSE; + } + + return TRUE; +} + + +static GOptionGroup* +get_option_group (MuConfigCmd cmd) +{ + switch (cmd) { + case MU_CONFIG_CMD_CFIND: + return config_options_group_cfind(); + case MU_CONFIG_CMD_EXTRACT: + return config_options_group_extract(); + case MU_CONFIG_CMD_FIND: + return config_options_group_find(); + case MU_CONFIG_CMD_INDEX: + return config_options_group_index(); + case MU_CONFIG_CMD_INIT: + return config_options_group_init(); + case MU_CONFIG_CMD_MKDIR: + return config_options_group_mkdir(); + case MU_CONFIG_CMD_SERVER: + return config_options_group_server(); + case MU_CONFIG_CMD_SCRIPT: + return config_options_group_script(); + case MU_CONFIG_CMD_VERIFY: + return config_options_group_verify(); + case MU_CONFIG_CMD_VIEW: + return config_options_group_view(); + default: + return NULL; /* no group to add */ + } +} + + + +/* ugh yuck massaging the GOption text output; glib prepares some text + * which has a 'Usage:' for the 'help' command. However, we need the + * help for the command we're asking help for. So, we remove the Usage: + * from what glib generates. :-( */ +static gchar* +massage_help (const char *help) +{ + GRegex *rx; + char *str; + + rx = g_regex_new ("^Usage:.*\n.*\n", + 0, G_REGEX_MATCH_NEWLINE_ANY, NULL); + str = g_regex_replace (rx, help, + -1, 0, "", + G_REGEX_MATCH_NEWLINE_ANY, NULL); + g_regex_unref (rx); + return str; +} + + + +static const gchar* +get_help_string (MuConfigCmd cmd, gboolean long_help) +{ + unsigned u; + + /* this include gets us MU_HELP_STRINGS */ +#include "mu-help-strings.h" + + for (u = 0; u != G_N_ELEMENTS(MU_HELP_STRINGS); ++u) + if (cmd == MU_HELP_STRINGS[u].cmd) { + if (long_help) + return MU_HELP_STRINGS[u].long_help; + else + return MU_HELP_STRINGS[u].usage ; + } + + g_return_val_if_reached (""); + return ""; +} + + +void +mu_config_show_help (MuConfigCmd cmd) +{ + GOptionContext *ctx; + GOptionGroup *group; + char *help, *cleanhelp; + + g_return_if_fail (mu_config_cmd_is_valid(cmd)); + + ctx = g_option_context_new ("- mu help"); + g_option_context_set_main_group (ctx, config_options_group_mu()); + + group = get_option_group (cmd); + if (group) + g_option_context_add_group (ctx, group); + + g_option_context_set_description (ctx, get_help_string (cmd, TRUE)); + help = g_option_context_get_help (ctx, TRUE, group); + cleanhelp = massage_help (help); + + g_print ("usage:\n\t%s%s", + get_help_string (cmd, FALSE), cleanhelp); + + g_free (help); + g_free (cleanhelp); + g_option_context_free (ctx); +} + +static gboolean +cmd_help (void) +{ + MuConfigCmd cmd; + + if (!MU_CONFIG.params) + cmd = MU_CONFIG_CMD_UNKNOWN; + else + cmd = cmd_from_string (MU_CONFIG.params[1]); + + if (cmd == MU_CONFIG_CMD_UNKNOWN) { + mu_config_show_help (MU_CONFIG_CMD_HELP); + return TRUE; + } + + mu_config_show_help (cmd); + + return TRUE; +} + +static gboolean +parse_params (int *argcp, char ***argvp, GError **err) +{ + GOptionContext *context; + GOptionGroup *group; + gboolean rv; + + context = g_option_context_new("- mu general options"); + + g_option_context_set_help_enabled (context, TRUE); + rv = TRUE; + + g_option_context_set_main_group(context, + config_options_group_mu()); + g_option_context_set_ignore_unknown_options (context, FALSE); + + switch (MU_CONFIG.cmd) { + case MU_CONFIG_CMD_NONE: + case MU_CONFIG_CMD_HELP: + /* 'help' is special; sucks in the options of the + * command after it */ + rv = g_option_context_parse (context, argcp, argvp, err) && + cmd_help (); + break; + case MU_CONFIG_CMD_SCRIPT: + /* all unknown commands are passed to 'script' */ + g_option_context_set_ignore_unknown_options (context, TRUE); + group = get_option_group (MU_CONFIG.cmd); + g_option_context_add_group (context, group); + rv = g_option_context_parse (context, argcp, argvp, err); + MU_CONFIG.script = g_strdup (MU_CONFIG.cmdstr); + /* argvp contains the script parameters */ + MU_CONFIG.script_params = (const char**)&((*argvp)[1]); + break; + + default: + group = get_option_group (MU_CONFIG.cmd); + if (group) + g_option_context_add_group (context, group); + + rv = g_option_context_parse (context, argcp, argvp, err); + break; + } + + g_option_context_free (context); + + return rv ? TRUE : FALSE; +} + + +MuConfig* +mu_config_init (int *argcp, char ***argvp, GError **err) +{ + g_return_val_if_fail (argcp && argvp, NULL); + + memset (&MU_CONFIG, 0, sizeof(MU_CONFIG)); + + MU_CONFIG.maxnum = -1; /* By default, output all matching entries. */ + + if (!parse_cmd (argcp, argvp, err)) + goto errexit; + + if (!parse_params(argcp, argvp, err)) + goto errexit; + + /* fill in the defaults if user did not specify */ + set_group_mu_defaults(); + set_group_init_defaults(); + set_group_find_defaults(); + set_group_cfind_defaults(); + set_group_view_defaults(); + set_group_extract_defaults(); + /* set_group_mkdir_defaults (config); */ + + return &MU_CONFIG; + +errexit: + mu_config_uninit (&MU_CONFIG); + return NULL; +} + + +void +mu_config_uninit (MuConfig *opts) +{ + if (!opts) + return; + + g_free (opts->cmdstr); + g_free (opts->muhome); + g_free (opts->maildir); + g_free (opts->fields); + g_free (opts->sortfield); + g_free (opts->bookmark); + g_free (opts->formatstr); + g_free (opts->exec); + g_free (opts->linksdir); + g_free (opts->targetdir); + g_free (opts->parts); + g_free (opts->script); + g_free (opts->eval); + + g_strfreev (opts->params); + + memset (opts, 0, sizeof(MU_CONFIG)); +} + +size_t +mu_config_param_num (MuConfig *opts) +{ + size_t n; + + g_return_val_if_fail (opts && opts->params, 0); + for (n = 0; opts->params[n]; ++n); + + return n; +} + + +MuMsgOptions +mu_config_get_msg_options (MuConfig *muopts) +{ + MuMsgOptions opts; + + opts = MU_MSG_OPTION_NONE; + + if (muopts->decrypt) + opts |= MU_MSG_OPTION_DECRYPT; + if (muopts->verify) + opts |= MU_MSG_OPTION_VERIFY; + if (muopts->use_agent) + opts |= MU_MSG_OPTION_USE_AGENT; + if (muopts->auto_retrieve) + opts |= MU_MSG_OPTION_AUTO_RETRIEVE; + if (muopts->overwrite) + opts |= MU_MSG_OPTION_OVERWRITE; + + return opts; +} diff --git a/mu/mu-config.h b/mu/mu-config.h new file mode 100644 index 0000000..43418ae --- /dev/null +++ b/mu/mu-config.h @@ -0,0 +1,260 @@ +/* +** Copyright (C) 2008-2020 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_CONFIG_H__ +#define __MU_CONFIG_H__ + +#include +#include /* for mode_t */ +#include +#include +#include + +G_BEGIN_DECLS + +/* env var; if non-empty, color are disabled */ +#define MU_NOCOLOR "MU_NOCOLOR" + + +typedef enum { + MU_CONFIG_FORMAT_UNKNOWN = 0, + + /* for cfind, find, view */ + MU_CONFIG_FORMAT_PLAIN, /* plain output */ + + /* for cfind */ + MU_CONFIG_FORMAT_MUTT_ALIAS, /* mutt alias style */ + MU_CONFIG_FORMAT_MUTT_AB, /* mutt ext abook */ + MU_CONFIG_FORMAT_WL, /* Wanderlust abook */ + MU_CONFIG_FORMAT_CSV, /* comma-sep'd values */ + MU_CONFIG_FORMAT_ORG_CONTACT, /* org-contact */ + MU_CONFIG_FORMAT_BBDB, /* BBDB */ + MU_CONFIG_FORMAT_DEBUG, + + /* for find, view */ + MU_CONFIG_FORMAT_SEXP, /* output sexps (emacs) */ + MU_CONFIG_FORMAT_JSON, /* output JSON */ + + /* for find */ + MU_CONFIG_FORMAT_LINKS, /* output as symlinks */ + MU_CONFIG_FORMAT_XML, /* output xml */ + MU_CONFIG_FORMAT_XQUERY, /* output the xapian query */ + MU_CONFIG_FORMAT_MQUERY, /* output the mux query */ + + MU_CONFIG_FORMAT_EXEC /* execute some command */ +} MuConfigFormat; + +typedef enum { + MU_CONFIG_CMD_UNKNOWN = 0, + + MU_CONFIG_CMD_ADD, + MU_CONFIG_CMD_CFIND, + MU_CONFIG_CMD_EXTRACT, + MU_CONFIG_CMD_FIND, + MU_CONFIG_CMD_HELP, + MU_CONFIG_CMD_INDEX, + MU_CONFIG_CMD_INFO, + MU_CONFIG_CMD_INIT, + MU_CONFIG_CMD_MKDIR, + MU_CONFIG_CMD_REMOVE, + MU_CONFIG_CMD_SCRIPT, + MU_CONFIG_CMD_SERVER, + MU_CONFIG_CMD_TICKLE, + MU_CONFIG_CMD_VERIFY, + MU_CONFIG_CMD_VIEW, + + MU_CONFIG_CMD_NONE +} MuConfigCmd; + + +#define mu_config_cmd_is_valid(C) \ + ((C) > MU_CONFIG_CMD_UNKNOWN && (C) < MU_CONFIG_CMD_NONE) + + +/* struct with all configuration options for mu; it will be filled + * from the config file, and/or command line arguments */ + +struct _MuConfig { + + MuConfigCmd cmd; /* the command, or + * MU_CONFIG_CMD_NONE */ + char *cmdstr; /* cmd string, for user + * info */ + /* general options */ + gboolean quiet; /* don't give any output */ + gboolean debug; /* spew out debug info */ + gchar *muhome; /* the House of Mu */ + gboolean version; /* request mu version */ + gboolean log_stderr; /* log to stderr (not logfile) */ + gchar** params; /* parameters (for querying) */ + gboolean nocolor; /* don't use use ansi-colors + * in some output */ + gboolean verbose; /* verbose output */ + + /* options for init */ + gchar *maildir; /* where the mails are */ + char** my_addresses; /* 'my e-mail address', for mu + * cfind; can be use multiple + * times */ + /* options for indexing */ + + gboolean nocleanup; /* don't cleanup del'd mails from db */ + gboolean rebuild; /* empty the database before indexing */ + gboolean lazycheck; /* don't check dirs with up-to-date + * timestamps */ + int max_msg_size; /* maximum size for message files */ + + /* options for querying 'find' (and view-> 'summary') */ + gchar *fields; /* fields to show in output */ + gchar *sortfield; /* field to sort by (string) */ + int maxnum; /* max # of entries to print */ + gboolean reverse; /* sort in revers order (z->a) */ + gboolean threads; /* show message threads */ + + gboolean summary; /* OBSOLETE: use summary_len */ + int summary_len; /* max # of lines for summary */ + + gchar *bookmark; /* use bookmark */ + gchar *formatstr; /* output type for find + * (plain,links,xml,json,sexp) + * and view (plain, sexp) and cfind + */ + MuConfigFormat format; /* the decoded formatstr */ + gchar *exec; /* command to execute on the + * files for the matched + * messages */ + gboolean skip_dups; /* if there are multiple + * messages with the same + * msgid, show only the first + * one */ + gboolean include_related; /* included related messages + * in results */ + /* for find and cind */ + time_t after; /* only show messages or + * addresses last seen after + * T */ + /* options for crypto + * ie, 'view', 'extract' */ + gboolean auto_retrieve; /* assume we're online */ + gboolean use_agent; /* attempt to use the gpg-agent */ + gboolean decrypt; /* try to decrypt the + * message body, if any */ + gboolean verify; /* try to crypto-verify the + * message */ + + /* options for view */ + gboolean terminator; /* add separator \f between + * multiple messages in mu + * view */ + + /* options for cfind (and 'find' --> "after") */ + gboolean personal; /* only show 'personal' addresses */ + /* also 'after' --> see above */ + + /* output to a maildir with symlinks */ + gchar *linksdir; /* maildir to output symlinks */ + gboolean clearlinks; /* clear a linksdir before filling */ + mode_t dirmode; /* mode for the created maildir */ + + /* options for extracting parts */ + gboolean save_all; /* extract all parts */ + gboolean save_attachments; /* extract all attachment parts */ + gchar *parts; /* comma-sep'd list of parts + * to save / open */ + gchar *targetdir; /* where to save the attachments */ + gboolean overwrite; /* should we overwrite same-named files */ + gboolean play; /* after saving, try to 'play' + * (open) the attmnt using xdgopen */ + /* for server */ + gboolean commands; /* dump documentations for server + * commands */ + gchar *eval; /* command to evaluate */ + + /* options for mu-script */ + gchar *script; /* script to run */ + const char **script_params; /* parameters for scripts */ +}; +typedef struct _MuConfig MuConfig; + +/** + * initialize a mu config object + * + * set default values for the configuration options; when you call + * mu_config_init, you should also call mu_config_uninit when the data + * is no longer needed. + * + * Note that this is _static_ data, ie., mu_config_init will always + * return the same pointer + * + * @param argcp: pointer to argc + * @param argvp: pointer to argv + * @param err: receives error information + */ +MuConfig *mu_config_init (int *argcp, char ***argvp, GError **err) + G_GNUC_WARN_UNUSED_RESULT; +/** + * free the MuConfig structure + * + * @param opts a MuConfig struct, or NULL + */ +void mu_config_uninit (MuConfig *conf); + + +/** + * execute the command / options in this config + * + * @param opts a MuConfig struct + * + * @return a value denoting the success/failure of the execution; + * MU_ERROR_NONE (0) for success, non-zero for a failure. This is to used for + * the exit code of the process + * + */ +MuError mu_config_execute (MuConfig *conf); + +/** + * count the number of non-option parameters + * + * @param opts a MuConfig struct + * + * @return the number of non-option parameters, or 0 in case of error + */ +size_t mu_config_param_num (MuConfig *conf); + + +/** + * determine MuMsgOptions for command line args + * + * @param opts a MuConfig struct + * + * @return the corresponding MuMsgOptions + */ +MuMsgOptions mu_config_get_msg_options (MuConfig *opts); + + +/** + * print help text for the current command + * + * @param cmd the command to show help for + */ +void mu_config_show_help (MuConfigCmd cmd); + +G_END_DECLS + +#endif /*__MU_CONFIG_H__*/ diff --git a/mu/mu-help-strings.awk b/mu/mu-help-strings.awk new file mode 100644 index 0000000..81f4606 --- /dev/null +++ b/mu/mu-help-strings.awk @@ -0,0 +1,69 @@ +## Copyright (C) 2012 Dirk-Jan C. Binnema +## +## 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 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +## convert text blobs statements into c-strings + +BEGIN { + in_def=0; + in_string=0; +# srand(); +# guard=int(100000*rand()); +# print "#ifndef __" guard "__" + print "/* Do not edit - auto-generated. */" + print "static const struct {" + print "\tMuConfigCmd cmd;" + print "\tconst char *usage;" + print "\tconst char *long_help;" + print "} MU_HELP_STRINGS[] = {" +} + + +/^#BEGIN/ { + print "\t{ " $2 "," # e.g., MU_CONFIG_CMD_ADD + in_def=1 +} + +/^#STRING/ { + if (in_def== 1) { + if (in_string==1) { + print ","; + } + in_string=1 + } +} + +/^#END/ { + if (in_string==1) { + in_string=0; + } + in_def=0; + print "\n\t},\n" +} + + +!/^#/ { + if (in_string==1) { + printf "\n\t\"" $0 "\\n\"" + } +} + + +END { + print "};" +# print "#endif /*" guard "*/" + print "/* the end */" +} diff --git a/mu/mu-help-strings.txt b/mu/mu-help-strings.txt new file mode 100644 index 0000000..a18a93a --- /dev/null +++ b/mu/mu-help-strings.txt @@ -0,0 +1,198 @@ +#-*-mode:org-*- +# +# Copyright (C) 2012-2020 Dirk-Jan C. Binnema +# +# 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 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +#BEGIN MU_CONFIG_CMD_ADD +#STRING +mu add [] +#STRING +mu add is the command to add specific measage files to the database. Each of the +files must be specified with an absolute path. +#END + +#BEGIN MU_CONFIG_CMD_CFIND +#STRING +mu cfind [options] [--format=] [--personal] [--after=] [] +#STRING +mu cfind is the mu command to find contacts in the mu database and export them +for use in other programs. + + is one of: + plain + mutt-alias + mutt-ab + wl + csv + org-contact + bbdb + +'plain' is the default. + +If you specify '--personal', only addresses that were found in mails +that include 'my' e-mail address will be listed - so to exclude e.g. +mailing-list posts. Use the --my-address= option in 'mu index' to +specify what addresses are considered 'my' address. + +With '--after=T' you can tell mu to only show addresses that were seen after +T. T is a Unix timestamp. For example, to get only addresses seen after the +beginning of 2012, you could use + --after=`date +%%s -d 2012-01-01` +#END + +#BEGIN MU_CONFIG_CMD_EXTRACT +#STRING +mu extract [options] +#STRING +mu extract is the mu command to display and save message parts +(attachments), and open them with other tools. +#END + +#BEGIN MU_CONFIG_CMD_FIND +#STRING +mu find [options] +#STRING +mu find is the mu command for searching e-mail message that were +stored earlier using mu index(1). + +Some examples: + # get all messages with 'bananas' in body, subject or recipient fields: + $ mu find bananas + + # get all messages regarding bananas from John with an attachment: + $ mu find from:john flag:attach bananas + + # get all messages with subject wombat in June 2009 + $ mu find subject:wombat date:20090601..20090630 + +See the `mu-find' and `mu-easy' man-pages for more information. +#END + +#BEGIN MU_CONFIG_CMD_HELP +#STRING +mu help +#STRING +mu help is the mu command to get help about , where +is one of: + add - add message to database + cfind - find a contact + extract - extract parts/attachments from messages + find - query the message database + help - get help + index - index messages + init - init the mu database + mkdir - create a maildir + remove - remove a message from the database + script - run a script (available only when mu was built with guile-support) + server - start mu server + verify - verify signatures of a message + view - view a specific message +#END + +#BEGIN MU_CONFIG_CMD_INDEX +#STRING +mu index [options] +#STRING +mu index is the mu command for scanning the contents of Maildir +directories and storing the results in a Xapian database.The +data can then be queried using mu-find(1). +#END + +#BEGIN MU_CONFIG_CMD_INIT +#STRING +mu init [options] +#STRING +mu init is the mu command for setting up the mu database. +#END + +#BEGIN MU_CONFIG_CMD_INFO +#STRING +mu init [options] +#STRING +mu info is the command for getting information about a mu database. +#END + +#BEGIN MU_CONFIG_CMD_MKDIR +#STRING +mu mkdir [options] [] +#STRING +mu mkdir is the command for creating Maildirs.It does not +use the mu database. +#END + +#BEGIN MU_CONFIG_CMD_REMOVE +#STRING +mu remove [options] [] +#STRING +mu remove is the mu command to remove messages from the database. +#END + +#BEGIN MU_CONFIG_CMD_SERVER +#STRING +mu server [options] +#STRING +mu server starts a simple shell in which one can query and +manipulate the mu database.The output of the commands is terms +of Lisp symbolic expressions (s-exps). Its main use is for +the mu4e e-mail client. +#END + +#BEGIN MU_CONFIG_CMD_SCRIPT +#STRING +mu script [] [-v] +mu [ + +#+end_html diff --git a/www/mu-small.png b/www/mu-small.png new file mode 100644 index 0000000000000000000000000000000000000000..da133a65d9806e01057b99208b55cb226b91c39f GIT binary patch literal 6613 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

>eBYjrCr$N$!i=C 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®fc!tw)ZPS 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 CAil={ literal 0 HcmV?d00001 diff --git a/www/mu4e-2.png b/www/mu4e-2.png new file mode 100644 index 0000000000000000000000000000000000000000..eade6d77338482eee54759980be826ddc8d85f1d GIT binary patch literal 132879 zcmagFbyOSs7d?s;DcSkCOty00(HrVj>^ZWk0N>8`V<;_S6$AoRWs`xF#vF{4J zmX)PucT40@`t=7hGkRFFz3=StHTdLWTGer?#cqDxZ?`Cg`f(LQ!Yg26yWg484mK|J zJNVzbh{!i4l{K8!)OrPRKFfCKp8lkjba&@tV{425xyfd>huZ&Ut^ZQn(0j8l7@LH8 z_0s3f$-h^=o>(43mIuFj^$Mf8r3I{@%9uc7RBMbJv+>6r^`CDj88(CK*X_8)2gs;J zGS8o?E-%k-YPvKNuKjW7VU})TDDYn_zL9@3I4D6yYqnRy4SOMZu!bje)`ir0f8TIC ze2CAOP!c7^?AVsNXC|x*TY-%zgq_ACnFmNxy+?ULH_$PdCr34=H1Xj0v3YY&y;@`+ zhuS_I<&S-bhF@3q=;8Kf!wRF%Xz#hxGJoC6r^Nt@LCMs2*$VU7FMQL(tpfRGk;96u zkx*ra$?cYNcZ2jXzrKKXXNZGe#oF(n=i2sffG*ElRBrf*`8Uo9yR-ZztwvbV zlvTV=kUtii@#${T4`eH<6Cnb-UueA$HbUvMlP9IJp`fQuM9g708vjNK6Fq3I89@8O z_-FhZR>MwG;~(zG^?bCFm~p1(7Y`C^+F;+nu`#-P;I!ac)Op*U2BbJ!2Pw4cIu+U0 zik*g!XDj#0p`?uGYl)XIO^*wjkzl)UhjPCJ$7bbmPe}gGGsSm0J_A4X-3Kj8J<8^R zhPM!d`*n`ky1YCzKEY@n3C}kqIsQlnj`vx|_kWO==VqjF@Xu2y$J1y;Vy9PlT;KZ} zg09l&uJ`UoR95#YB+$MKt=wa$_+3A(367Uu18ePZ`D+~ajoQ{f1o=`wVp>vNo8>}X)j#t()BW$x4Q2W{s~DlntRcgx%3gs07+hId{kbZGy=espMqNy zJzKjyAi|Nb$<|ZAoJ^SdgBC|J1AX7qiJP6V7A`5XmSb0;p&$U+xws3T zssx-844-Uk6sTMaU1@cmv5wWGw)OXTE&+#*%z)RQbT03w7q8|Yh8k(e&L`SKN^%T- z?xlR%)GU@tf~rBxYrQ`f`+iE>y3gl~XPB;l=f;G3_ct8zVlQ~@kKKIGyuYpbr+Xsfdw;C5KO zb|yE5UUYdF!aBkH1I2ft1=RV`$TH+p99(~ia zA{1-W6S%>)QIPWZEZ|eWq*j+EBW!+#$YN`~;C2iDXr#L1u1IU1e@p82GB$hlAma#Q zwO3Dk80>!m<2uHU7;?&PJFKu1xp>EJ@M*wU8#+n3(F;1xPdE``)EW`T4Vb*1DxIb- z6ZJofWkb?`_<0?GCI{M!a6W`Y8wownNnoIkMWs*KmETOlW}X(SP!9HL`A7upOE(sZ z;W^+Yd&n>ZM!mH+fGRK$RDN#4;(Mr-hq`~N`Wy_|AmjJjfj(1GPgG#Rq#MZIkCrcA zxL8j}#!q#WHe5M0kx9bBt3KHNjB5w$^Pn`|PKY_;ds-h7q4^UX9sSkx=f$=0n`X-t z-K^y!?$|*4lHUS{&yZNyK@us8r5!Ejj*{2MT}mKD4Pl`^LT0Fx)8NeZss9 zxWk~mkCdT4zJ#yYaUaVqZ+)s+~3{XBj=Y8KBx?QDH#St z6J~+O-=C&!>+DQpfJmZcF+k0pZ4L)_LaqjF_ro;x>^3LSIS+BM)V!!;yJquiZ}D1x ze*Tnu4l;@-@gbxnbHkUn>=n{J9}r5ZyUhZ0J`54+`|Z=T?fb55@;u!+kHeFqN&?en zIjUZhN7pM6-eg|OXc19DXstzBi8wbhJoFfsugQ-kw&s@3oNl-vb!WS8<=mq@0TkcK zw`7G<{sutCpQI)s`=1ctdV)e0iW7Hdl6TeM>;oMiwnF@w zAk-c3%gx=AoN?wceScL5WrOcZ)jybH0M$hlFhohzC7zIY5|yL&W{AkIby}1BRIM)r z3P7F0kY-FXUl8&;44mOiTe*3pv9dbOD=A1L$+@FgxjUPm2i_TVy4>0crC}#47Ivgz zfI+toBcMYiIV7iZPw>RmvS7Fq3mAT@B^c9R((O#4+B2y4M8Jhg8eUViGWX$#20Ne@o#!KA z=508IoS`>nOHFHPg~KD;)AeA(Z8gu$bfPs)cbrihcue)_hBN2x zN7qj8Zl?F60MgBJsKx1Y&dT?e-}Z05q|7VD{FzSivmL!9i=}YrN@VHrB)K;5rtYCI zHF_QQqxKwum{LVt@%mHaMWR>mGb&KgwT(X<;^?|~j9%kUI??tTm@dMsL3iblhQx3l z6V-chOquO`(u;wg;b2j^I9Z&bbVpxguS@K?mc%-C?ag8BssY0XKnWFlg# zZ{N9~tmB$*gtcMcg9hv@r^S4OPR1 z=eWlCvg!)6VB$=zU55JYL)A*r7J5=iWAecCih>vklkeNx*&zL4w;z6~?c7wAnP0tH zFoPv44LXto0|PsYEB1xoym`~u(z4CBq(42bX?%gti=NR^5fT!jiR7{#{?@{`5*tAk zeIxt&`jB(rcX!21Z%qY1s;nq@pOzTuj6Rrg#{mcq;Gz>n%Y*)CU>htfnQMt?KYd$1LpHVC>7eh53jnbON642kf~@dUzp~z)dU} zCYFFz#;8LNc$K83f2TPe;0;jqONtmSe{SIUt{Cz9p=9*Bjk*Ek04@c>w~L-!Zbh4G zmccx4sr-?e_@?KcP7>O7@oStN|JsaqT5OwU=oNTL)OfiVqvp@Ii6=aW^N#@!L0^dzYyb0OcQf&ELW7tDKk)+vAS;4S{bbOv8AhjV z^Vwm6npw0*3Nk|dHXRe{k2I}p?dR>&hYz>gRl4~k+^I^ya3S`#4M)5A=5X-i1wnSt z8cwxexwrBz;L4dYdbG}Ap);nVMkM&y@3AuTw=bKW)7@x3orG$W!9+osaLM2=@zd#^ z`pX3#Z(~=?fL~h}f*bAV)a@H)NTT2e)R~;m6H-ty5#z2%)mzrBI+D`?77DAydqz(~ zSK|Gn+m9-+#4{2}OfD^#YGmY_+HHkuuXZwsvz5=CV)jWU-ur7k3G*TUoHy3T`pf)M znY^BOvF?MR1_BMB`eOk5?T(9ua>kH} zKJ*tq4>fY$t0!yaCAq}t&M|sA6+MD4WT7_0S1-4@z(a1ylz#lNEz+T*a!>aI3r`U5 zw_Ty_3%is)QvXc%nUBG;YYpk~>3NbQbWVcWVuExzOp zwWMW;fyB0pgM>E(DrB>ZVpCzuX!nE;n^=o^a$31mHOn6{W$kGjF1IN!w@r2ZK3RF= zX{OSXRmM&~tJTjz-I`dTDiSLovhqix#GqfBrZwSnN<`AZ>YkLEn#&Y^T8dBXOW*LbKwO{~;m=-(Vl zP)-m4qJGmi@Vrj(+R5MNvQOCOxT7%Y-u{dfv28S*GOX?5-BYq29c!ovr(4+`AegA# zw^)1%S5-URePuV-nFhXJRqnnFXTbnH`L2X|S&WI?!>{m98b;VD0L_rX@^*{wyoqsV zS;vP@TN@<3a-V7)`Xe*7K~K5+&CR@)PdT^OIuChl!*3!L(MMSfy|^ZuCGb)`jeeGR zS@&lw`V{wTi~DP<+}>OYk-QM!6sd$=Fs=yIrEp~XLIaLN-<`X%cVuCMA3gc`>^6eI z%O6hDDIiU;WNBswVt)K@{qOLq;jjrgeM_hxrCpAku$+U9Sb&5?Lps$MfUq6hL4I@- ztI1DBXh0nF@F**sUBx!m$ZNk*=F7e*M`DznC9&vesmfHaj+V1^z1{yaG&}I@cI7k; zt?YB-Z<1;{u45ZKCcQqsb3nC!HDAX#M~??Nje!R#jnFYlxAW5V?Kz>Xhmru)cH6jT zEv}nluXXdB{Mm*Gjmwf80^kzl+K#*7nVS$Af%U*yzNSWA0cUublJ{flgZKF^z0P?} zWc|7CN?R6?Mt1~O0gkDj1Dys0XWre|i0iLWI2!~MT~1r`Rc4WC@TO-pTeftSIb)!u zqr`jwEFB=P0H;U~&UJ8-WuLs;wnTDZ6FQ=P!cR+!@1vClxj&ayNLc*>ZEgr6v1W=# zZwojU%rxE*F}I?6UVPbAH4e+MY?n9|+f){JIq=_Do_M^ikH)Nc1hM6`6(qJ~Kl~1Zb4>{ePPKLU=+SFE z#2iZ>tQdP!{1f*yUdDD-^bCQ;)5X&qk()l;9#eo6MaX6@lkgY-hCW~Nr6)_QIEpf8 zZ-LCt)~2tj(Bk3XX0Q_eNVxcz{qD22L7%gc(T}^5?o5L>lWoD2@UklYwINtMd-@C5JD`kG7SqPMKL? zJ6;*O-2gpg2v)3z=a79NNc9;o>BmE~da@e@Au*eE>ip25b;~d}t8Np1wUGnJDsK4qb&inkP{1c{aj|J#WG6 zD}cdEN9}^2{pN-uh}w%|KhuA5S21C%xAAGb^z8U*39YB~TPXV-dr#{Qa&_kheZlAJ za;cHFllGPA#T16c_H4awkd4Z%Q0K3)G1X2f?w9KlJ)KsK9Xt+ZW7j%wF1_Xp4K z2>e7Jr>0*ZvJedPWry86cv31<} zl7gMa=%|OoQ(tm2aM59P{AOsv+O1sZ{66v)ywVjC@)pc@MMe45OxF9fm*Rvd=UbLQ z_PJf-_7CY}qai1V1hhV_vhxa&aR+=r<}Mo{_v& zeBgErw{3fz&_fn{>~uUkDR-BS=l>~BqWW|SX~jxLuyq8ihQb|MHgc=R6@ zAXLAfJmms;_)Yp2{!T~QH=thsMLjQOTbp~-WE$%wSMbx@-{4zYO5g97OhEYQrmZ8j z$HVA0P36sNOCu0g4=0w;VPHl8#AP{W4JUcX_?C=$#Z1dULuA#}bs7&z-1Rut`|O~m zZU@6T=IJ8(dqdFHezGdfNC{q+s^j8lwMa3D^4fs9^^URIeJ%9n{>nkIm}6^0`zhR! zQd`WpW832~Ifw*==lHO8|3@{4jGrd$SlshT)%#RKyKZNT(T0R$dmJv2p^;|PR2m&A z;eq8S;Gxd%$Ca|^0XB?nEAL3_KEeESziTO!V=1-yN*3&(I`eqg-i64_Y9NogH`UQK zBDkIVcd@5GU1QeCBZO{US5OUq_zV0+QnrGe`&GcW-%c&EH4SKNzSH}TN-(E8T133= zTgKBdi~hx)2x+zC7Kbl~#N+;%hIHSl0Gm zfe-s5q=#-=$NzCvOs;tKScFRRpIrO~86l1SC9$ScJ4kx`j+uL)e;GF2GMZa}6uyXQ z`T1Xpi#Rw3v9|?rz6$u-@28PP^6$Zcj(`i~{|L1*`SbVxeQbg(LPP!M{Xk(HlJviy z$Ysrd^nX5e^6l%%!Z>r^4SwPF1ug)#lM^Kd62$qJJ5>%;^*c>2r;fag?wj&*6cu4K z;OqJ(h%;sA7;eVS?jiL>#|#~X*8wFYud*<+tzkQl={RPiu>v7p>&a1+m#cmH7y{iN zf%E^a@lEKD6-{5xUK+7*{5ElaeQ~vV?sMwZNzYD!7aA^|uc@UKar7 z;Gsj7@4u=_Own>W`4C!!8u^8FWPlS8|MS_{n21ix)$wSVHq!;K>7bF!B_;aubZw$F zVO*D3;D(^xa(mo+6FNADVMMVtQ$&3F6msf@AYyBd-VmINiMEIF9?cEu9orfAb_T;i zF9@P#71DT7nIf2pO@#auLhtxq(mY*Jm%rk?m=F_-Cf^+nX`?J zO?~f)u^p^ffJhSRZh9&xe*6PjiT!mPW(W}P5hyG&PfLZ7Qmmn)lbT{5E32(4Fsn6d zm7bhssY_f{RppKU{w$BfrhdH_P`N~D;jAkJf2HMgF=f3&o{HrbVs?K|11n{nZ9A)M zOC)M779K&Q&ecmof`G>6CZ{<%xfiMfb@tdWl_kLvhg>$N_gY$_4*0Ic?wlp{DdvCP zn2J3OYI~!`B|r5WQA@gK1>{jCrigZ347-Y+j}`RLNs8xP9%;I9$-PV>C zjweA7F4!ful$xA|8>rmh$BV1aP7;y7Du@>@P1(`G#b(u>QC?4uCv+j$U3>3W37hOKaqx+w5N`{U+DcK; z%|=wf0}&7G_m9^X37Pkg_%EVm(eHhEar&jziIk^*h_`uW`m3JVQ}pxJCe)ab#u7SJ z^{aFS*Q~qTzal{<|9K>Gl1#L!7Es1YdL4s+9(qdm8Lrau_HzqyD$2nPXKL?*iNxeY z4P9NaBm2$#hK>Z?hHZkFi##T*_TqwFVPWC+;(TjitFjDjd9nFHk6QZ#D^>+-1!h}l zcN$dm@-nz}KfA+vt~t6NPbhI(Ma=$3#*G#4u*Bmnz9H!LO|fdmkmWcWXK--Pdqjzs zd~nlaPLBTuH?0-Dl3NtwqwBm1iV$ z^K}2HA;QPknI|9b__+59uO?H)2#)6upK&ZLWBZf3L9DJ0qK!ZS9GWb9?UQAD9hr3d zp9@*ZP4Ovr?>b-m{@HAYowD~&L@FYrKM@M((UpOT z3D@N%Puuo#4$l05G}M3+zMLRatip7C7BYOU#vLa_?0cF0~>DsLOWvhp~>Xp^g zR-xNJ33Hv^JS~epJlckj?kHcrjHMw!fyKWzFe1W5Md;R?-+tkTk)Fqdzm}!}-ZE%^MnGI*ocIPz1Oqr%!s{=sa(qU3pqs>y>F8 zCiQVPl*X7T#JZT8VUAx$M#c`-9sQm*p!)b=`tUhFWAIe}KF+P?e(0IDHU=dSZzAa%(y?L=gQg%M`*aE703vR%`g8w+Ci9;J&34Ou_h{HwHVeI@x(#YXNqS%} z7VQuTS>JVIocbau8UshIRD@`IYj`PO}Xo% zv1+OqH9mU_HUxp3EPAj_PCfzewAF&jeDtNwKHh}V2t`rif|3rx04rY6o%Z(PybjTu zPJdC2IXT+?Ll={D^avD(meBes?)Hw3($cy4w*?g)8Rg}QtRsDO_W6@@4owytYv$vw zki4z})H$+m79(?C&d%I$f0#d`eHgEriZ?yTk87C+zmF-yiqWpJ&mZ0}liENp*6z^p zA27ACDQCtaUOV+s*Lp>7ZB9e2rJ2}p|Km+(=N(nH|E@K0;+W}XI@LeID``r&b>QrA zh{@{ouhATPG$M}d{DN@Lr>tLBBbdLRT31Y+YvDT!F3c7n?BxX`u4O%}X&q)kDSNhDi`_bmIX5$qQ+Q(M@?4?Kd!pBIOo&ob{?7Jy<(k>Hf1vL%oN7Y+ zy62$YGRGYc|M8L|Q9Id;lrc`87Y2TlGk$*}*Sh&z@5D=VG@UOaIoZNuA}u&XqET=CC&4dk@kL61o8k82dc^Uc9PayL)Uc=-WL;v~+b{*NR? z&oHlpnVH!T>HHJi$K5dOjI~yQ#N{Nh#`@no%pq6TjJq zOkZY}qRe^eI}9r-3GUUt5q&(+qg3yrsSvP3!OM=n|66JVl+_4Xu}N*#`TH!m?U z(WE42ul)0)EPK5@g%$#}%y!a4%57NnYs1d!vAUfe(HIC$59-&P5Ez~y&%imVi5r$* ziXe^m{u0`tL#$8t#%Oq0=Ud}NMMY_C=UeL@zDS{IJeI#^W~A-ysg66(@n9{E+YvPe zTn9VyW{Bm@RF=_X&iz42&$XOJa_xv}sXtEq^`z4t{Jnbl?IO|AA9qjB^~>8y-Yj$O zWMOCm@wXq=ep<6?e9;lZA|7M5zQ9aJ*I?Nt+U}ZCm zHz-Ocbs;?ebf7XB65~h3shp7?&)x3p!{|4+imR6{>R1dkG?||> z!h!jMf-!-xjlA640GadRb4aMsKvnD9++6mdIR~O`h#DN=?N!8}eZS}E)*kEhRFZ@j ztTWE4+#h*#wVnzKyAu6SdH(VqShC6@j45+z!obH1yf+AE8|jljTIRaigc?$MbP=ZX z&>+!U=eC^-*f7+6@AcB87#}jzJjL25Dn6{4nVp^5O|uzJ-|h_}ZWbObLC8LgjcuVE*?TsS3MSU&o$j*U4EpGZBc zWtnd5ZGhiPB~vB4k|(FFFzS@&zX+E_WLj#-hlh*Zi;JsT^QSkd$>AocI>}$G)5<82 z3?PT6h;y8*@4hy7|5ufdMzTBve`UivbEYreMLda{K7&I!L=!E%7~1vE^}5^ zmZqj=t~GgZucVKU&k6j2^e02i#;>JWDJ`wdTn-wl*irB5++UNEaqXu7fsu-GMKqDL zN6EBJz%&EGHJf|U)sIf=yIR{zcD@&}i*xRquc;;6kI&#K@1g=jJ)*8LRznz!T;7E?sIa6%toi%o zh9^VU<3}*l!jY7J44-O{Skp)odf}7*W{^EBwONLjVB>*k zb+LI!>ljF&jsioi)*icMM9I++b6UBpmWy=JTg6M1`gI*}7&EVA0O zT!{eqFYg1Y$5n<|-XUz(#H6H27%XUFyQHBYVQPxNP3-BI{}7ywUx`cxGUtWVA%-Jf z6UPGn2956&Mi`1aF6iX{WpfWqeU*mr;La8W`OBoFd<|6$zwD$uGEZ zf@*R03k+2=5~ZOR4gyPbCGn`}eueH2sz^A^>Dngv?3~@(IyRUnv0x9!Zp;>I-yVE9 z&S<>H`ddT+i;&Z+O&^@CR+h6CasQcfp%CMaC}?O;RAc0RsRU+*N{Jlv-c)Gr$5 zsb*jxqvigJx+U~?Gk>$=%6MSgxo)k~OX}Fr<>eP?Bw|~7f|P5?uuq%~{^$sMJGYLD zZ$S$&q#1*Hc{x2lIrC#wm&e&@>iBsZcTInF-#8KjK{R6V0z|2m#B#N8m8WxQUm!u~ z2*QmS0Ibt=#P)+mt0kS4lsRCV6;za6+QR&ht7b-&;NTmOe|}sy-3scuAl|7?VqhRr zvpu5W4>uRB38INg2I?Ll`uVG74{i=0x3;C3vD6QGdKBfw1bc@jkl$7FEAH0bWYd`#B);4&g$&|7Oge0#Ubd573E>U^r@%MlC-pTOw5kztQ~LhC>B>d*@dI=L7Usp=qZ@$ zw@*f&;yb%N-e6GajQ0r@m8SO%g?#$d)f^6mIu^<20H$WFqV3IMD!x3y$8kaXA;-!# z|7cZuj8;UIZY7g$wR!Js_GDZl0`p5z1HUOhU5t(?ZQ=WNr;Bu5Oeu;xE$kvn6-pZa zT$-n{;DG7Ng@yDmNP&n*M7&|)%E$rtHO1f{u(QpBD(7Zy``_oq8mY!4EgJWoH~MAh zS`$^M7q4Wgz*k`U+$Vq3Z*q?hm`zPh${G9!F_j`!yem7T3YXW;c6FV@2qD1U|0!uP zgW)w;jv;htkG&FTf-*zf^`mdwDmKXvd;*sw^rdrqqZuDlUgwI-hg86qTI-<<_-|d0b*W#_i z`=5qNQ#&&1ltj}~N!=16eQXDqHI}+s7&PLK(*C|rIc?k3D<``X{th3{|B|5tGoLyvWNw&Rq^FGAYGWcwaaB4&Q&eY2@wJ14=x z6t5Q`-Azv$-9Ci1Y+Pfc3Av89o&jO}&GwTpiaySGuSM$gg$xX;5N)XY)H%C-+tE!^g+pT$dd25?YShm4;_nHvRRqSnWoCx^T)o#S} z_knJsXCs&II3>0B9}`5|ie>LC<~&Eoo&H|W#tM5)9Q`s}nu&?&`?l((0I6NJ z33*ux!4Vzu4|z(+P@O&H+gIl05m@DlmX>e*je5UcR*@>m`BI4I#3m;bC$kzvz&6&3 zl2|mno9+Mh33iTesUuBvi7}{MFk?1OhAL`4e*PpYr>D1!@-0u$!zNKoMys^4bksU* z`QFZJ=W}x%4u$AE9t_O*)Vd*A4L@Dcefa$@V#XBZ2no&SrC~%E>C3*Kn7H8rT(1G6 z>QUF+Ar>=nLtX83>;vY7zoTadXe;h$Fcik3{($ z7Je)Wxz5*n^XO5K3+~ffn&}cF`q&m2!k5VO9Y^?Dk1GkhI9p=?Ha%T+1xKbtwiag$ zx?LCU=&W8l27KG~!k6%!d;qjWXvZA&kA&P+1kZ`kO)(){OdrKSVDGozk0z?%o zHbl|Z;Vt6u(~!qyL})IjUX%bR7aPliAts4<4aqd`q-M05BZqj7<2Gk!!V9DrVAwLq z>CQmFLu{=0ooay=`GqT-4*^US6y8@!fXe0CEGUIQ;D(x!#_-hOE7mN56zOeQe;4>+ zqH4xZ5fhp_+nUo;*NHzOP$MM;1!kobcA073=hBFd?2nyfy7Ah#E+LgJryB56?2No7 zYWf@VPkYy)qBL2*s30b5frIyJj~&b>`=gmc^j(MkW8V{%U8&J(8@|Ze%o$=p6!`Y* z>@&2D{DR(pc*$cqPIe8*vxk*_-W!{g=sc7&(^*-VpXbA89a(QROF5qd(`?o~i4I*@ zUxH3%@Ym1pez{TAKqI01GU`N#X*C*=?T!2GaERB%%2RP;Vs?C{L4n9i>{>Fywd9KO#iL0aJB?@Mp=^t4Lo0X$^BYV7$)n9F7zf zm3H?J-@L#)`F(fU>PFIQ{7qU^MMmotVy5x4`Uh1@k}t+|09bPZFD@1;a+G=e`V`$l z=H{eM$PN|9NIgQ!)nN^p=fLo8%tVEuWNd7#(p58QFI z>fEs$1~;#cI?pY=I>im~F(!FQEWsE3pv!d*SEwU+Vl=IR(Hzs_AC<3DpqCpbD1AZr zcjqlS2CJ@cF-3_de>XtJ8_nVl|3OD6CaBmNk?ru?ZHcEoLRC?Ltwto2FSM3fmt}TN z+`lvWPvn!qGT3VBuxLQgNEA>@&;1Fd?cUXPHSThnYpx@)b?!4gi%%>|c zIr$_HKQp`ir3#I2EJTWvw6L}op~@nJPJ|-B3)twV5k>8n?=o24bXmLfVP;|?^@MDg zbMqZk<}=M-(7A6wmzPxpDaWZpiGc5U-t=?U^XVbP?iSy@<=5HRv5-i}1|Y@p9p)!3 z_xDCAWonxG%C;Ij!7?8ZdJQ5!5I!X@d4cd!V|itMU~@6!_g(}eQ=8@lBrL0iC3r21*CeTF%=!iU^%%SR5vRWVC83!UA83S-k==65P-#o;ET3<>DPaSYk= zFJcE37}llDxIq3iG@=hU)Q{UMyH@kP=aYuZz5^zs*?d8AG~S6E`cAz^U}Z$Qhtd6M zdY-%?=;q-;a6)o2XBO*n{Llm89&=NQayu`c349RFw(M4VFj6Oa_wHSqkRPLcRn^Sw zZ1nBeFv8Qi@)Eokll!P{D5DL%k*$8m&ThKg>D?-p?Yu-PTcEzkPQs!s-f})@{s7Ox zNo^Uqeh?nEO;_P1A5%hFcWGl{V|zo2V@g`)i4ZtrMmEW7Yuc+d^!1f#Uwr2UC{HV+ zskO%_LC?>K4-irfN@G(KZt34?&(vfEPEyL&K$Q08b4`9g0s^`zC|hjsw+9U zeNfI23QDFD*->DeBzlzsky?uKaWjyEx+6ruo+2e{#CVt*(^qTVopf1iZ=r0r=y_>! zhp^?xbMB`rI64iAkal_b`l%P<_6k~C&42mJW*HbHq?b5rBwo%_KHHIQ1J>Zh>Xtmizenc)_b$0MxcJSGtd`chcPz|oEd9J=c4JY+)~Gg&2J9rR zB&v`~gKdZng4hIlF zaa{r281y_}$!9miWId|2K5&0iarm`ZBX!0PlUuP-c6heQAyftS1${W#rChsx+Lh2P zYgS>AZ$8a@0Hku`tm?ybE62PL?;&il8?*&fjEzn8iiv<9zK;0q?L0_yLOO7DoM+kn zr2wbFaBH#ZAb-=(`Cu)%>?q&cTNHo$+|b|P@9i@7&Y;th^>QwaDC_S>V2WzT6gN$Z z+5dtCXW8MZR)i3wX0ocJ8mCtGug~pLFqhE20tq#Vxn-8F`L{(GUng#H0>eNmtY}a@ znVUu?ss_L>J0I1(_f1-z6^hR<$iBuLzuB$lx{l(}RYodm3Y*df&7J%1RJxv2GBchi zGJEJ!bZu^kVqco?Wx8zcf|j+bl@NC|@QnP)KBHhA0a`VxCeYBh7#4*;0ZhgGlH}|O z=Jts?WkLIS1R%#d%vqUQ9Dy%MgG5Ka)N8pcLUzPiBX%!*->vA$j`?w}GPmybJt@8n z#&zHwVH7G!$qq83-!^;KsvH%;@Vgpg!YsbBR?QQ<7)x-baj*HZyH?7yhqIGvKqK2H zu;K{w_Eb1P`$WJ>$JIAH6**AP{eW!Ajgm~s{_WPARzrGcozy}+W3%M9 zy_3HTL?qtw@X<)waR~k3BJ#yXt6B<<0Dyd=q?4q$cZ~U2bPVhHNRJlSKgUFFT-00& z@@IWrV?2?5`Gpv_qB^Cz;5BJ0vwtZin7eDVnvb^MKnjNhje|s^bvAf!j+6(!Bg7ln ziwS-6ca#R{)(bz()Xdxcp5mbcU^qQMJ_hK4(5hozv`w<1K^F)DMKlR8+$VXUy-iK2 z>xVXb2-oxl`g`xNaYB(D!7>5Agz{DYro?rC@YcFRJ6?E!J!_s@SGQh3BgE+rK+j&W z?kDsLG>~!`k4du1HNBGNfTfM@YD33?jCVt?L2nQ-G|%NDT2(3h z?OB7nej555(BkrA@dQTb%YxA{Gw@;X$?MG~2hloq+Q8O;{4<`|fXoGB)VuO;#-4ewK2`1CGaYaJ3>VIC8@MOrwnAa#(r zjLT}m$RRn=)yvN>`qc=TV19{qr+I99uydOa!jWZnQqEUqXQjl#7C6)Qqb_TQnz@|H zR{l6VRW^8zE6(jbPoPP2NrrRV z^To({#3DY_R{SX}a5NU&DnRm4lOPX%W4PXyNiq2H&H}An4C>ytu}$OjVGJ?fM%<7e_G_g9kVS9QqPLh-)Utj>0ewm0SjZjqu}1}P`KT7MDdStssU*6= zx}^*u;BemezE2waI_$KSd2{^6X8U*yy}iA^Y2DA50wO%!>8j(!eahtosfFxRlRCb4 zWtb)i)&?a%xQRxK-&3I6v|}^*)64GH8zfUzRvPTO_GMwECYireqd99tq=_kc+421@ z?<yRFZ=*C8^Qzv@h) zyaM92mgA{tbI<#xomLyC?vd*nPcJ#|a82Ml~K2L5h*k>yU8 zSc*OIn|81Q`?*8-WcM#h(XP`!Jbuv4*36|5VGTS5+*$O<3qTgE?^EcCZqeKKP8m`c ze(Iz8Fjd@^F0tmrEYdgxc&cUuK;!>C7@`ohhwp>TG>Cw6kA7ms~x_%nGc2}8G zU~7tkP(Lp4F7gc&6?ZF@SeLy!ViVU_jGt3BJBe%lTi>|eKc+(}7$<@1cHi}9wbmRg|o$&AxGer;x!knEyuM_eiB(~U02+bT|`rC!8eM;n7|WA$K64n z+$EL<-3V(YreZ&h3=-Kd5*EbL3BL0QrSR;a5JUdx3!#(1^M>20NJFe;_@uu6v2{;nlG%n$;{_ zUjf;gRq7#`uli)90TZ4Z@e3Ud<=qPZ&MInciggQgjvTzx8^#~xB?Xm0I?)jltzbX5 z(Q0(5asQP@luKA5ao{6W{7CywUF7p_!w9HzZ8`k~yUKx>Y9ByACiW7%5*)djuxTzk z6HZ0Y2X`)s(E8sjfaZ%8+Yd7`>Nr@=$SSmo#~&ObphW8JWNK{juD&~IX-aR8K(6wX zGYU1jl4})3UUgg+7gMfkC>^#t&E8n=s%sTixK0;sgJtKk8^14P2r;C%PgN1UT+~G^aR~It8JG2?pSEdKfX^z*!t#mHD!Nma@8bON5p`y2 zJ5613ZI3{)VOzJoCscgK-MSC&8zO7!pz22*$Ku=YmSvnjyMP_MgSLLaAw4A;U-jyZ zU1n;|Sr73>`ElW9mrDcNKq&(#@u}#Uw*6Z+$j@Ur1el~Ur3vJLH_j>;S7p8ufRs7W zCa|>pV%0gSb#%58mTeiZf3K|jb4`!PSY-lhsvfAbJnKFq zB}?&Y(MM3ZjH$YS7*BD2TG9(&dbB3C_oo#Onu9~Bvr^ZK&UjOQf9M~Usen{3aK?zq z=Jk7h;gNXWOQ>B`XexS=EJzikvKh4xF+_P*}&TipM> z-M(@)Y=+`?Pk>_%r8^XSOyUjnVI`-@Om@ zjwAVt>utxW!i6QmF=pk9?a_9^>ef=P zQ#YpbjmZ*LMi%-i^5-5WpV}{zRwe7>Nse~nZUfV#l3|NuA_9fsVSHq6g2k?EvwB6n z%G~x8#kmd{8Yq9Im`K9Hn=8;&GWvNtd~g}QT7nV%fnbjS_{%i@yip8Gc)qI1MuKU( z%{?BmnrG>q-}M@+EcpPYkEevl=Sg?lpis`lEZ0$T?p6Vz_U`pwWCY?06DxPid_sv* zYK>F3=IHN77?2)X@A;UQ9s0xREaHTTfs4L0xC%{^AUEk3I?P$h8(bDRKt^ZroGU1_bTOw?Qb1VDeFj-$5%JBJfIwsIFI^hwM@G4at?{hT6 zwuHBf(5fwk!%PFBWSP(dP%{iYuA@;D6alEtu@C@!0Y1CX&4963H5&K$1gz1PAlVVD zFUkb@SZBb69A5TvvZOZOA-$qBkyv)rJw}6q(c8K`4Tu&*Acc0^+B){|W3jAD+D#oF zP79-Nm=iJ@c242vm;GDa&&!sW34D{Ir!q8qu~c|iBd^*Y_IW{FuVD*mGz`?>@;elqJxcd zc{tr<;91uhFeS&^S@JLV*4T^PvplW$!=fA!?|hBDR&_o#>uSbMN>@|Ax&si%0i2+p zNXpF+4gG3hT+gtF8wx8P`8fCsSoWiLh zOxU=GzuF9DZzG!WKWo^U7=I35*IP@}mWnd0ax*MTa>TQFObDk3Erp-U7Xjbe056!? zTN`Z2PDb_Ug$1q{m8n|YJ^J8WZlRaW5|i`3{B^j=s<=jGXg8NwsL6wYPZwF7!Qq^$ z(e&91<+Z4ImJoBsENeui7HEhV!Jfk z%zXRsaguF91E|v9utkoN7M1%3`&?bgPQ(4h=2-d`e8#xQuN5B0b_aIll>^y~lu{Tc z>Oy?H7OK^l0){5AzJ(Iw1eDZJr*_M(uRb$R+P$TMQ2SFuQ&MZBBMB}=%>P{XL(`dQ zU*)5LL$@RrTOHhnl9R>v4rp|Q4<1|}K8s(6Dg&#`uKg}NE2_Kp3TNdA4~Ol7dE>*< z&ZH!tBVTfLi9L!%m$Qe~psJQIz}GWAt!qr+4#0dM>}D~9_LIhq@KQSln;_16Ci#sw zE^wPZ03Xz=AO+)SO_=a`^O@K7Dr80`TdHSmA@U1TFwrB4VN7Two*SRUJUNIYMpG9r zspRl!y4dz{Fl2O=V(9u60bVFf)6!7)g23k9WQ;T5RI(TO%j+x|_lUd|o$~sKdvs?A z10FaWj)y+6N0s{ORaDgEdlDiR)cbr|1bau{PAHl$HT*^^{wxe*ldomPgd* z#?av9lIz0H+bDX`2zv`HL-B9gcfdk)t@TIZ%FE{td}~Uk_dj%8e|c+`{{^w7-CM}W zG>6+~$yUatC0a$$L%Aj`+{!;|0dI5A;Lj6+i$x3At7bkov>VmlC+k!aqH`JFwxtz>+B3 z0(!#q-KAK)oCl#@xEixr$a-1B2&xk7!lMr>ES-&*0Z3JG3h-C&ULRG$yBANGO(!X1 z0Dn`_yY5`!BVCz`(zbk$Oo^pX=iZ?L(Uh}qE5%nh3$21Mx5ybs&@WhmJ8W|}JN>>Q z4UZ*)bVl}5=a&?bg>E7zj*d_AX?qTMcs)W2UoU1xqUG$Mr( z9H*LF`Y}5;&&%uLN^{QM`2{y;-Z|Y08p#SXfk0@)q|A{kvw3Jc1VATUKCZJaE5AgA z0?=t6Io5Ozag{)TRW!W3y}KAi_BV^Lja zTr|{f;#g&8%ac4(46_zc44o~Exhs6nPN14K#!i2J(LL+&GVqD1?vpPYybeBHO^hT_ zz{-p%5-EYfS>p+%t44Bgz$@_qHmlt8Wo@H zpawE@5dVD3*5cGlUp z-HkH{Upx=Jfw16Vx<)R8RR`cI3^elKPjMV?VbYJ8)vHmljYW$a=$)0(A7rfi`@iPg zFeRW_8>>6x3h|=yDKiNBZrjO6N5 z->eJC5K?D2zp=_>z5x5{vG#;-U!&H`B?~31)9WKbI+XtJL$o%V{?l(3z-!hRq=odH zSDHmf{Cc%fijP@)bbN@Aycetuj5l9$gPJ4hrj%Pa5Ru)795#^?-l)&~Xs$?+ry$bA;BNpo)A-cnBqbA3S#fzc4iZTt2z*TSaJ z=?e@|E2tAAPAG-8vLF9iry|eI_?d~oRvmEPDRSF?{K&#Jr*V0o>Kj7C%sHOo_(lS_BN(=uJdUK1bm!uNGAQVWai97CJQRk1Ix4pM-`A-SR6T{0u=3??5M8TuTr;Y|tLPbvfvb+vvU zE5@F5Um;+z`%_*}_`wO@^Tnsq6~MFw(BxHhDcuPEgt@-`L-nArtK?? z`^9e&%w9Yk*ySFr)mMy!4&_}W_C%ut&tX717VKt?+vcCsO}0l$_Tq4#Z?| zVAVen@#=DGn-{?P8J&R ztPlUCskh{%{~@Y7)`C=XYPDxi2DHys`T~I{tdd$v-^l$}z>1zN=(4%rAas{+ztRzo zieY-Ak1C=#tWyJp5DpXhmf-(W4}11Rfk>xZ6$eNmEoS zfb*(MlnNR?(_A*MklDZWEZ6?1Cu85^+iK{w|5IM`2A5PPu-0UPqbBbjc-CzNv%Qq5 zw6`2-98HhdIF&b1EsFZ&5_)l0=>K+TkpU_UnY)@_WnbhErk+cFyy`LKlWhQnnpQ63I>7ptgvB3oAT}3!G%;$hY-ju#y}>=S?Y{^BEN~D_w*B1+S?Gfr5T{ zXi1>1hzG2;>=4R$xm z8^Jbnnm0DO)5lQ7^6+tG(T-AJotOTY@Lt9>p&A!sy#QNEI&GGWf!?YFWKSm8Kp&)u zS(P)Es8+L$Zgx3P4stdF{I=j+mdQHrn|MGR#Q6koKh|)|>I|XBU(|))lLf-OoNC}0 zJ9K%NsqQwUd-Y8ft^D3gAGYe?z2EHdL1u3i%SME>dL3~~Ktaji@M61wWvi6=(^ozW%Du2eIx|~3A z*PRkZg8A}Lc}BK@Ol1I3{<&dC6$A~3cXhK-{etd|9bn^e(IdZ9F~6|#Yr#)r3qdFo za@9J|4+Uq52gi?UdgVoA;J6a2@T!+oH`(3%%e3K`;oNHnyG~b5pM_pC8lyJU8wTxX{An$~Z6m4$F$20+cJ^Cn;xk11?HxwkJ9e?obQqI0K&mo<2&ZUp1$%!qc|(rQaw@V9%kSw%is z5E7cr@IK_tBzdVH_!~m-#hr=uKSi`2Rd~npg5JOGqZ+*Ce`sc&|3x!{iT{7l%s0Qk zCC528{lXyS{5Ewc;F(4ZpQVRSwV^wND}Oq-`<^&BQLnV395n8S6@^;WHMxRn^36Ya zSbpK(D`)4j>Yc12yT`95Kn6NQWUx=fZzd9572-0=iMqeZ33~m==)VDFd?}kkzXCcy-&1QKyH}Sw)_GiIE|aCJwSP*9v2S>f=f8TP9(`xOhWAfKV9=% zZcb*)!|Wy5P^W39oHd13JZx0uwjdz3AU__UQhR6Sj)W~H-*m~L%rU;<*{R#NR{zM)40#6d8W^{U<9O${CXo&U9I zvlL|c#JnzOTv^6yQuR)MBjk6M+QF?F;186d`~DxgIN19CFI_yz0#1cU5>Hi9diX5U zr$dfE(LXDWB(Gk|dl8%k=;a6t*8wXW0EO3gg%)186VK|(tH&0O5L16S^NiHNybP0| zc`aquDIVxe9Jpjz5-{!-Xe3QCDd}Xz)T4 zGQ_-TWr%9xa3zm3Rmom>Iu(NKUKiEj(q9{+-nb~rrAGOb%vRNdc7%xfOEn&S7IXdo5nPoC4C`;f$n{d%gY3Y&oRpUwgL2`6W6GB$^8ibRNM50?XRHP9ZtX{LC4?F{Eo)}p+ z0IJDd-5%H(STr=Wfq|?q5+!%gUe>^>U<~MS(#+Kvrfy)2^!8MU)Dm2uZHD$S9t$}D z;t~!^u)s>KbNU|&x|th3ohuad+q(Lp>l%{z5S`DBksB(9DWuew`1`frA){GBg zxgsl;2*;c;XqhfK={pe|EMasU2-5$MxfQ|fA~BoslE+{4v~_mU0KWoPP=w@%-w?1V z`%GgAHv~|D$8fR&8K>KY5co$EA`l6nsNtkQ}=eTHeNv=7*6G9W|TM(dNtQSOr^U9^9q8#9M*vV>VBkTV+1wZ$%- ztB;n&7XZ5nrfRTM!p!rad*sU;^`&u`t$pZg(+= zm${czi+UDM`E{lEemsPGj=*=oMd8Uv8p92|R+YkF$%H%b;X2h()`&1LI&z~D3zdw! z2if&2M8gusW-mo{Rwb+|X$@PJiXpRRBirhiy#KI49|!ewu4W7#?j=Xbk@?Ev%bA$B zt-w}z^HdqfURISq698zrMtm&L9IWmO8IuBtYKB7=dR$z&4p82@c2yRS;EYrcNl444 zj`Y!EGCCs2=i_xpo_q{6Kqq2vLu`(JZ#t5efg|U$!qwQrW^RTz7@49@L*~M2EL!sh zyyJ`f`a*`79qu=(+c8nqw_Mto?Td&zsXXk(?+fj`Un+Ly=B@R6ap%i`#s&+XiIXmH z#eihrrAIVeWRGH78czs$%LA#C8Kq(nRUugd2o1Rla|D0djxY<9~SR^UV)9MvlM3T@+cfX5jJ7mWOiDW)#b!vKbS1sOULJ zyYa9IdnhP9(&_TW%S4R~Gur$p8^>Ewi&9=#-9|W3j^N`P?m_zw>o(m{1GzQzNGVj!r~^`5>}5Lphw%^!0j2 zQg%4Pa=Lrx!RrL#`fWJl=rm--r#G7IydaA70=fVEB%6Mc_od03v-HnWQOJLWA)%ck zuBFA$U%|85LfeFTN*EeOCcRE*KkPv2ab3=hVrKI3-Z*@#D-MUj_}QFddi*9u>#uc2 zj<6Y&_>&_zLEA&OCWiIq)UegDl)2lsTqBD*pO08IKkIgKZ^reflRi(2nXuZy*LY$2pMkUvd`>7A?I|_8pr;ch=5l+y1&^x zOOWZ%t*uEP1Mq97?e?k;Z+2|w=){gZ(|cX}f$bjarS5yzzu*9$w452zY6N~;(n@F{ z(piy+HQoN^6`MQT3*4LHG;$WMKk5iz4^S~k`^H0~gBv^fJ|*cf%;sJH@G-=UFje8f zcPBIMvli^DknVDwzs%;(>(`7;kxfX?H;a_mk{-srzWHuL{#-ICM@k4*&s*1QG;&w) z?2!i~yu+*N^Ny01QkVD9JVUN`Oj+@AjQZcQ`}kom5|6KR0k+pAY8ERx>-S_Icu##* zJcQ4aK(74G(V3TDI-zY$4*&;4_F0n`1FOC5--jp2cX&doFe*}@Pj4H0LXtX^SM znGbG+O<61-*vX>X<8ZxSP|QO5u0p5+@rOq-QkhP8O|4w7t185<2s#2q1f0})>jHYJ z-h~Q#l?c(B*yof4bxlns#VjPZSOZFZPbkcf<-URjGya%fr_FT5l^XIFvHVvmK2I;E z!r$r=|JCC4>n%ss%_ItJME(z_`A5E4)fdS1swZ%phq*uL|3PGk@qemgpBGR&oX`ap^;L7R`33v_ z_!|Wp*&tij=xq>SrlpFPXh!o_Xff+^d{Rq7zi*1{P2KJ2fgd!xmTfESLdL7pmkYIQ z#5c1|&Mz?EB17@5OF70uXVdDNJRSE^4TK>eb0>mpu8?y+lIR=}lxXKJbsS+jC9uTw z6=2=yIx=c}UieH_YWGdn#^?wPw29Zrk*aaVN-l(lQg~M?HjtWfZqE6#4+(8KM zvB8O3-4vID_E^$W*eg+T+A`nvXn%xcb~`#d4AVm0nc55sXoX4zCCUHf9K@&97c92 z7?K|$26kj&2O|+2YiGn=>*8DJ*({^8+$y-H>a-bRlN-6k)w^+jVq!SzIMXxx4xVVO zZ-sY<=ENF%F8evySTl3xCT}xkU;gf}qdY>XfHB*T-f)yrMq<9$9Ur%ItRDY7^lwZC zBj=)fq@okFeSe4t89WO-SbyBsbJtZL82R-|bL`Br13|Kuz!^(os~Me1W^w%LPyD7# za!IPyNf;;ekojij%(DXM!=Cf4Pf8O&AV=eJq1k7SF3Bj@Pzx1aot$~_%`J&t=Tu{|APLSe|s+7%7= zGp1SnA;*oN1Yx9gKSBf z@o)$19|gzIVo#TDBdFO%Dv^9gS{GZ%jGz=Csm+@zwhx?Le0&gF zkBeU3N%0W`ZV91!QgHG*DlsBQa`jx{p^WLLATTv)FeIDEQB|Z_3mxhc7rc7om9Tb{ zNs&sDn9v^YhLmEK748rSB*G^`+U7_=ztWwDk;z*n1m!3_MmorLpZ@KGcx$?}|5D8s zuQwm8*Jn%yr>LZ>I_(i$5IThXP{ZDns069ES)mQORpaL9Rlvq7gdD>^w}?KbPi|-H zlYY?XD;;iw~LU=O~;f==2)XczvhECfT;}g6w@RaCg zj$V#vyov8cju;ywwnC|a%^nqg9H;KY3^{Fu!v=>S7W4PMi)7L;L{{#BSzN*$LM~PX z=qdY|h&@l&pRPc_<;I#)i?p9G#)Wc+TWhh=4c?0dHJlr_Q#t)@3<-?_ZDhg^225CU z;zNgQk%H!_qBm9>bpYc-n}^?n&Nw@?B+8i ztOT>o?)>;9NvX%2&GE&0F02EK-J#qEj-u8;gLZ6A6cMx$^@Lly zo48v?!Gs?SHCrkGPIZ5~F_kg=hr#n3RZ^}=h$0UPh0BfuL=oHCS_mAc61&wE_PWqaeZ;! z`kr$SWtwc`p$_N?t>-X&rHCrwBBJ`yk+dNa_Yp&9F4(`h@%nak5%y9yA+s5h`VnwL zX|mq<%7UvBL8*~0+F;BDoo_ckN$fI%N~+Bn!p@HaRr*BL?Eu4ws1ZsE*Sj$jKv@o6 zm+ZZq(IGK>7yw#4B*cdHE86OfxLjN#*w0WrC5KNIQqup8tc?ALae!!)lL19Mj>MFa zIKLNu(Q{3MRx2dF$PsYO%GxNwvwj%R$hLv-*~tYf`V2B+jtZ==zC#bvVj0-8U*|*` z|1Chu&piGWk8VNj6{g0-{ZwTj@wK0hn9>)yk=46*REu}BY5H7V&cwnDO=ja#;y18m zgQaPlx|j!Q^PaZm>c!<_8FZcQtj~e>0Le(WMBeIu%f4JKAuFq7`6bDjund;?~q- zwsje$g+|@{61KM%I(UemaU$!?=EZ5eUhvp9Rv6R|rkbglJTR7eOaluHrcI@+qRxk} zPLt$N%JQ;h9oqh!{;he%k0}EdMLlc?-pRP8K0j%TTSc8!BoN+c<^Z%7dU4JN3s2aw zqpeADCHOqEC>x7`zZVGQI%{4HCcKXyUgH~hdBZEXN=Xu|GHc}Uk2C2c3R(Pxy}oLs zaFsQxpm^R7>ft@LDV>ptHzEe%HTso74NlG}x(NJ0?U)mY+xz8!`r-Br)qpNACeajA zG6YrM?1JS5a{v@}U2vUyM!%u5(XEr47@=sU$ZC$lQ13whP~RrE3j)yunn!B5Nb(a8 zKdj7ztIGP>AFmF|k_iHrA{oaz=40!r>P=kSE8$8Nl*bJUzYjVGySLY@Sa~vo0F`ui zOGt7V#`G9wvHpgHF&LQ!(DvPnEPJ1B#dSKz5vdqW@%nl90`ozYCZ=_9g)yaB;wnje zGEdi08vZB=W=EXa*kNR|#~KKX8)Uzl*@aVK+39%!x@Rd390%e1MoM6neXkm5J@b?) zB>jvvg!6in14&?Jd>O#_oWBCtv~7(Qnp zvJJHAvvUq&l*Z&sD#l%_ht-2FPCqh=#kY8|Kv;k!|Av1z!u|d84eO=E-q~dIewBLr z3(`1#K6E{c+bIz8O5I|D+UV{U@M0NjUFTDvH@!+;V^GDXTZaEEPbgoW{a#LsHv4?p z-|g5NLq@^`c}nq)^rQ7nsaA$3CBW84-o9H2ynbQY6f&bU{kJZzt)N{^&_HN7c#sO% zbZj_CoPRS7KKIjhTZ8!GlnSIrEE!A}IRxL{!`zC9MYbBc_~(d ze3!&uOK_U)v-ZpaqWKwz%5(wsp$KeE&mu5{Jb_Y{BV`Yq(qh{92)lRg4 z-KwW>L6H|8m^@&X`lH;n8NXmsJ&hTpFLgTiq-ALN2X%8q)Ipw=m*}q)`!|E7(cW8(%sn?Qn_$L-C(XcI|C;JG8yGsqanc` zq0(Oko1-Aa93;2ueTZF=lW-83{g+6Q)x!lJHggT2zsK9I-)wPOZZTF$>H|ltXh#PT2XwD6>@v$vwVwY%-;gCt^Gc<5=jya` z9E@u=no>)&I2ONvaP(HurcQB!#q4_CR{xOL48L`P?+8f%re+&+p#2|Y%-xNSK8FnJ zR8|}*`8a;7==yVy+Yst2S_~^ODDM{exyJbAk_)-6afafjhQ4g3$ZUh>yVE}{Jqd&k z2U7Z6H7lHV=cfXqK70W?|ZS`<`FnAcbva!W_86NjJDSM!~)*hJK%ywk;sHw z;$56U-;MUaTcVm%l=fObxJ>Yta-Jwo3F(|8N$^1S=+Rz!m@UhEuRJJR?nEgyQ?xMc z-3+F?qtek1yj1p=*oouPXK1+fRy6Evu0BVeRF?eoj7_6E9ng@DCvHr zs26Ub1}03%Bg={M0)K5&hPAiG8@|Xv&(uIfd)q`=YKbbDl(g8kA6wCEGDv|+t zHxuyN@E+qNErCAqBn+_6b;E8eml4i*0qvU1i4fZGhwe&CNs_wAV{oOviQ{vGT|WEW z^Zb&Z~>IXe!*tEizTvc~9? zpxJTW%)IfIC(g9uD30OF7g10Dk_U=<#l@AfA*?|no$5^u{TsCHb{sQ!Otb$k(Qd0N z#fp9D4lt>WF_7#;rBAT6I805OyJl&Bn2lcPJ|MnVLM<{=$TK*ZUW)&D# ze90Fu_TI#+l&B#kc=)tk~?adseW^ zH|QG_Jb5vha>+DE;o_uzM8N|r3@T$P|5BKMVwkHysi+E&$yY8&`9i478R6}QQLfB$ zxbNLI)vkxSUEL=26s*V=*2!7DHlxa)Zwb@88hhh7Ohg=}J7~upgJ(Tw)cA|tEW2U# zQ=SQrkRKPkYSK-|a{N|WBJ^|Ey-9c{M$c7#sa|n-aVrvkP77kz%3{cbtU6kErPMoC zX}(MEZ5W<6ewiSF!(9^Tub1+*V%|PG=&SooOycbY;R`FVu1LnbQogfAE3wqPI3F;o zq!H${-7i~ZFaA1vc^@p0-EFx-h3*OoA1alWNnO91B+ni%9yKrHlPDauH;rwJEX}n= zGwB?#BEO+83B7LJ;O=TGsp)G4ISh}&l9Rms;^aeygwgwgGI%su zUsLus7KgD22l9(K)mqJCh2U|sU|g)SP7^JWIwulK**s^$-b{Bp#=2ihGaB)w+={8V z7ZRcae(c7P#>TtuWWu5H8CMV+k@;Adym(ciO6J4^o8=q5157G>c*8T%`u%r)JIlet za1NlCrsAv4MP#9g+08Ly*VfT3xzYrjal;0@a~PF7eu$?jsS33-@*YW+E?~Vo2Mp8> zFh)MonPcu*Y;~~o%ju=HA`-_(3$-a#H`Fy$LaE%|#J;Etn8Q*YwHY0KL2R ze#fx9+w-81B|EPVWwbDAI>`cwD@a9f?Fra5K@L{S;|E6@3SS4DY>tINrjT)2&NB7L zKmQS_!=Q}WD{yGO^#t{!ftj*L0PO)^oz$XkUBulJ3s_h&Bdsg_NW!-{a5&Pg>g=jd z+V6r^>BkRs?KX z3U^FB5~AeI`p#Lj(xFN({>y9WY#)4DxL+f$y0Auj#85cefG}we#S4LvKI6L11t+~u zp_GYk8~M`GhQiMyimJ4<70TII6Wc(pFuAO59*VuZw)tegF7kQKP#3cxdw}kf8HMGw zq2r8jXnF0ThUU@Y!Ai{B91H49R<^|4US4yLgXc1ED}c(1qL-MQfy00bwO4y+h=V`o zivmHxF#-9FfzQ3cb>VH2u#EhvUFxRBWI*CUir=8Gs+YmqY+^WV%ZQMhuZ@egocNP) z-Ehq$+e$qg0eABEP&$nar$~&8Bk4Ok!^x{}nYL_P7J98p9beOaEAqxS#Qby=b9thV zaJ7adFKbjosdEXv7AU!4>PR3F^6FS3S1#pJuw%$*g=B_KOnAc5h=Fn1@Q#zf} zp>)h;JkK^BQ-4+%9E4KPS;BnupODvDC`jzu=#nhZI&N$Heo)rL+XM9v*}q3BB1agQ zuMR>)AdHV2?)2BFDTiMo(g}?p76X>9SA24)_!a?|XkS9O-D9h}HY4;bNqZi$+R@jS}M2^2R1&%U( z`Q!ij=SYbIUIWdu$Dd$PIyclc|AJGK#^gbGwI48%NR~t-E!moai)uJEE%>KG$yc9k zUZ+ke5~))Ak#BYLrFZn>>rRrOAV8BXo;1RScE?dfy} z?>5dAg_SA12)%bNYIeI=K&{b@e%ElA`=kBUo{rLDgTvJ+BE~T_+fDbw3A^dxfAi{?iIv?9oO_Ya<6T4`U~AT;_%U0$alt0@4xW});aHkq{SSZltJmQHoY{lZ~)V# z4~=@Hu!JGV7vl{FvGMhUPY~t)Xd86bm$RMpg7s8k&7u@T7%?qw`=>GO$f$b{eljKX z6USvsW`cH2_NPEd%K=wRTA!yn@|5}lD1fG$;#9Ibg^R#j=w|;b1Hew(CjLa8-k6du zwaFDo7OG+4<|Jc{Mvz)su{b8y%C~Qx(Y9Jf2e%0q9vhEJu*;TPZ8z!E=2#y*)#ugZ zCJsfV42Ia8Z36wiOQ79<98`>z)D(z5+)bgdxee%w9;R;YZlrUNBqEYS?#a}6V9-kG z57W}y9i_U2P4B%&0@ zS!MHqc)w21<7M#2M7C65KGl~RH(<@2DCnP0q#lGLVPuDLA&ZWQ19~g=j(19R%niLr zPh%AR4cPN5akhtO{Lh5Iq4ou=80zFn zDc|>{t4MIVPsg8zTeV!Xg9W{sf_j#W(X48uC~4v*w!f;ss|$#lY;#x$a(B~|=uuij z+b=iVJyp`brQLG}F{_?cyD^3Kwtb?WU&Z9b=v`hJD`O)D)k=%MJoxBxHHG2qv8%3M ze=z{JtJYN?a+&U)dc?1?^9Un(OE3K_oiVD+%i+ujP3MFlmEFU*Fa}YUC*r&;ta|`; zezq8={`u&MsQ56a6aG)Xq6Xam>Q{8=>4+LF@@M_^;#dIP6opxtF0-?xHVoCC2HwpJ zr85~%k)d;~yfv12rBxXL6S$w%*8C)c@M}rlYkc>7NecVG;wzigAR+_>n2g(9AHvV! z$r`Hu?AwZmOUX1~G~hAqOR7dM{LSp_Hff8TAkG59S+zj2AJk;D2gip{s|<=7*XS4L zPmv&Nii1an5Dg17=Kvqb9d7vD%++9*OO(*x+>_ViVqe9Qz+Jx1&b~)k8RbtySDzpo8EHeJ!;$(Jhvn+XRc092Vq3hH39EKKpo7<|)v+#m94l^1@$e^O zfVJ5M@g=1HA-~r+lOi|z>K|}YwRFPneagc-G9($_*NZoOee=%M1miCBtcg zvQgri7!3F%H!R?a|K*>AdW$gE|HGv%+up*Ep^{S2r^w18@Ei!ENVqv%F2UDFSda+3 z$Q#8xNlH+fd`ARPWN5M(h`~QK(Zqc9N?ECl)E+Lm4vzX=A!Q|ki zWEvT$+|xcw)eF8z+9Ta_LX1$DzX9^fymrqEvc(skkI^R4m{X3Cni-#76ocY5IMJwz zkI{xC;68UC8<9B;U@iQ98-KBbe3{CBc>(Zz-?FIAepz$UimCoh0wI~;bLyrHs0%N7 z4`&f`LTWE^=-srR`yW-8bwqgcsGP^JorOqhp?&?^Fi^BX5;u@SM{b$Fq~?fZcm6*8 zFpWbxBXVhKy^Q}^$LqK|^@2C6(_O8rLi2xN$6g+OTi=yyNC)mBFA^O~(S>lJYOoj_3P3lXs31r-I9 zp^&he2BwRP%eU71s+YQ`@<1JfnAdud#~?9@S;N;rT&Lc+=!Dx z=j{hsZu{SyOeZqaKB|9d135mLp47EDcVlF6?|o08Jf_=r5u=j3T_pFEL|mzZPjSbq zrxhoR$Fr73g1DEHDHq4`*Qsr z<>sBjch*u*Qw$fFCZtABjrL?df4Dv#qgS*9N=C;K5R-uSS9vi05v@Zw}SjwW1 zGZmg9hVA9r5pgj_?tXO-UZM8edM8VVYn((4IgJdOr*PzCzN!1OwgrTjU?*+yLfQ`O z4xaYm^0&?d(3D~e;DhY5;l6~$F)nw;w6ul`rRYNU7-CjrR6b9cHn=2sNd@;+z3i6o z4D4#klwn7_Rc;PDW-veN0;b{R$@@SQ1|76XY%B$((<1A;IY+ma z-uet1XX*{ufM^}vr$Y;b%F2_cbIQOPgxJA&X5kk>W-(un7}tWsHQUC5)BqU}I<9(# zcM=usx7qw2?9Ib)O`BeNHkP?_W20vV7}&Km6mLx43ew1ZXvVlJso}NN6ZE*weVV6p zBd8nzNvQ=h6@>WicY?foqxvfRIp5LHxt(2T($i?HUc5>6HfiYXv%D+D1v~1EqSIoE zg)|3H+rgV2MB!(I2D&TI%p6-#zDzFBSjv#vn7$Rw zLRZWMk?+;5f>bF|M7dG~+jmMU5|4_Aqpe@+Kws|a_2NH$1(;?1FC@8uz}lN8)--=l zm=Q$@tB>^`>KhaxNj9X%=YVt)0>m=FGg$aQai=#<|;%r(vF z10@Ul)$c&7Y@CU{o`Z|x;FurHod_F)n1|i;g@`4e5s1K`>}?4Yh!zjK|Ter0{?CdTNYm zO(Q2)z3ltdPO(;0!|n?5j?sCnS1F$}ReXK7o^2nUHJn*fGY0J3zj5_GQ6*t}y!9=3 z2FDDx>)KRT*Zrm{8yD1GwZRlMw-hZ48qA2qlRx(npPMJ4xn=Hkh-)x;EZZH_)}@$3 zWi2`<{*sh5K~C5!cuFt`SY9h_!N96o5j6DKc0U5)ke<~|k_M9A?J+q_;$k8u8rw*T zGzJ8!hzu^(NZKHx9ipV7pc|}cKhl-Xo2nXp6jhM4SZTr#i!Ykpj9eBhG|!f^4{$Bo zq|G4=dq`Ev2F$ED3$n;zSeRsv8A5t*nbVx&YLE$I|+i77g*5Rzdd(rOB=doKbEepuJ*ia?vK>FRr}3W=ksCXIk}E zF}!&G6xGLWxSw^L0y=de3v3l%Ylf{6j5yLsj9f%#i0TLAU#XlGDoPij@lL8rKb4c|L*utXMlbQ$ka<*EMz0T=5~^_AM$RCL_GlK68GB z?Yof+4`N(|trB2lm8A{P2oV#*ha7P8G8nUDOj_cm;B^EEHt* zvJu#Fmg3?}zc_zUSpuGajOqxND~$s!Y8=5(+Ppv%(LAe0RWL@y?{jmZ*JA@s#Hm*mcn`))FmPbgj&m|#b;9L{J6p$?r1aO18B(S!Plhy}hMPWH5z)pAp$(o%w2t73%ypB8Mn1YX!>T{z z6*TO=os!~k)Hfd0le^j{5(2keS+#!`RxpN<1X=-G9pJh5dIsx`zlsmLQy^0D{b4S# zq@wc>q?D+J6j_kZ$?Xk~ZF74MnR*sQR)LLX_e7GvOn1R{zcnfRT-*8tw^NiJ{<8=| z1)#{I%?Q60!d<-$PiD0Gq_3hz7 z6mGdq6#3YjU~0V~b!kY3bbj(y2-Si;St(^&&mg5YV zX^PmeoC>ATZzJP~1OxfSW*4_9u9??OiX^OLbtF|NOWP~`>MC*3iLxx&wQ1xT!qvvZ z`6}g_?@&uTj&}SL(S3fu2$p5_<6K786*Zl<#h(N`u>R^UDZ_jUK#eCzRrOs_=lCt zO=IG10bybh6-HB5PSA%GgJ-9>#6!fW+^+VxuDkkE<{QLr4Y4G{+MGVFL*E`Yhb7b| zw&d7kj>aird7Uee+OfNjRW3X7erIX6K2&@-nep}>N#NnmAc;0QK_b5Qm#ou!4;za) z=OIgpTWj{Vq>@uO<^Y)-q0P@uXVHj)!Q>_7j~uBfA*d(Ev3cWvlswFA!NpJ21_2P8qtwSgp$PVy231NgF->AQ3KS!vPH zI9S@8M1Lp~s5eoR3oJpySFzBI+-pnT{>9nvg^ILylMl@632I?_uX3vDjHZmNCi= zv_l92giV-8JbCRh8}~E5`~j#_3Kn284d{67*ykL7pQG)<9~()T4j2ncb7(W3Y!3hS zqv<1TONdNE3}kwc-X-vwPIo@Vy-~x^ zkW3OB*>^fP(%51<#J>k5=Cg_CoSF zidYK#QD^&RO>x;e3N#^TgN5oam7z!_GT&)M3Ar#D;ePwz(WsIcr5maj|0pHA~=d%c_F)@$!IQimKenY@Gprwe6)6j`1-=4bzW!E;<2e8Jb| zdW$n{WkE2H3k^%0=0Rz$ZkJ&7A%N?tKj-uWjit3&1791waq$sIb*1;P^@&1Z6$xZ? z2o1*-6xZwiWUj_vL`WAhmR=fahffif0x6f@-^PCLC8%Y_xlsJ0aV?jmO=H636E@bHM9odNcg)mPn5(;9yJuWW?yAFvWD8(bLeq=aFDs9fJv8mU( z?CM)Xg$O2il05sX(f0rWkqNi^@3^Rx6e)YdrF7XuT9h~1qv zyQ~fPTv3QNiF|Wk8K*k0SyE0JKObJLnys}a1vt=M>>?bA^cOUpp97KLmD2@!M-$e# z6z0+{=vg7gJ(4Lhe71Lx=6IGzCu57Dvvy~u&$k*I#jl6?ve8X(#Im`kqf&wmxmB)|>9QeI(ymi) zFreEi43M6dAZ%tp1SG`E!0?fsElJ};Gi{2mX;FCzuYe}fy`{T&PY%%=u|91b2mQ9$ zFFD7-Hn-u&XeH5<_&7Aw@dQG3Kh<3fnAK8i!Q1Q39X5X@{h`u>c-r78jdQ)?la<7C zJE#D--X$^L{qYO^+{3)y=Cmnw@tG2DGl#(y$O;i+=&1b^!>+}gXn*6iq#~Dl&_Y1}qn&6TUt(KNkzX^6^APIAuZ`#umlECWOW_22q)P{NMya%Y zR^V1aG$agFRAww<-7t8Ivi{ ztBc$2IzG{kB%Nxl%kLu5u*K_77*`92gX2ruJ4Xvle58!`xdLVj#my_r87CdnTS@it zRKJ$>?x88tIeNrC>3grZMO5q@JS&itVbiw`u5MVb7y-=4$^L4H~7gbU)9o z+jS37z;oA7ZprF3ok?$@y>Ku=sPl^;E0zQwabxT#-!8KSc>h`}ITeamzuqsN(l)|y zr-J;Y1p{555^$%*%#8)5+DqTUt#66%58Ps{>@n>h$b)uqIPnh{PhDwJhDgADX8Hvk zj_bzwkJt7~R4+LSZQo-03|?bk8&wg3MPZ_IJC8<*H@zkWjqUsr0}~-w`aN+ytDV7k zF3@z1FC0-RmqG5O7%xkTtP7c3&Ea1Ad(%XqQKCRLTV}IMbx>w2LOg2@Ce=3mau)A|gXEuXDe zYIhHpPb44xOClh9(B_rb8pl$2)WzcYSP+eWW~t7!m=3mr;SMYEhm1?K%a-;)=!dMx zc=~{o4zB6sPMC|9iHEF)mfJ%GV08jna(t1J_FIS9kEi|?h3W^3O&u4)Hztm|V^WU! zLrAv97(3zj?*x1UpdUIj7p4vibge7fsAS5Ci!!$A$W z>O)eVzlYrU{mnPbm!$8QM&*5zyNtBket#-+v+#n7oLRbCwj`pB4t{Dhhl=Xwu;TgR zDebdbc3LO+9i+&-IWV(?t_1l!l{zLOce``T;QIT8!Ki*(l0I5c3X3WQ)#?J3Df!dD zDXBb1#N$yJP_m2OC^FR*8B;ld|K`m?p>2r0{^;9L)S|M>oqz7abxOZ*bU%-n@rx=F zI7#||y)yVbenF#z%PO;L?d&Zer5O_>_7$P2RY%CaxSLYxZLD40UNOWLv-=HNA;)=w zYU8kJZ*0pQ0)B3F*;Q7Py1r(-JG7(46YYd~9bm^#s+aT_F=jt@`8^TdkQ89cYh`2L zQc^)yA7{$ksYw;w3fZQ}9Hv1OXy&$?JNwi^ZFOz+NLR^02~u*6)=tUETgOJ5#ZLnt zRyqhbGUx=d{T!sRl71(@9y+!>t+y|JbAU|8Hl+P-lbXrPcl#5lei|c`A6rHg3f%OaXIo-f zxR5F7jf)X*{ec!oEc^n!lU2LXU%Zsb9T%IJH`{#nSjj8gAMNBIxqIt9g4*1aXP;U=~e_|NbW#MPf3hK zDl(J4a5^X6J-uX6W0%dA@)I*<9~z!aer9+F{DoB_WbToIe-x4W>29ObVISLpl7>GZ ztp@R@K5Eoc-Qk&ZWUV)Vm~8SM#%BVw?L(%*Ruw z8zh7`;1m;^LbI@#S#i|lsP2*>;vrpMRFZGvF14V2CYGNCI|>|a3MX`OnT6k;I&=DN zy|f0sWAZ~Vrul0qY;KC>=nv*pS}?^ze-INc>CPOcOYAAZFKy%XQUR zyFyadcGs2VkCvYxaNrS8@@A~qa8I|Rc!+;C?U6_xWa}LpnZ;zteO0gl+O8{g8+)>G zB5unlUSq$=+c2w7?k>_5AZoTJncgoVJu{!L(J?TInG2$+tF&l*=rf9@u`&#NUL=ge zZ+;w^R}oWh3~7Dwi09o2UN&3s0=Bd!_O7zTPKd_%IK+2t?#e!Y!$Pti)n58Q+oocT zt@Ds1!_607>~sKJVt+05&BTwQVp()MgMGPK^a3?QUR%{B=U5?a3@37A_z7%~f?JpC zdx^tS#n!0bc=7A@SEj#c=D0Lw{q=qvNC$8AKcL6?{lyft@Dl^g9+ZMRPBXn!v22oG zvjnq1^Up5QVetL_J$r9{)8JJbYn+mSCsO<^yHeV~MUEnhKv}g}1Dvga6&qBE#O-J@ zX6cnI(%=S|`i5)}V_Z~ILNc|in0UCLzVNY}M1z#f*Y?C>NP%-V6_8AE?_UEZ^fyH3 zGQid*SL@c?rRKFu1}4EMOA0r?4Ze=*PNkoiSzq)z5v*R>&u=sr1$oIKIkn*bI(a-t zakp>s8jQV2girV3V0n7?wHpj5$3GK#@ndlFw!-DM#IDg}C$X|vc^eV;be9@h=nRZ` z@tP?DM?Ui%;pJY#ayrr1@vwk1IUT<=E+)@I&CTGoWhRf&GLlTElaCQMqsaJEEaQ7< z$?tJNQl8*j5|Z2Kty0Qc0PTX%=>MK)$sZ%xkei-?He?G}*7K|{Dn^c@5{){e&_fmc z{X0+fHlF;*XUTTN46#*;OCTP)ZD>c#ecgpub z<<3_a@kw^8(qp-oHpywb}j?Ne()M#Z{U zQM54P^@UBxk>4X)@FnJ%)mS$t)VcI3{KYIh%0a!nNZjjy_$7}cx9R2e$NA!qpbp@z z-6}C$UYj{zSjma%bcGDJCAU`B<}S6kkzdq_Q(Zfx3DdwXx9luhsQjN7xORR+LYTr! zF39m`(%8?Yv!$`ebBlWZJdJI;zZhwjEe~QC9-RV%*=95F&-4*2{z;{Vz4m@2E-x@+e6_f-qGEEFU%R&u(z;d>?DJb+8CdP*X_s+nd>+%MZ@P zGwOXc0WaTDWfC`;0#HuSNHs?-#nRLcjyFT6@ZxCN^23RH*WS3yHWcTZC{`E33xA|aG%7C8@e8Nyc zsC?sLgL!XMw@3rhN&Sno422QZ#7+ zArTS8-pL%PvFM!|EfISMZ0NYJXk4z}^ZvFfe2zs~q6uN+pag4=VlEnMuo%r_8;3_2 zC?{jI1bH9s5vH@N?g64jY>31I#%s#)@6ZZbg3s6jVV8UMK=^%DC zRs?)+5obbk5Ml*mMCg+wm=U*R*TnG(kDzcULCo{Nq8LM zAK7}VG(E(Zw@u5~>A-ml_u?>(LyOK*;evhGl}i}y&7ey48%Z55&dODtO?wx*+v%R_ zZ?Mpe4O=@J6{}~Fh?%sahpk(wOD#WUN2YzzEk!ZQbJ z;W-G|;()4XyJ_Y<>^zEJ86~^5w8)({X^Wl>qU z1U&nqBI{Z%6SYEE7Ng(CmOLGWC~P)<0C@t9&*Fi23cPG~l|Ch9vGB!XU z{dUYto>C^1l&I(Rv=WNQ@OfD`mKP5^(f>Tgvw}L;{$j~%BIsY%f8CDkI+eG+k!0fW zAx1S4oGWLBf|dHRjRVpwhc_EkQ@Nh4^+6GL&OIaInvNIF^z&{jRv>^sN1>W7*g2! z)*IH#OA{+Y~xS!K8YJk$0EeJE{-$}Vucht$mZ9O%b?+`|)4uVsWaCd+w&@a93i}&aFJEX9UWL3tl3kQbI6Jb3;WJtud&H;d0$PM8L7?WAhD<&vFhMuD5knOy z;wA+sl=Tj#a+dULxuEN$flB(EQ)f0KCycH5QBb7(;U4lpIoP6puR7WgHXFFC5Qbe` zYA}__z_~)2RX{yQpxpeIcRV0Ks8~|7hhk&_LY#MWOKAPg`LTdc3agh-o0J?jmDA^W ztNnhiDF1V26ZWe9vI~nACbB(1fu8PsmxmHC{0;%hu0uKVa^X_0eMn; zpR#(wDW#_16DkFr+bHy~4HgUW>v@7GwAe3LBugI2yqBx%T@JT<%QL_|Co%!spFY-&B+m^3Mk-Mv=7kPX~uoUXp?&$F;tSgY?!;tV^3pqXg(UD4kplX(FZAxUZ};`Xsg!)CZYsJds^w0z?H0dt=QpPj-fa zjFY9B%t~st@5A0w5!C6Pn6|p-tipWe!|nz z?L6$ukC*zUfrPX|@#2t_IElzUvP9}JB;q9SlVf#j~x`Q0* zS9R-NPXn_?xV`ZXCEv<)^7_;~w!>&st~Ho~8M9Q{aAElea&PZz;2G}GH3nW61<%Zo z^dj3XdHh4^l6FSw51?_i65hv6)#=4m(1Ki^2|gjgZ7EPCjM8T|1BYR_y(BwEb} zB)kA-U;6%_@INh3B+;<3p^nS1vg8tLY8DypenKINIYK4!w`J_O?|=FGJ#{@M3EbkM zl<=-$+JoBO@tN3-fI3c;`lyKW-ArSWtJRt&GlFk#3`$K{2#^GD-3^UD9oc)edrM2w z;-n0}=!BU1<4B@PgbUUnPGk=PF7?B}rI!C^_cFRnZ&yI}Z z#=w%%kPXmZNMzdwE1dnhSuHeKn-GMXKk(@eOZ)6w!bnP_I9y^+Mh4OPO8Z8yJ62RQ zr@$?{yJ%Y_XB^#ccqjDU+P|0l0Gw-8{VOIvT%cRCL@7a!5G=q_!8+ftot8Asmt4WvQt@~eXI7M!#imeQ@68_+69)R z`p|(SB)k761F(=$v!Au54q(6*Ur&l2jWM1loV%gZnMgWWXntkbtpt@zCapTtCvdkC z_=otZoO?R*r7VX5-aAo9j?f#Js)gtV^7lhhkmPxU5pNys+$`boxPrd}#ikV$!6hm< zFC>i5uqYF(3@Jf-=2L$unD&q5h4b-j^}8IRwY$FgFVa{v-b_|z#HW!OrT&L@xd#O< zdIIz88g63H#nOQ?&(XX&RV(_Wd!G|BJI~?Do|jU4su*4wkV3?bfhF#N?$%HNt#uN0 zJu~T)ZfWhJlzn56oQ7-eQp@y#9T<2i1JfC{b>3i%CratN{l_Uya^5@qu_0j9W+mD^ zoj2!C28vrXs2I4^ z*hoD$M6JF**SWKt#Ud&h=K#S}1TCEGazgCr1<-MYexIq9krq+#B}|% z9z=pvSj{Q4&f2k%#5!C!E9-YQ1u`l$L7sF9dR{4;r(*SJN+gQhy+q~_`nW6?AJJR` z%DX+28$nN8z~!=Zfu=|yy5fP;8R7HnOlYS$1GM8@3L&P<<%0J|&LPj{stbOG`}eTI zEo*OsobE*{+%Q9mZJV32&jVOU*gH!+ph2vwnM7ILpbFHS#*ERgq$M|CF5rwSOIJMj z$<&&t-YQojaV!j^4IZ~a9Y&7o0ff#!x4WyyLO}h=sf=$nS&^9Ej zK1`s1Z4%S>V4}VK`cPMZ18UpyHL~jI^N-=V%wc%MZ^Uex&&VeiZ&`aKqz}2-stFY{ zYEcugp5EHPPAB>|CYttdrp%!RwyRixWgaZ{doa5C_G-)fleIMpM#Y4X$s{p84$i z>L8K$oW6aTWpD%7>1;GVp0p6TFMl8d`#YQkC0wp>qWE2bqP2&cIXEB@e?eJ<;~r;S#< znA-5y9rE@q_rQfnd!_Kn{y$7y6R{F*%sz553+Sx9jA`Fr&Ct62h0bI#XH!gM(SY-7oLIpYg4c)+bmb$=*|QTJ4lfPS>kW zE*0!jCk@fYK9^~7B+o(-vTbH(49tO!KRB+kHYc0BbEQl^mS_qJ*}chYx^~+_SUPE3Ov=OB=^{s5@^z#kYLgCv>B zAYu1r`{KwrLOGsPNLTk8QIp+^X1{K`D zo|Od(1&YBW{9BcGmyVOG0@b#F--cv?_yii_~ zP?97QaUok6B0}3c>2U;d>CcD+PX2Bum_NKE0}wh5{|c{3Rtjv$4&7f&#!JR=pb%D( zPe~ID(INhXZ^0j~1Y1)#*vP1d&J)1#N=$4Lbmh@fMg1MvhmI3@&|{N;Q%IOxdr-U?T9!WhxAV;7Fc4sH{k z|NCg#GJ3k8B`%#z^{Fzsv?V;Yy}?tLew*W*KDQzv)>$50NQs%}7S|3TQ#M?M4aV%S zK#NawR7~+{|E~}#4Ww=IpzKaw3N{z`72KBOd=8DFRME*eY^c$EG|sagF$;xSYb0L< z`2DE&KPSaT&Q+#wF(1w@{Pytivk5kEQR*h15*y#7ae3{6Irtf8nv;4bX;a7BfF9=# z!6EB8+`bRf9dKeu2o|gH_&_e1l0?5^)<>z6DcLjCRo-oP?^ziBhQ%_Yq|zD?^<uVdS#ST7GGWV z=aW|;lT%Xf9{ZB;YG^ZH>}CA^+tbU`-d}Is&?wtLTsgv*bci4iY@D`lYjbIm?DTru zWCE;;iJus4L3~4hwnb&Q-bnEx+k4F)P_6M_u=`4YXhpIteA%3sour0R<|Sg;{ET0c z{#OAa&|8yqzVaP`06CKx1Le@cEPt^{igy8iHM*Tcl&|laGeR0Ws;XK1vML#WRm6p# zrS}a!QOY5dFiuKno=Nj+*)|_=-W_)-{btabU0xwf`Nu7EDU=Gnnd~4$HI4o79#4BD zw&L11(tUHnGMH0uk1)7u)7bwlZMJAqK3>`jk&ZSeT022{y18(WSBUzEzcT5xBzw@P zubWQ?>(bN@{ukKz?)fhdL7fHTJl~1sTl&S~a9? z#5mF|rL>u0fw|lvgF0#&|DEIV%tY4hQmS*fygMI%`pL<6bM1du!(o)FRXTLMFZ*z6 zT1fv2q)8^5oK=ArGeUv%pK319D&_&r)`Mf?4pN7GRl56v0q>F1M34=AvhBPspsW29 z&n7~R_lO}$Xn~koG}4;5<}+G=?G{Ms>+w$k!qt@J*Iri_pe$>81Hr5Cap=(`N^VSJi5VCZ#P^leM6u42(IbygBt$PD#8w(D#J9?m1 z{|r^>z4$M+Q1GTQ37eq!X4a>_Z_>g1TLixZ5F`BySAIf#Q#SGHA3C~2PB%zK#{S!p z{!wW)@3+pn<6Y@eMYglu_HKXkBBK^Brik`A_E!je#xCk6NghrSHR(oDRmG(V@m~+a z7p3nEJ^$ME{pZm_JS<%e9R9zKN=h$x0hByh*vqo-->y0 z(4M|G{e{pAiX5L$DCcaCift@91ga2e5A02xUys+ootS?vqZ+&k|7R_nr7Z+HI%V{$ z-Lwx~`|3uxs`}956|;}lkc2B1PewQ7(7zMBUlYKdyPCQZjy!jOOwL4y-%H$09q?{5 zLkDWYNt5!eC}?-cE`Niz1=)_2_>Theg4V2pEM@oar(FA43Nk*>IUzdw+YAFHx=xNk zMk6cZy4Q_=yi{FxH^vbIcL9|OWu|n5)LN0*-a#+1Ilrl?unchN-tBbC8ZovDcUiB| znXbMM!7zL!cYW0dn5TujJ6wLi&tI9WxLi3%F$J&WVKFTX!QlmFhVEu~I&4cLE;{xF zFP%#dYJwRg-2m2*+>C}!5Ix_dUK_yRim2B4oC#~_A1Og|ZoXGl`2^LyjunJq=;v)7 zo>WsWdcMJ@S&YAthP`Nn`I@Fl9)ye~x`;X|EF*K;GQmNMvvjY5s)kUB65=FB-xN>Py@9^U>m?hGiARVs79x66*B0 zkb%C}6wchW3#4{IA3F@JzR0^9b#O@8uEAHrfzZRo4Ht>FU ziA*5TuK9owfPm3C4RqCke<|O?`NS81e~fUo`P(EJq!D7(S{tOHLG2VUlkmQx=H7UuIhmDIGEoUj?0g(C2|s4ifw|94`8T$$Li{{Ig;9o`nQ_FB9Nosqx1+77u1j>725XTu7lp!k z5Rnsl%}gy#LVZN}xYmq-7aUWzl<^ZHD8!w6r4S^+_{BZ9Q%oj4vQg>J7=s$T*f8%86IrQZ4jivX@o5IKIhW(H?m6lctDbb;wI@5z8E z(!4l(`vRVs98f*ZQH~;K2eD!U_2s$nZxKCo2NbyA{U+(*|FO_p^0Wg*Wl_-#;eH?F zqJs%`4><~2sqq;?^NiIB+gM2dcxB0Pq~NCg7WheNA$NWl{sSeC8f~al6Zw>iQW`Q4 zZj%nA!l$SKWcAYu%=Z7#w)_x(u0$pFMtEj*M#8AXi~CPv>$M4NZvKg&upPCpgvw&*w zq4qxecOL@wldM9-SQ0W@@5Ya_{x>&Y2JeCPx}<$gB--f9ZeIys98UO7MVZ?xXf5h5 z0=;Euc~m@)oD7*KmK1bsgnlgFvg5N9XT3Lc)JCW3QLP^FRnTQII_HXS;IPRB3yk4c-y&s7MLjkmDJ0q(NUx)ceaKv7QSe`l;efc3_ z%_Cg`^XG?obVPRfI>bQqE4GIp8We{ZJZ>l^!5gC2K;|xa{e#>xLakVla?@anL|gFb ztWoT<+z&SfvO|W2jC&doAqQqHmQrjSZvv*qx0TYfPh}5awQoRuv^>J_OnpP!u#C)Z zL=P$`X$Rw;Km%?mXgXZ9nlDH-FTeb48EUs2p!d=w{XF*i`@F*y3ymrTh{1|KqTaV_ zANTd@>T%WNMA=_(&(o)sHRZ5a{Q2;onu(T|YP52G-=Yok&(+Du>JBi@1}lpZRuI!`yjSEquL~}heOZ1vt8R*G!pmC+5kDBv>W8k7 z?b`-VcW#1$IZ|tcC!q>N{mo^KKkQb!9drzLKh42WVxE}iG-xWaMk7G9viZ~O!S!e< ziU_L_dPNu5_wI>0E05(03M%7@`>Le$uRM^V;P1%a`f19?D|$$&lnMbrVa*iopRlH! zouA4wg14fjyxMS}l^CPsfCP*pZh`LIs0k|Vc-t2g zPM}AI2W!iOcSHt2^Kbh)$G>EAgU|@&W*OTBQ@j)<)tpbmoc9v$$MkGsc}iX|5p3-) zc&6w?lzkCj;%@(uWd6)I(nMw5rNV@4vHv^3LRWlgl*z0y~8vzW7|{zAWfW!G1IqKNMVTurM8d;~QdfJOIlXk{G~z`X{a z5NFdo6A=|GY;&D^7q*Hs+bF}U9#}koFM(Torq1~Gbmvcpg|9V3nA9G-GR4j9@JY8Pe-QhJKZw-7t__i>g%^161}H<|VNHMOhy zIw)Pb6(6bvqfP1%^{o)L_6*{j0AGQI;M;X*w{%(W=p=aA;jd85@LlI)|EaQ9*}%JxncrAm?LwoEb2z(_iktp)w-@$n4k69Kvt}TXHiUR z66zBcsaI!&@vVcRX@Al&uoLY*Vgq0c6jV@Oc6z$V%`=R=&7KYt#CnugUsG8Px4>~h5N1FWEyE*=s>sZ8nrJr8>Y6Fkf+c}%6EQ#FVH6*`M{ zeSV-Gn3To6B8CF{om1cIMmxZn6Oe4u>IhlpX0_yfGBj<@@VBKT$C(0eE=ocD zcrt#w?HW}64dv@V2IV@dKE?UVZ$d zdsef23bSd@T&3=0{-4xT0@oGVRWV5#XN5-i})$$zpUTK^RM*7CHpHx-4pt8eL|j<+QOPr#DtRK zjc(RS{!UAnB_P6?sGVzzU0>IyD4&1vlx3tNpE@g9L*)IW9n8Og794^c4^ar>a*k1JyKT4R*vNXb4+X{Dl<;1;ghOvL#*8C-O1C$0okpd8wx9 zXco@`%b}*mda|I+kKG)>Pw1<@&GSr^83`*?u{P2sP(@rI3L*=KASPc@k6q@y-4H?l zr@y0HLKvJbW78*O_|Mil$ot`6q5p4c=I8DIP&0M3bnXajE_keUpnm7(G=lcG>{>CEu7D?YBV^16QWrND6+ynEyR&aMgcBD5?9ukTZ%d?QfSoV|hV2uk zh_+mty%0ML-j}fc?;`(a@K#s%Q(1G*5>$P2d<@R!^8wcoWRm(WLPiOtft-;&323CF zy_lY*B=k{aX2WUL1VO-oAcQ01!$1wq74r-5S1D`br?t-2-s~9t<{{&R;~a@(wnzpc+q~nL$W9oh%NM<6I`A89a3c z`}~(YwEEIg{S@E58hiNdCC_DYqt5EKh?ziRjyV#Xcby6!P?AJ5NC-VdfKPB01b)yz zQ1C;VTYmw1q~HmU^@|t{Nj@ma4{Y_Y-_`GvkAL#Kqj<_p&zXX;a$7FIw&Er`YA`6) z7L#SBkPRwgQe{mhU@v9#7!>C~URT##&N-KQrvo#?gtll;Vu3l8TjSCKUP7^*hW(b6 z#6>WP9lt$p2#`R+jl`lBy8tnR__Mhr2ipbA((kWKDg6n-Z`7FPTkuRyoDq__T@7Ya z7JwvS=J&a)s+yCj+BU22H7JI* zR+|$*#6&3s<3QP z4BSL~>gv+VbgO>ZAJqytcHfc;81M@Z-nM&z5?+MJd2Emj9%tBMMNVW)=1dT2C>Y39 z!e=_i20h}?f`U9=HOmC~0J=)>+1zAiUNtx2(DBGU}CA8Z(ff=LZY6mD*$^+8bxW3j)th9HIZif7*kH{v8HXq+4BbDh)sgjog^;!>xXzF!do zsM^>iN2r(*rLH!e+v;Du^S?Sl72KKFoXIQaV{DmGIt(duzY`JegQ?R)zF~`7%F_l|s!YGQ2$D{khw$cfBNgYte%4RC_f=g7-l!D=kp#+>(1hypRVs=}xvw-EL@Vgri(G1iv zDP*=~2$fe~R5i9*7Ee=xO4C@us`Y-nPlF*|2EbHfX1$f3@40!daO>a-B-nbC&B;w0 zpAKTsCg4j>3CTwo?+jDP;JcBKsDNphg($-`J~s!UaeqfA$^bilUi13iILgm|_Or{> zx-7r_n&wl93|K1T%&<$z|N525+|jK#F|(gnU-Gw((jAxN-Gs4kEs@a08xyUtQJI}^ zOh_IPIKD*r3<~?cJ7&1<$ihz&YyzgN5JW*QSPVrpZ6zjgn(%GLj544Llb!lAyekb> zVz>;l4cmbCS9K%eZ>e+Y#J?VSm*@*_=2FQoe%z89>R z@FDuj{dDVW`Z#y(tjTS6S~-E-;HJL}gC7aU<+mi#6C~Ce$g=+Ui&ba!ya$_#1?mnN zd6-fz%kC5$@8laPAn4uxA^VepSpAq}@=`eHcY}t>qPzrtRCip$;VX4C%q4I&IoW?& z9zehM2fZ+?c&gG!Az7hqh{a@|`jU_*0!61U7>6~*PknfFOq}7jw4#&MWgY@7s*^L> ziiYloYAsUqwSa7mYX(lisV4EGgr4POj_Spfe3~aJETUceM3w{|30VVzdh6LxYt4(! z9dJfU2^Jqp%>LA@CS!MIiu>42=CJ;Of~YxKX5J6|rdWGCkd>e=9bVvW(6*6%o~+zd zUmwZNNVXX)jO;7BH^sB;i^$U`0X4tYk10H;XDP}Ut1(+Pb^ zuH&uTA-N-&>(iQhYByhUIWQEEf5^E;j!nV8J~cSxQFh6gPSf+n?O?H*e@$ zB;iy=+{a3X4FZwoT&b#-y#v3FJhZ@JivMaY3-Siw@H!a;oS7(z_Ra+F2?8G{)YiBt zJvV*qyS2kb`VTCa<_=#`N$0BeYu9Tn4D%vh3;dnZ>f(w~XDc$l7qQOqZvcgVHhaVO z#WlXp#ML9xrq)NIa{C2UR*V-fKSX!2Z3K&tmV2Tk9NQymn40ulcCi%4!-65Q6T9VVCxCC2db2cRp4Xm&kUin zOfuZbmcqS!XIPcu-(aqYqzV#d_^g66^HAc*GMs|wXz}%am^~HYTa=P>>664APVPM( zLl8=GQgt-+D@r=Egx4VrXg9>Q&XN4RJeSFzoE&+3=loHiM`Pwy0WegnZ67QV2HZ9N zhP)HL+V1@My&l8PI&T_FUr-%66tzb${YgMpor`Uu0=#Opz;5*_5KC0G;8doX*Mz{mUAn#U zs#xc?haD>d49&-nPpvIhm#{|%^N$b*^II_QONAGZo)^qHxBavr3dNIGR@o@xQ9?gk ztUx1l+b`iK{oje>@%sbf-Y@4*3kKSElH5U){jqnC|3%k3MoAL2+qz}jwq0GeZQHhO z+qP}Hs>@xrZM)05)!*6Yo_ogLcm2rxlOuCv#9AvNo;m0H7DvkPZH}_Be7m5_|Iwy1 z?n`+UDk3I%a>>P5{M~7XXW~R3x99Wq>i2Yj_P>(88GOuSl1;2hLEy;XA+CODfjP8#uT`v0`&{~Fq=oqm4R(7&yQ?Xk9Z_?r$h;?fXG z5;&kA(z9{?2#uZd;yy1aHRGXHcNC;9`vhz{2}{MfwN`Xv;=ile!axt?iaO5o8C(VM zBtPGML0a{VdU(AdpwRZ+9|X)V*1xzDXue;e)R8O5jk9=>Axm$YutBQX`wu7<6o7-q!gh@zNUF zrl+!p@d#xj4|V<6+EA)~Q>51nG*o?v-{RWrx*GC$q_6KXm)7f(b2x!T@{R>f#~S+Y(0sT# zYOvOGzNtC(RIzL*T92(fe-#49NZ~qd64t1CNRZM`-Z#|5GTXuu(OyC;G z;_$v8d1XvSHdOsshKG~JN_zg3Q3vd&AHI=txS%JEi5N;BEy&2}7daaLeR)@9=PsI4axB5cGNL=O7oc?_8pOCNJ}?%+hO$9WpyPkkRn#g8 zEeDbjv3vL{S1UZkJtDZWjkX=;snGfB&jzZD5PjZf-9mi?+Y{dKA$JC8!-585OXekh zZ`q3?I7)_8G-?4cI`YZ-pJ|?%#94jeip8j%NuRM(E1LFIjDI2hhaHJDWQ3AYaqe2Y z5Lxp=+9rS{5#3la3Yno;YSU?URE;xPYtFr)UPl*rTXhtOjPyaN!3{qSeP6O9dHekn z{oHZYf=8N@D^Qok%jd&(ITp2dOa&H>hu>v*hZHc-V{Wa|rsLIEk51VLa_tE*Y zXBjLF*%v~O>{a;{^9k^Nn7?B^0p;+4^Glb@vR96o5%QIqZq)d6WfsEaNRsh{L*4`i zSG?0a(+x#H`(PuF&+8f6%dGRIt>YIO8a>{w`ZcI?o=Mxjhr)^H_WHd&>f2hj;~=I` z)JlT}QUbvIpZb_!{g<0Q*(~)+WqLxafVm5N$!~0Z(}JeZ#+G zB!g>hZvTb^=J0CVkyZI_O359&8oKHjfW;gze{mae7~yD2@U3UNbVL-Q(ltIhCPuRRqs;zJ zw;!AC4z_WD07Hr+_j~+w6)#HJ%B7hJFx_^Xc6{adT@0z7|CTbmHJL-*sg2S9h-E^MtW(+l17VNGUu6T@7PG(%Cq z;vRr?85oRf`>Q`rtnbmtCIAXhzMQ5!AU|D_$V$h34_q&IdtW+WP4IS==o-_Kz^0DP z&WyqVzS=am3$&iWSP-!-jN;{SC4jqQI0WhhtQLPcRMmoPb_*swe0J^jNLQ?q5s|GK z)vH1xeLRL=3qdooyoo{{>M^+)$hE&+f_fEpDVxe>XxfjHaGm-+^2fY(_LAb)zagfC zh(qoqR7{__P~|mq=koYUSq=G<7C$oBM#)j1I{y@FhYWuqFPkMb%)2 zUNMLd6oOQu7?k6LQiK~Y!b~-_&+2Y!G9s7-s2OvNXSI&jzX4 z;pLe`=R{7Md^ho+8Jt=?%~3c0Z_wHR$hi z4?ObSEgzeCaP@@r6RR<7h#VmV!>I-f^NiCH+8X0{Ml69R+C%lmycY@1J?3}Q zF_zw+m7cs*N&?)!nob~dFIYU2Ib^N0M2@0ckT{pViT24t(wQ58`0oK4Y zQyNMh3ldWwEX2R3gJf-c4L$OrJk>!ycGdaCj6dww9nW{cL z#++OAcHk01@d7Y~B{M3MEuCUYa%jcsmlAk(cX~7(&l2`4)e%AqCoPj0EYa*3B+D#S zYiHS$nV>%tv-iZCQW!;RaXwu7@5*>}?)e8U+X0?GT^lP-mzT{WV0UIyVXrkGs;V#2 z1pG5~DyJ zS>to(zHT?XRK_JPZ{?Tx{;T;{G%y`vK_~?Qc`KHtLaj@$UM}vJLEgAgUS0M3k~KMG zPi^n~&|i`wzr8Zt^mjEqNf-AgO;6@>;|2f%*3_{M-+g%>5Qy@BHHl)GD5kYIo!prw^vw~Zo)=Q-uIICHby zZ_X1Coi&$SUG1=BWN8TJ(9)QXc-M4qDXJ6~FNdZ@VhZiyi6lYu()M4#Y&{`P+v7mx z#KJb)qlpxFLdEj$5f`&IhM%SnH0y?Fs$4-X`x3|B5G+FcNd9CgNp<)6Uizd`@3PuZ@fCyIOm&*a7LV3V*!ZWl- zt0jgfGeKZQY`Gtjs6AS1UaSgeRzj(u%dh^n1E(Bek@WSU!!)N0l*}8}eg>fXIg`>n zQI2G4#;d#E1VWopkF0NzFi#ts3R8fp-P&R{^@geff<)mV=gT`YJt(g476Mn-o~)Iu zGhAPSH?scvp> z+$f0ndbco4!sLRiV3_S}?D5{h#<1s0K}Ry&Io^wNol)Gs^M7>kbN=-Q3{{KfDfsF0 zXV>#D_XvjPEl08SwA^SCDa&hZ^SsS*veNODrm`7$T+79!Tnn1HurW{-bYj5LLr0`U?{wmZcqWE<&rCsq+$S0e3CEu&y_9**DbCeXlN z>S$u3tBm9BwP+umPm-(FxEJmUXMhp!?iP>2f{Jl{p$%(`$RZ1GfbAM{@C($?GA{Eg zk)czW3zW<8MVDseG)gH?cqX&mdHLY9+STNn*YzfPp4v3kR zt{4LcXlhXT%T-XD2g#glO}O?KKq#7 zSFfgKc_RSl+EuCoFfDBtek~WV(H&S#HtUqxN|$~xh87lyyv<@rBi~D9pkU(acNgN< zWv7>oms2`l3Km?Bo3-KdTe08j0=5D~JLtnsE5AdAy6|?ZI4Q9&jW`rtZJd8{;pRH^ z3W7Z?p1~htj zd8*~M#a|4ptHHF&0hLzGt_F9b2exE3W~KlDbdv*yVlG~CYkIQ&|KW=j+Y8!K3edZ( zS(pKH()c{cdCfbPj;Ty`NbJ(lR};mn~+@k!CYx{RHVANtCSRWAJjS6KbNU=PHFn5e$ENmm60 zKmJxz$WKn0k^h_2<;zs+qEInQ{+^f28c4C{<7@U0de;Z4ULt6gHv@>Vf|=V6!aT>0 zcsR?!C7LOAe$iX?U5b#OxjW!0AIv!`Ds)I}?4M>{SJ-TG=eZdg)oo{=MJ0>imKnyW zVF(;_u7!&;S}%WL`l3szUBJgV=&+TiNfMnjBryH;aBqCv0D`~$j^<}@DiA)L#=!Ed(S>NjGMe%2sAxgU%vrqys@#2v& ztS2pPZXKgD9aYpdjNIX+j&KV%%ZrUvtf(jH683nSO`oI*abf&&fO;UKJKjx*!MW>* zDSz-=c8CzNZnz22^?LT zQMf7R{w+^clR3Bl=JToa?zi;cz!@^B0{u+W-YH{X(Wujfv7hUW)?iqwR|l~^pc6RB zt)?z(RxBP7yC)R2scb+iaQBM~R14Z~iYIBou&DC0Z_)LiqQWQV?zUL&zzaF>cRA^> zxv`Xz&YJbh<(}=JwJ9(S+_Yq|xF6xdqZ=65PSCF8zJ$Zw;eW2@U0#AZtf@_a?T*m! zxu_iZ4wE)DX^z3>FbWYYIoiLS3hOi{(;1^0WY;C|9%kNdd#om7x?cavW3%8%ZJk3vw1XbLq>5NJ!F|AfFfgw->1aMY>!pL&kC6FW%6GMN9V;xOS(S z)oBH@o*CdtPIh&tvAPoJ;kj9yUWo*MUr;o!YG@glTl_X>3h|@UjBwlTYxnX}d=Fdg z5ox`k#_x#vnWDA!xqe@HX(vR2KX&`T`3U(Pg=ic{THV8Y6VJUHrq}p{4x)O~+2A&J z=Aogl&zq!6<~V|Ak|XpnErGoPKTyu6Hqe=f8?VVOQ6yZ_7oO2hsA!FLp;@Ne<_*Pz4y z>;#pv;EA>(uhmbT0caNFS;N%3y$;Yx&IC+hJ23hlk1-HfT@aUjBd_ME54)e%`6X%h z#eBnJYtQk#h%m@-?SRquwdXe*1tP=h-zlC@w+posoG1#uqJ0M&?}OiGUx|zq-?O z!#&g%gsSc{0N&`$i5}$ZrY!JlJ%c?Pvd#|o zx_)UZ=!o*h44gvEyj7Ha{WBCj?6~x4k#M`{i{$Onz9xl_)IFq9u zpH(Lur8&b)(5ZV;Xg9uX0gx+O^tKP5s^~l=@GfL)zUT)=K0h@l@#f-?5xhi)wq}-i zA1^oGfh3ljI(+`-e6%nok;|&?^1kR^|0HT|`_on@j8&s`hAZD_a;53SjIaf@7q=Gd zUHJdE7hrRDK8st5gf2nxfK*jCGVtZhjY+603BC<)*kYCH*lVQ8Q4_WU+c#hNZ?+(* zYN4ZKa+>yf(Yvg0LxfS{McUz_jx-s1P{P0={3_-bNK#Q9S-ClI?cB;fvGLt-fX^r2 zzeR(>Y`q`TBgV)fXDV^&tSVhY_8xXac|GGKF;#*?S8gI}j8T;1oLy}$Q~*mf4qCn~ zWocE`bUMa<3!gi8O4(s3Cs9x2d}z3@jlI@!qJe}JO_B1}y9MW`P<|WU9@hs8TS{U= zTelK-xV%dGQ9~L89_O647&Qls+YiG&ifG#sGM?H5r1}ZAElopgeEQ2&#uv=&!Ka$? z%6+*$V&$1Emp4|!oLVprDQ&mQ!+p}8xkc+$-wq8}tj72{8r6ej?gZPU@oT)7`jR_5y|U{UNxFips`0w8L;n$!&icm< zf8M!tWYlegZ<@%l^_v|~;bKAcT7PQfp!K+P>D+n%UkqMkUmAI)aX8dtP-xvN-6O+r zB$O{U%G8p95k~yVpFH%h4F8b>64rL)tJy*B5;6iw___N{Cg=$J;J3eeYih|cs!4<1 zGZ6MTLjWl+Ai@?*8De$_NlJy?$*{>0u#TLjR|X<8PAAJo&ABX5ee@llJ~9)s-W})R zv7#zD`OkG~afz#qj1n1D8Ib)~PTk3#9<{PomFL}wRPoqtR9;lp1BwMz#XVTguwj8< zb4i{kd{wy2!}ZO0IIH^2fqwooK45>-h*?zDxevdMYG5amiipsr#hM`l)({fQuM7;2usNcYRn) z3E4yiUbYVQyC4e0OnxKAI2jkE^m^D;9;N}$mE@2m*W<#3g0RV+JgiC@gr+;HVQ{pu zx4QH|1GD4k?4;L61&+Y-k9{+9quDq5CDlTajq8YSIBbk0DwH&Y|GX(pRA_r*_YHVs zOwQHGO!8`QzY4a)5^nkuO1}>RQjWc@tIY)Na2dyso}+__U95tZ2qJahkKR!6qRcI;0Z>Je%# z--1~Z=ZzERrLek9(>=SwPALdVlZVQuJZBC%`JaD|2U05J?c_~P9-=8K%q^+XvXN zV*j=w?v;o#1I#)C!xdM6-$R2#GzB}Lm7p0#!Av0^<($$2^fJ(ak*x8!D`oTR%F;E@ z&oV(dSF!QOG)so!SUev*=wIM|kqvow2l87xfuf_+Y)$EE{~@QjKYl%n zdik_(${m$JJ8|Y|+Km?q%Dw|QFxaob8`FY3U<+`)y`H~l-a&Ro8GXo5G!XtezgvP; zeTKow8|69W4n_oc(HS3F$P6!wHgQhH?*q_1T)q*jKhYfIF2fhthW|SQZ6Kq0V@wV6 zP;xe8sd~mA=H0K`pkG@{D0^$axg^$a|5{g9^QpBm$}%S-A2QlLz@1YEw2NT+F4EdlrbzrUp8g8-x2HlxdfFNeaXNmuE_K*>N|W0ViHOl!F2lsxqeJbay>s z>TbTFa+JDq4EreYS3r>!?)l_O(Ts5I|8$h=9$o-yu^PhIFkuOxP({7Z?dW$9MNy;e1+lwLNJfa$l8!v3*T=^k~6F|JFc6dZcIzZclJH zB~`^2AE10;y^eztA+HE>w`OS*ZwU&{k!ZH*R3OSJhC}l4XH1b}^OFG7uXu?@mrGlU z$xdutT=5mDtULeh0wmjUb0;7QOV=ya!Lo{K0{@mxm$0Y<1es;m#+l#{FrGuemCq4J zg{)so)Q4FQZGj)Ae*TB5YH-O8$N>*4GD>oqC$@_^EA0@eIl(yRvE{SaB_0Poe5~-= z$U221?29i{%|PhS?WjA$JTMm9gM=j{SqS-m!>(8b3HP1=7u!c`UjQYI3*8_fQeAUJ z|JulqcD42e?p%g>yd8^NQC_s&zr|iDYmnSGi~r2-ZILN#>10#V{R@_i3Se1XX;JjJ zlFa0ND0_VW-g^v@k?FnkkjTGj9zhzNodbaOF^3zKYM#7jn4yie&~P zw<;j*?fC`#hR``6mVP6zYeIu=*3x`}1@hBR{RbI0xKVYTMjYk;4ZoKCj|@1ex1jtN z?vJXK%?L|Rm{sTcCEmad*fD@`HN=IoUJpaOwlrUzj?)OEq`cD?J^kekxcIf- znw3ei2hSx>#cy*J((HdFS2b3&J&z+}TQmwv&p2#jIY^1KsG zcXLvW(srY~D#R`H#Ya27L@^i@?B4(FU5p zGEb3H{4by&;IN7aGq9--;o8sj;j#$*ISg;;Rri^i=d{Yw@0c$`teobKgx8u9@XPnK zQL8hpggV$%VoM~U{?*M*3jr5BTXtn#0i5iwDZfdO=o|zFCG}+SlpoIAI25ZY>o4NX zYw5RI>t6nS=y<6)(L|T!(I=@oq&l~X)y%)JB8H6=C_Yg&zfNXnkP&cwh47CW6bQ?) z+a8W*@)9i(_>J<1VW?8joUY)zUy7&=8sr$47Xu46(2&P|Y64`2$@R(dUM!XVG|`+E z9<4RZ^!bTIeFTyW+oQ>*kLDo%@-W`8wOl0fkR<$Zf79F#tVK4svO&f$Wndyo3iw^C z-H=Ldu-oEr0sv5dmrT0K82YGS=l`DO$vt9Jf?&5oZIUctuZhX8%bx=Z>_8>{kzR+Y zr7eP@(9Ej~)_`UudjRX*20EQ?^XW_afsR|LG67>!cr;6p&~f!$cxLE&zNCGR3AB^t zjaBy$eaYKi%71QN$+RxM%(D`{0m5IstudZeaqus{28mMcC^G|kVnw6PW+F1o8zS+W&&V+o{Ue3| zDX^8tHr*|ZS>XzC_0|Ob{zutExK*uzkOJ6}(OE!Pj^=Zg<+ZioD+aISWMUb$j4X z%^cNP?+iy(bd>1)@y3~>HUWk?R5lm3$JSYjT`S$vI03sal=%3ZjMg`;YX{!5nhMf2pH`n05 zJ6@9{$6_^zeoDQd`q^L zL-)yrGjA{q2KY`fN#dJmLJX@qKjPe4WLmpjp89PkxS*W&N-Uc(aNdhyedZ zXbqBP3*9O}X)75_D%$@c*9!t&8H&i|xMq!x)+DKk&+g;Gc+sEuv%< zLg;FcyvO-utCSI_M~cSDb(mUmk|sFgb*?a{MnhEzYRdr*UM6E~W>VE_u_X~3SZl*U zS&nkHPDk0rFfJFUG9?ZKG^U(CX;5%>^%J0vnt5kjjZW)e3BP0*kPZAB!0FO%H@QP^ z+ovS_IWn~zPICTArvWs^V+;n3C!~hwY}m7^8)X*XXBOQE=&@vDCc!!(1RD#=fvi96 zY`jFu8Z>~E7F1S}t3u_DM1#d~hli`lgQ9jMD`(ild3D_td4&+0kH4re8l8^yr(PjG zpWw5h<)yTC1@WFSk>{wqAnt~o;-8ADf8JN;)k(&g&i>d28`R!S!c-Dw7)ZMSVl}O| z=|>z@IFk*?2~P()-`y9}%>9GhFs@ls(fm9yfJ|JvEx9of_nTKJvATiueKR1!7x(0; z!JM<1&rp15`2BCIdEr=H@mWB~>N@$BJFWWGB{F-G?Rof`{8zl`02i52)T_2AYOrl( zpSxJdM;%!ltMPJz0>sEdW(<5pVLSuwWE(<4Beqa7tXF5*X20l*)0v+&UJMC|`}|pz zpdme4q+`PgM-EW9&UGR%5##J0&AJ`=#}>z=AQV#XtwbSZulLvi)iWt8sF3gp{%GqC zc{h!oU2yn%gS!A9WbjgDPW9oTwng~hjuKjkIqVFCLDp$c0c$-itR@-$t+=cT7QnmK zUmg8H?m5d)THc#rhDFT-Vr2lU)L$KM?OM4>5aN&H&(9)ntj-}ym zLJ=<9aWi_cPSfw+i7Jks_3Ngc!a}M^!FE_?&UwAmG)p)#yyJyqMd~O#utou>2R$}` zfYKs3ly=0^Za@oxj$;maA$&GCGgSS=_6(}bjxW35B+ME7xPLYyRuB*Qa8{BVpSoLg zLA>I~?N@1oDKpva?-^PI)km4+fWU(f*3aILIU_5n*%O`Pu}fqBxmYVA%Iq;4;~~N% zzm#B$3QzX6Kj`>WbK4xP$H@u%0wN3+)EP*Uc3_Ou(YWALMv^Y48-_=9hRDv}F|D4!I5tl8O z6`l^8joPRg3FPTVqtU%sRNt?pbQIQ-&paozET*XPDqe|-C5Fw!szB`)HCzqwicvMwM7}f*mENQ z1t3zmUc6UUvd=By?=3z_4yCsRR71o)6ob?X0`}3+L*L?v*7?GhtMMtF@I%}#d|Q=+ z5%7(rMAubiSyYQ~*t7OnXBEGwHzd#LcVM*6riUn>fA!Pl-T1x-8uw%zcM{| zQ@i2zIjMOepR)vu-w+CW!VflFiajm1$m^sER(&Fn!DI{v2TUs;`;L9%uF8?(o>{ua z?=|~}e8noGdXKLgNi1qfFD8>Jm@%bC2z?DL?uuKVKi%5w+Z{p{XrnX1xm`lSrF)M| z5BQ96E(LL!8P{ra+Eg4-WHC9KThfZ$<_ts307SoLtz~%?T4gafyQhzbjS-LTmB<~Y zMF%?Zt)mR{H(8?G^-g0%uH31pT6k5@!+3jGA zfQS`RtqP{RBW!9tJs6qt9vQY;G5oA64=cu3Ft*T;8KdR=u_4b5h4eed8}gF5SsQ@4 zT}*El2e>61c8^qe@wa*jD9mV`Pe5PEm+;_qP04Yoh6jwn=06s~9nA@e-J#FFK*?fqWWr78 z@h`Xe9c>^>Ttu4T(x))sxgr~X-QuEzb*X?b5*k6O9@Ss`uJTUR^57KhxEP3l%yA?` z16fbX_Ke?OKOkx0L}ai>QW`XZB#fEr(lcsei0cwtYp@v|#j)b)bCgj|E19>%m(Vum zM)uw+pMDK&gTu*}WRcz^leOJdXKPq0sd9~PY*Ol?V2Nt3DfY1??oj{H=5b9-5jm*a zobpQ(6_enFK1Z1dt&tAEG!v3N{h?IcjwD7s+P0slQ#~CxxXu?ktbs=_(d~u&iBUW7 z8=r)sVglQB)G~+OZ}WadF=}E_Tu8b}d?UBL3Z+t*M#Mr}T2#vxs$&nN|H&BY5HcNQ z7q(-{e32(ll(Q+zFA7|Az4A>@&W!al&JLfFqAiqMl+xRP;IE#J{-MY%$$Zua$_?t) zE#c#e+nSDu4Ju&zZ-2)qmTR=gx$pld^|jIb`h`Aoyip#=4+TRzXG@9oO7LIjI#a7Ed4IZnwF##H+i2;uPh(7;nC` zI+jPl(BBPnyB>VtbkCpap^kIKL>oR|?bz3*dc+ge;rG|t(hyu7ajA7>N_A%$51+t2 zT)i=8YP!XFlAoeGUQLgwpC8^jk$bxG1drzpdBV+BXb8(20DJQJD-;c@rBAxzSQ|R> zYy9kLRXQB67W_zEFRZv5FD4~i*7G~MKl71qxNkARv(7SPw0?d}ZM5O8cVgE_r(hP5 z^+fbK?peT$)xdJxbjoSRvH8_4UgV5_(PhP9!=2uGQ4)rf{PprPZ*2>~(-zl7!ED`s zt=h+uJLW?7_=}b$eGezgTqvS~HSY@B_jseI1!KA)E%u&P=F;Z^m-i2A;Ce*62y_SO zI;>U>|JYZa$59k=a*khh+irw8YWlwt!rFFP&MVHsnpP?o@16Il^#^5PE+qa(_)0G<|@4xHC8Dg3Vbm~Y&L<6fT4vm5oP7ZbKctHfD zD(6>SSsR`nh~UGFOL}1e~7-bxtYu)fc1^Dz=_`L=5h=tdxW>WaGjJMreolX7ctWy?|{9OaNe*bcsFNGD3)9Yw%d=KB=OHt z)%&-m{z(@c>GGpc2LbkLUeOwWeAC@@i0WUyL?sXEtzXS&QX$iEpiHqclMHiidd_AK&6mNJ;3Ln0 znyFy3?^Q^3==?@*dEE)%UCIFY(VRYMqb50=IeyYz(L)F4 z3a7zj>%XAoA5CetL4iy~WhM_;tzVDoq4~@%Jh|IjAL);d_*ix;6z^Xe!D!H6`@T*m z)Ks8mSsza4sS;Z`kxXo1&9^tA#$ASiF^PMb*D^w=REnYWS>S5iIaBn_Fqii0LQu19%U8_@p@v{r( zLF8xp^OQ8aFA%`2*CZO$ziV6xW_u$(L8q>A(mDc$=(mp)E=b>|#d6 zzZxyc=B6c41aaScUjp6WmJM1X4$sVr*gF>{4Y`3vmQj+8k`&ELjIJPlF%r$;_wA%Uy zXE)dB_w`oiwrFj&yX+BYD+8%)@E#`Qp-lRjLo$J@>$Nu$Rpd?Hgz6W57$cRi#SF** zgD&@P+Q0u?1M3Bdne9(E>fF8Lmd-YuYQi=r$>BTi*MRLBDjK`m5>3bB@QMttDMHzC z%;b6iEZGc2H4-{`q!4RgO9zBkS+3yn7J`=0D)OEZ{%R>}>jb#7&yQYkl! z$Z3WtweRgvl5VG`H~Q>xWhWtG!Wa_u>=zh(ttjaFQ(ILFI3rbH5^7D*^Lp(pJ3MFi z_ufpbf;B+7@jLvPc9$^&@ROS4lb=t?&W8B7?y1+i1R<6dsfoff;g2>k6M~EoLffho zTCn=f0y;)pE;ebBf4na`Sjs83{W1>7mgiZEt2DWBz;elZJ`PXGs_fhZw3f~1zp|kD zYE=dQe7TZi)eQwmZG+t;hW)xbO0aEye%S!(EtYB@RfG)hb1B^6!t<@GEma)^%(qBs z|I=Lx&duxVZjFDO)--ffm0@UXAOQ{ZS{LlHS{ViJ_TT}GSZya=?1P_a<6>z)w8WKU zwKpSZ$t;<18Aa)Y9l{NEA347Dm#bNq(+M!!Zo?Hw1bNe+>dJysN%fFZ^lFS&bJo34 z-ow`KkZw-+qo?+vu;gk*TDcSk6`cvgcYz#F| zT-RDTvQ1_*-`fcwf-|q znh4Rf`%i_=#se}33ZEyiwrg8M{$~>&QY##uEvAc#Keuzt`(L*K3BznKBzv#uuW}Wj z8?$4Zct=q_nw>+xSA@St+&Vs2Vgr=Xs|pLh^6L$Q(`oP_%XNV4zpq)YUw9)|a&yE^ zvFn-~g=nhqF{EzcJxE+yK1C0t(~XG3sAnQSQqdx*0j$niXFcJ`r%S`1=Nld9vV=Yu zz*)al#nkrNDcN!)pY^+2Mu(Y{xsdi}hx#j-9C};WV~S2b#3RHuY4#=C?&NL5im0nG zTV6azjQyr}wkd{B8PdJJTjEjA>TV?)7juigVyWD%3;(wlKx(VSrlQ?P^4z~Y`weH? z``n7Vi)!Wvgb8PVm)A9@6!HRAcVldSpgr%XMH~!ixt|>yT)w#xsRSm|APq~L(TT9J z*3~aIdZk6aG6mNA>2d08d^fq}?kT8f0sGD@{>7UofFw-OMH2U)MHChh036=#(EYm( zS_}L6mxxuqt_NLSL75*^*b_2%Tac>wIaiu&VfvXElEsNEg9KvxffpV=gTv`b)9R*W zg|{oaN6N9>KCUpU6XoJ6FUMH~Q{p%y=ZGA&tHjW%A(#%X-*ree%ftgBsef$ z`C9jIn2(Fuj6B5QHSAvQCs2&(?{Z-?MR^MZ07P_n;@asL;rH}%It2%FGk`DvhJ~#i zLCZvXttt>m=!afsZSbdIVkhF!3+v6YJA-^Z z(v8?<{Sm>rub}MAxxUv-KH{1)jU$sD-f}l3dQSwdZZp=FG^7`Lv{L4Y8t%cu5xs+2#G>`~eM{pI)y5*aM$G$&v0XC~_0HsJt!e zf|AJVJ0FJ`9XU@OTG{u?4mL)pI+-p?o1>LfQC!g!VolJp&k_@!?vi_iDBZ6dXMvES zap|BjPZ)&kf%ZEp+KU}=3*Eq#Wcr8%mycH;2c^uVQTK;CW{{woySLg1DOZC*FiM`Q z6!J4E*J0JOk0JTVR31|1NVM@-oC0G{_JB;|abXJ`PTVYByHaM3j1Pyw2p2ia&t6mE zBD|#Wf>(|q&G#^uytH!~X9-LR1G86&$Ge{i>V!Q@g{Jh=BjuZg?$Vz^nL@>shE`y? zSj^hU8X4!p{qLKhrxid{ zq&pe{h*j;YGW*|BMdTgV(I@E_Rpzt8`-`bOTR-Jj6Dp1CJ@F|yMVtUyOUgiDQi_wC zo$iu(p2pNi3((>D_<{gq`Gv^rcy~t9RI^st$gSR+cKH_MFLy@wETP#g@0=e^hm_

;1xS50O!Pe1VCuQ3nRdU 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 literal 0 HcmV?d00001 diff --git a/www/mu4e-splitview-small.png b/www/mu4e-splitview-small.png new file mode 100644 index 0000000000000000000000000000000000000000..ad059884c81fdf49972d087bd3f6769b786ee8bd GIT binary patch literal 62377 zcmV) zaB^>EX>4U6ba`-PAZ2)IW&i+q+NGIkavV7hM*s5^bA$v5E;tTJkP&l(IsQCkmECqn z$E;FVDrMzD0^f#mI{*0lO@HI7w5myKAI(~O_)=5LlNaOpeDPcIBaiV~zQ?}5W&VCV z>GvX8zrXS0cpiVcQU3fY!jX7=zBg*$7bSn*5dHk!_xAyXqkplYW}`p)%Zlv#zJG7n zdet_1ZQgR`_W2Yk%Fi4RE3AZ{li$kETr7W&r1*nFwY+zUAKbdf-o7i1%X4hRY=U030F7H$2mt%j?v1m;CUpn?~ zOMhQo`kwIH8|=}4UEIAs?mh1bI<dEgZlmnk>Nd0%YVEQ>bh&hMNzjf!KV^lW**t&5>GU(+77KNkv z-t=9IywA1wd0PfgcHz`4+)Q2o{G0FepPclszV8hR2sNTZb-es!T{-%~GNSGAlhbH| z+;36qTi_qxzkQ{j7*$S-G7mO5pY^%Ls`BY-;HkX5Eu2^R{Qo&}6PM$fr^K5By{^ZEYt1Ml0wbj>Hw&n&tTX)@U_dT}l>Dh~`S8v{ZxcNMCfYQ-Z z(`l!laqP?s)^53a>utB+aqZ5ZU6U_`|NQ-5bWOfp%WtRRy#BLm9PRz{JH2?}CebrG zmR0C@j}8Fn96fu6sOIQg^z5+=D{5wuHG1RnOletD(IdHD`PsWaI`?1oEj9g@earu8 z=Tfxp|Lok`w{+?+efx{9c^Kw?JN98=)buH^@0_QtHEUhv>7Huq(&qG?SMw;|F)lk- zcfVqHyeyb^p2^X{RriiDkCu~1onxH6bdJ;0>cgq2?UA>w#X6v&$-bx5(|bNv+V*@c z51q@PnJEYmuC?o@3lC%yGpX||Dq>f-XV$UByRq2o))4C4=Ao`^5~-=H_T{>$)2i(* zt-GAwHd{(PcPx;Su#npK;Y_ISO92c4gNqhwY|r6sy&jT#_gvHO0FtF|Rb*FAvb#K< z=F(jEb9*cV=rUj z7?^plg;!R^tZ8kFRqS=S9rA==VU#CVr%yFSx4=??U~WUZFDa*qoqJ24EnD4>SD8R~ z&UWr;ID#K1!CB)u7pr&yiM8wkqMoBj$7|w{PcJ)?1J`7X(LY=8LG}mrGWbeH!ncTYhB6BwzVzC0i+k1 zm9uM|Y^5DYpx0J9MnT>Z9yICmbg<9HxohRmVH4QzY;C|P7l-*4(C0io`Znj5nmBc5 zcp@hb%?Ccb03Grvd;jC@A8-D6i!^x3E{mF+%+>(n9C15P38!a0MkfmDTv_c{B$#J* zJ5tYb|ExU&bEL+fj>3lhuf*D9-be44y*ok#vkvraGB(T34 zbuSwY?ipJ`GW=ngtD|(&afXXBjfL?I^m~kGbAkOrvg~)RcD#-|?QHm|?7y7`e3imh z?av0)xkJ|HR@u+#J`tP~HQ%N+c|kuM0Xzf#G~m2y1vfbOXp5M*h7VaFhwiYUbsAs; zilDNpQj4ZRqhjIgcrZ|HwpF&~dd_+n%{-p#tgoWS=+_cUPL`3-!mQv8z

$Nf{^uLW$uE@W;}Im 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

cB5ww(6EW(q=$4L2)V=NfED~KUoS57TddK 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

MQfzNww;?vGb1~VI$aWFBtXqZgQ?9^ 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 + +## The headers view + + +## The message view + + +## The message/headers split view (0.9.8.4) + + + +The message/headers split view, and speedbar support. + +## View message as pdf (0.9.8.4) + + + +## License & Copyright + +*mu4e* was designed and implemented by Dirk-Jan C. Binnema, and is +Free Software, licensed under the GNU GPLv3 diff --git a/www/mu4egraph.png b/www/mu4egraph.png new file mode 100644 index 0000000000000000000000000000000000000000..089a74420edd52a6ed58d256e0dd9240714c79f1 GIT binary patch literal 366402 zcmYhi1yoy6vj&Poixw!ZK?;=O#ogWAwYU=?xRv5A#arAd?of(Lp;(aM0a7#&ireFV z_x|_2m6df)cFvw;X3ZY`CRS5j0rxebQvEd5!OI5>YZV1qr04&uU_d*wm+(*vPN5m-Pd|X8RU&*zZWjzNvc}zE)~ELn zi#_@;`CZpdG>%%SwO`=`g6C_`S8VWnhDn~R_3MaIcFZUOEc&59Rc1ryS7<%gSghk0R7`KdWKHZgJOwFsDx6IFzvZ!2_}q_smVbh?Nzv&ABam2m8Bufuuvp(n|M~kh ztBIwm<~1u*q?crgnkvL{*)F3ES6dlTD|-~JYG+s>g%y>yg{nNv_nBZ!H<|#j|JmE0 z{uRAtUD7Qbnz6Hd$s17C{NL#6YU>S_&)#@&Xmh5vEs88jzX6*$wq_*?r6^C?xX_o@ zEYTT9RngJFnKh3vVsf6z$~+2sl)-@%c>xDk*0`_FU?b@mJ?2Rs=JZ#f`ZGc=y>C&r zJh6LB8M4laSejW(+RBGrryCNJO&re%fD97QEFEUYK7(Xeel|TzmiUp|qUX9&b<0fk z-oHsviD-5_tnNA|7N}Hyo&uW#DAMCOic+h`Ntzp?yO_Rj|-l2U} zudp?Wo?=oT?J9)X8GO>yEAu1wId~B%-`kQ|cDYm?Js`U`{1ttvXpzdiH44z zBHGxExlxu?ehJHKRUIuHOfzwovat)CGPFoh@FfAt$WQ>xET~8{8R)y}P@2KQ#1 zi7Xvc|1`c(VF=@Dldr;IwVQ(4!I!VL&7K#Be5%kf(hjWcUKAZ+8&=fv4vP`EZ=Q6mw%u@+cIj-$+z8cFQ$K8~Pr z#+epD^n}rQaAaxxOtlxHFAZFY7BwK2i~SgWz?Xz;XH?wE%!!Q_;rNkB>QshPLAktXIV43xE9AY*654x_88W>scuYU>}cN;n-!S+*Dr@#M=N6#0T*SUlzE zq&Cl&F-X5>8P-fvwIi7GemFHxAl*(#!F?SEO9;&>IdqNU-zXzBQRo@FVWeal6&axE=uTXhwU+R}d=IK?(I*!5?$Prp*RM>KIG=x- zjQ$qb9C0NYU21qhE_yudXRwPN!@w&0F<_PZ+S%qgHCqNDIx1W+a*dKKN%*6SnRd$a zIEw-F=b*ytI68qB4&r-99f~8ZyiZDcwlT+7=>EJF5aKbY9@25b%w|s@nPkheE+^EU zlanKqM1dZ1?g=~lIj;_w;fYGHX{JL$2|pe=Z99o4z_Mn_G!{?F5BddO=_TOq$Mkf5 zzP^{)S#Ux-J;s#S`PDY}c|npMZ;T!-AIPVsRzfL#MrN}UmdT1>9}P_A&)u@|egBq- z^Yc)k!uk-h*d&i_Ie|6-*3h{uUFlCoz!KhF`gl|^3l?(AEb*SU0&$N5>t`^oot7*j zgGWa(Tsw_@@{fGQ0BH+18tJB(Z-Q@C`g`o2#K@p5y9~S7*3>8=_i#ybTR!8GymHE( z;4?$GWLQds=%lrR;xSe$w<0Uc1PZCB^cY7XcRzG%t9AgBYxP@HOk}?|j>6!wX0W9o z`#Bh@^Vw^|Dp85L;uBAfymX$O*%KYwz^xz>8rBFQ0oofZaY?MyAf;FWLVH{}@(WS4 zGY)aiNiT$`jj(cj9xIP-IRQ&l%w8-K z>)UDaAP+K#F9OAekKR8HpkRVc*yF7zrJ8+BR%d{dq5b;B+_W`FVsZEPCP$iL(ZJ1m zD%^g6cT5@i>2DN&m6ldlC-t}eAm=27sYf|t0j`m8Et9@)0O_J2!DTL zNGgNn|I=6@3(>|jtu{}GhJ{=*i{<y7a=)fm?#C#=%g%BOQH*EXBt!1QY;Xz|h4K`$ka?d+a zyo$qTVdbuZk7W#zK`v+Qge;*WiK-(yFP>`9ich?HJcB)vlzYb7Tm;57JruxF5>7B4 zTwCG#NS_%9iT)fTpG=t6RXtV;n8D6Zv{7Vkst?A+Kp*+KP-I74l>wlz)mE{G@8uXg8VKIK!KpGn;bWVqNWgXk6kt7>(;a%i@b1HDst#X#XPAkm^!)uL-Ge zoQRd#6s?>_E8l2#gE98O0Q><3~mmQtH8%&!+(9FNpF zN}u)EpPTKiSGkzcc`tgFkDZO*BB!-w3NYs}zSvMWs-t#j7G=1RG~Xqod{qEuHa>Mc zdli+$bqk)rFg>HT0vJ^qWyu|l8BYu#l@Y6%DR@wavRm(e;$MT_cClqO3+hZ5)}y zq17Z0E;437t&PH-*e``*CS)eG5z3wzu-y8>x@Ea;3yB?ptui20l}IZ_Kc=GEsmD)N zNz(`Qv-T_xw~|__l2NL%uRc$)9=B+xwjv|StBsP;6$HN-k3fbExaS-vuRcx<|CcQiRF)X8;x#qr*r!DD?Fm! zJljqxJtIrsb+Q>p+LDi|e85;IOU?=Z{JOgOj3Z5*m2p7ktaQ`6HukZkHHjeTy51-Y zc$kwxjx}EDR?JO;Hb34`^FEbtM0lPo@luOhV3kWPI1)d6+;)z2X(sAS!rA1Df+s3PvC4rW@qz=C4%nXYlA9;1O+;h&|I$hmBTI%nLeZpZU7Iu#lkwHI*3Ue( zDPhDHEA}6@DBWkqN$)6KC9_C*0hYIu015#@*J7;|!kd9_2?u&<>@z<$05NvCOj<+C zWq~QAhV}r*jMo{mY;rn|rD;@+jtuQ{ikVt?Dz&a-Wwt!r z4`+8KH`A?5!azQF_7Wus}UJb!4X!6(Zx=J^12x*HI#xRy%;TP}e zM{tO7e^Vti+`-ny+PF=U2r}3)o=o18Rj(ziZ!?ZrHGgI5H(+!f{O2e9)Cq@KJl&EL}ERq zgpX)&hFk1D%0D6kVa-})O0OeTPnA>Gq?HvB#mDtJM$wB|U2cE@7m6rTZEdvK*U3#{ zwrqoB)R_{rhE$v**E7YRkJ9g03C2qAQe#x}KG~?j`hKSY1aef1O*!7ac)5?dIklf= ze2nF4#8^p3aunH0C1Y6*qqjWiC*ayxrH0kypsa9g2WPDD&zfVklxX>_v*@!QZ*Z7+ z<#|h3$iEO^scF{aE_WV%MbHw?J_;#IAnp z>P~`u^?(%IX8(Tn8DTs2EiI#HUVh)Labwp^Z08TgOJ*P; z%Ecw{TZ~2`lB)1Fj=S=Ue)Cz(O>tg>${{Hn6&CpoO-S1M{xb&RYzZ^vn*>=wTbHv_tNrA>pVs|ST)CW zQs!3hB8-o02|iJCW6{$|>pmI_G%aGJF2I`Di|?#HOa~s8tDmr!2ENOrqt43o;FiH_^_0H^_ z-Mld+1V|Ly=*B0l*b+O$##r*6;66%`u$XO`B3EsmtB$ROUl&L{&P9J&mWAt0i6!1e zO-ee-$|##=57OPKetlxyUzotvSdOFY`DlukJv{Jrx%6DHPX6;0%BF2-qj5dB?^7Xm{t4(WE2OGV+;i9))&uJ z=xVFTdC92sG~aBU%cjxP+HsL-k}&C+Y3-AD)t~tvR!b|A4@ybL&~P{p+%8|ElfM17 z8{q20Sm3D|3vKb^=(5$*z3I7#B3P6wO*nW>lPb+n3v_UHXi=AyZ4xZx;-v^rVP~Hr z%C~p(P0HEEvi~qm<}@#>Co-8sIjv11gfi+-zB~3ij|>m7@FgIM*dHH^ZW`t&Hf#{j z4#wT=-lt#&5BGTT2UOUOSaMm@ifpIN&}V5}L%W8SsRf=tC-xqC4LKNi0d@xKUDm+tdV zCiJ8qyL)jc>7(&uwIR+_kaG6P}i0S<))-?q_j*ue&8j;y*k>*HBr0v$KjM{QqvdkwX*cw>j z8uf!s>|KTl#Vje>vPXkL<>^YtrmqU#|GMQ@|7GKx2OmdS+Wv%rqNMnwoOP|$t$>d1e++Y?M_YhRAZ&cJz_&BEe z9kJZ_c}r6E+V)7@XZ*xA!OF_&dwNWr8cB5q7J1#Uucb?@7Z!aNBtnBD!Z3^8KZ9T^ z7yu!$X9s>9HjLCR_NEM=wSFk!tx5>ePF_V`0f^52PQ_qOH3cDuyEa@PZ+1${!1fak zUYV_9ZBz(0fZra@Uzkw{ijGhusJmgY>a#Sv2LDd)<}M|Zjgl<$&9IBB{TQTu`(-N~ znP4VIU#Cg5WGs$2i}=U1Y<#EVS9Rv`M2d^jx{8tIq-DpF^H}zHTU;k<%mRKAUbd({ zhPqWUrvi*WyGg{--)bn#MhE&>UK7xixH=hVl}$DG#P{Z@S5$ILbEo0Zqi+oJ@4w;` zPLm=P-7q{;*)7L?VQjN{|4X_X9}@s*)3%foj+*N*;!rARNS{QSyY=( zWlUeSR-wCiaf~eU_lMJ1@8cr6>T?$61qGSgJ@uA|?OxGSFxR2Li8_CP>tk%@<=@FI z)oM;dHcj;WxyXD*Bm=SNi?PS#IHmb;Y|IK&nH%-LgsDfrxR!^n79@JRm7;@?zvzy* zDJeU$HZFElntEP?t&N4NvU7($C%>eFux`c3r?sg8!yF^x+REY0$g;XKkbzEWOdIMc04rikh6=UBlX5g}3zdyrW&=b~ zay}4_yH%X#T&wPOq=;f%GC)Cu>qQ=GSaQTMVp{Fc;ZG~3URSxT9V*POqMOBCknjde zeo(8rq|kV&anpb;`jIbsz~kqR{~IXPoOFvS z?DK9GHROldZ!MD~+sQWyBV5=945%H|)=-BrmYGKWkpy@y?M2B^d$a4(SL*JH<7LqM zu6hxu1WT+Yc?lqZkc8B?`Fl#fXEJn|i*1%aiQZK(`MS|f!E=xk{l{(Pw=|q3!Q<#8 zrQRcI(qOEy`9@B{b_pW7E2S-cuHJjmtqM*Yb02WR1VH6_nwv!>UjwJw;_6}mqOoSw3&6sianm7vV1K8-WT3tUIE_~*d(x4f3SRF0NCVYN38gW*(B~aF`aHgGnV+sMC;p5rti}$ zrA>_3AAuQK<1tR|KHWppqSaI(Mg*ekvbk5eSuHENehi$KigKhH%Y16OuhSt@M#;KH zfkIm%r0(U6t@R~xt~R~kE~O#*(pU`cPaLJM-p0qrXV|@VSL8T-DN!aU=Mb6do)>Eq zL(lcMbR$B*dtJw3e4M~sWzBj2aB3LC%y(VM$UdbsB)URJ~H|Xj9vlgxT?wDK3 zE{t{FF6G5wOc@z#qOG$8REUFqqkt&rYT5MvVf$W3*~hfGp&%_e!3zt5@!->UUDi0| zVx(8fliL_lB{L|gJZjtEa%3t%%oF*|L~UNY`pO(5=DchxIjaZ#mX3vWS~ZN&Xk0sZ zvCBxlhoR9yWCQHs66@k~kvDzz$Jnp5Uhlq%eI%*va7~+*2x6LLF9_>?s#E>WrIx$9 zQ+s3z|L`VJ*?#@fxp4+qu+3YbZeyC$YfAR(78W=IJoY!opkIf5x_<8M#uju347Cg~F_qhA#NLHuD` zP)SbRf74^KJ^6{-T&_5Jq!)ES()iWtz7ewWbk>dTzn|2gMHz&1AHyZJI*!g+k0s0aR>+zwoPCH!n+H5%F2bn=PPW<#x^vVk*xA{4f-SkIWC6wky1*%j zZ-R>$Iw18jM{9hfll)UO_tnQSep$AxMn6wc^REewBaPdYbqTHZ5Vdw5UJ-?QYnDU} z&+q}0^7spXXI4z6^z$gnhDYwU9Lp9f&z`Ue@BEKgl%2m^p{$#|`||Z&o|xUFqYG+@ z&CDYw0<$74yq|e#n6?(6?OxNt8nDv3JhI*5Jj0d!A{B0|@4x4F%MM+nWr-uDV~7SL z7-D{QZ=5Ifqs8^6bcoq(>F4$QFnG&h;z}4PNpI`r9Ov(9B-{R-J6c{~-E!9WT$xqX zNjJSzzqQXY%Hl9ZBs+aDcX>tL?kCiYDkJf-pi65P-KdZ$vq74!QcdoFef&r}b#Ud;0B9!TCy&4x-9;HH)!pUqS z4Wr#y<#pPScUaff4Y2{EA~OrJlVGDXM6R_&+8hQ=2~?;KAO__4P2znZMh#X!8yHU7 z953ro{Yj9>;ELOR+LI`ywbg4QT0f3>=_r&{y^kK$qH<`#Ah)kqV$}ii6BpSKnTYeO;~Xx1b);78MFAl?GBnHjr!64PsGO@j z)+swJA&wA+Dz71B%Ln{je~_X2mPP1b%qgo%7NO8shK)6?^YP>002fFDMUBXM6Ec!a zIQm-m*aj&AJ9TWFeFT$;rI}qlh%0p~cj2n#V+QEWQILnN`JaW4)niXjTC!!JOJFzgvXbfN&+tn=lI34uWpu(!G9dYxY+5rU{r$gOGi(& z!jVTVw{(f^7rme;ISQ><3;i^b0b5s4jW9S7K;EzcBH4%Cp5nU=RlbyVa#hieeclvw ze7=n6>{MexmR};48?d#aDfv*IvqkxZozIPLx7ro*H3x3(a7 z#N8DeT{BO%zGe2?!Iy-TkunbXx*MjH|HBS7plK|^eMcE(`a6P*m(7;gBV%eDkuYWd zjVDE%)$R2gU7nrnJ4#ELT(d)@JUrCDJ~6$O9{gqu*}n~Ysr4B=sxC^f+1%_c+lcUW zb02xhlgD{7i6fXMx%`U^o%7jF(gAPQ%L&(Iox7CWV)b{fH;7`u0XWR0F`}atMhdAmBMyp}9HWF}q4cl_1w<&2mGN>tF)-k2T}By!_KdyZ!a z!ezF4|6=){6(0DcS$pnG>E3ca<3{oW+*UJl(nKj9rLILk=7vC) zEfz0OXNjX?LSOXBo%;S~PicO+6iGqgrN)}d_y#khXN*WmHC>)ZE?u#&fTHK3QgtVn zcs_?zbtE2(-sZ1VJ6{4oF;?lt_V9N~GO6jk(Vi+*W%EO#5JMMTl|{AJ#Hq|B^Cq`p z|1hB9qyubjeMQ4i%;r{S$HkIWbiJp97Q(2V4V-=3+lvn z*m}1gk*T7*bgckbuKmeJSSdXzC^w%_*uV?&W@IIwzUq!!f;Tgr6rK6aG=Ea{hoZ8t z&1L?o^gBb5FNgw1!Y|5hJ2|s4X5GHrxj9NI)~e}RY&x1j>#UZ_ax&HI*cf)Pzj<p=7JyUk1LSxH`g4tkjwx7p6l&eD!n&sZbU?&Xaovi0B51?nYD zf(5EwPsL)ZIn^Uy9qw9G{u)O5k-TzzRU(PilqU*S6GgCQEp$%HnPo9`C2b@*?6P;Z zl?Z3Q^U|*v=b)i~r*y7jp6aGwB^e|53eeV{VXqA&N=k6VQgZbY-_irKUblj|`L$%1 z+PF!+>*gc<`D{$4*sKgOoRQC)W@*tc$x!9p4K}c-ohKs_zHF*K)TbE1)G!;R^M#87 zZq(Noh1IvxwXF}!O-5t^#c|OLBQTimyeE!~A`!1C&v9PY>91Iy`7Peh1bCY-=hT`- z>$Ox9e{~_-Bw0e*8!KG8^gyxX4VID;%N?Dd^0?-KBR=u&@Xva;JXlzJW2{vq5uFs1!d4rQj@P@UdkR*k#0*z2`I z9fRR-?A=U+tA?~NYEXA{BA!1L@8Fx{z+IvIi>+qRPgI&8)~RFv3*#AmhIH)bI(IxE zCP8aZ8b3{V;6Yh7!s2N%)X3QFh^yCco^Q=#5Z5&D1SlwhD*G{L3p>g$h9^4Xr5R|Y zWTt^u56q(|Mr3_}ntt$Xo{TB9*~3}fW30aqT_o!$jyc7(aUr#!lQj+b$*-1?6bU0O zym2TDJ>}%3!ZYZ&`7aPjg52TVA1c+B^F7S_KFs?KZDn=g1I8qgQ^CHw#rIrbO%j0UjudFMY6&SEBFUoyIyvDiEhpjaOZZhV#yd zdav9m{})+R#Mh#-_QFrP8ycmLFL#Hz>Y;tgdt zFz5e7m-F{+2a|11@f>a!YvrL}Anlu_xt9WZ^LI0Z<5(Jmj}h@HE4AI%tm6uvTR$KC zrsJ*MTj{@o7KNiH>IselkFMGH<6W0tFZ9mS6EUBs7?5t38iEeoZXXsms)o1!xdrDu z?Plm`Y~eKoV$)aF1_GLY@$7Fk($w_ywl(U+S zUI*Qo)Hl~PcYejuj_TFV-QHPQuNo&6A%!A5>=NLzUv9@T&tU+~TAUA2cR&bqjfGVCwnvT3^|-=za~8mC3*&_+z&p z{L@P-Ip25H(I4K4n0Rjx%sDUUd(S-`nVsfXw$kFs+gw84G=O#V&kF^1MdyAGa6SIq z5&KB*ac=v@Py3ACRb4%X@&PcWmt>#?IJPgk66`oLy=s)$k1Xnps%husTJ=In4n4#M z{l1`CKlmf@7^6_<5_6kkqaprQC{zsMX7X*#2hi{HB=>O0kbE%RdDYyomE-=1A#FQF z<4KI~zf1)BT@(7*22pnM_vr*KF;(<%B7t~xc9(V&46k@>zX09poX$+Ye)jCXYh8&S%h+@*_;+V70N8HxB(Dv~q zlXP7Q?|2*ENCKm>Bfmy<7NB=;|LJ5_`8Z393B8#eH6Oes4NW_I;@m3Ye6-&{OqJX$ zU~c?$4|%9Q%_m6?IQi0X>>i3~&*pYB1NWEle%UtZCBJl(?g z-*5J2k@h{71YM@}!~8-|&L7Tn+`HEAYqL1uC;-J`I*UaPS=AwHURt=*o8wevAWV9`sE(TY#F{;deY@Jrh2?uB{So zp+g@|cBT5^0jDcF1@ItyzuF3_rLK1F=$X)`3$wcy`(2t;8nVw@6dP#PfKV6lJJ~Ha z@$ezXzb-$%_q=BeiMf4EnpCeOB8Zj1#8uxXpW0;rD!tT!H>wKN#HK zb0N@qn!j`w*DP=f#Ls#hhxTs&<_ts`v|I_ex+r;Xb$)ao{G!m%ONXrtk)WQp1vr4`|j;scTdN*SIh1m;^8{G}rq^@5L*0VrPUZM6%v{ zUT_EL0ymg6v1XUfXfV+Y)Qhdo5btW&nub;T zKq59)HBo=uYB8xQcI21EqikJJJDbCzZs;RzV5pg^F3YbJiN!jM3>(uj-;O!dFj#r`W0nmz7uI*iW^Ap zX8m@j&B8GA=Vt;Bu-4*RX^c`NXH^7tV2{9i#wi*xJdEkW@s1#^i}TQ19(!B^{n-Pb zt}m%?^dHy2lbgcNWV{wMe1)4U;vwz`J9$6ua~%(SDfgN3dGp9vaz$s_f6;s^qqRZK7B zw!TAO*h2i~7L4ZdFQj)+hW3(-qyKpBaRS+klqxUn#>p+fZZR4X}PAtV!Od_CQi z@DkS$(W6ZZ^&v7F&Uhs*c(LdOk7}F$6E7Mtg>HbD7m1UHw0MuO-THt6c3K|bg9@#T z+rnKJceb^VD!2D@?HGF_{*k)e47J`4u8wAH;zkj{IHsXgQ&2t5B;F+RdvO2us)=v& zJ@_Q(B)(|-k~0`A4mAYd9ZN$jnbOT5w+qiVb&!IKYKu@ZB=_gY{@uIV+)q7`Gd<5A zqX_&roHxhq4BTLqL^E5*m>ciRs=AzMul|lAeke%znjPe+GS`gk)?VIPc?;2_J^izA z|H+U20Ke|v^M$o=tc#g-yVm{*K={uD*1m2#lqgR7G~-;6nzf{@c&5e zq+m&>{GP4hF*f{Y^55C}`Cu~$t@G&5x;^RjY^S!>MpGt8(S1Ga$$7oI{-~onqc!Mm zzGz?K`9k9M*j^&uyZ%0;)o-=ekh_W{`{+x z>^PhCv$l{lSA$Ji#8WEdohGf8aYGM_B}6)3S>X1xh^Oi^2~=<=VDo3$K1Hp`7hobi9KHKj-;B z`ZavF`pJ5IPhR*uv9!r_dr>YCfDY@w9elXFg&|1q6(?CzCCsPu-f3k8@Yid+FH5qJO3EjW7F7v}x}HH!s&h z>t0Ub&Dj^IY%4Tbq7a%SlH>|$I}gVXLZU~z?u7?;FL(4>-Pd)KJ10-5AO=$MU=5?? zV$exyA^kiV6XyGrD`L8$t7FndaepjJ)yPIXnCPNUgkN-dq1RK5`2i89ss z#ba8^04#qPch?Bxiq#D41Rqb&SU+&&MIU;vg;D|=IB_Gax#(sVPJ*!SFKUA`e;eC% znTtL&CR?1}PG*OEe=*rVRIl~b#lXp*KchcEC7vQ*P{WZm06TI8Do?Z*6wu^=K_%D| zt{-NszHoK5Uf6N9>I{NlKD|ryq~qmx*@(amFL(P1QtyYc?#d0k+qfQ?jJf{?mPAho zzx6pr@vZ1T@q_x97u53($%UE3zbmx?qN`JWA>bBAC7$MAS6vXDnN2j@mOhzuV~SQJGrs@92b!Gvq7^gBcTmo;!ef9wCpT6lTx9Mx`D(*})wm~5kEj$lJ`AGVTq96c%*AjWqT|K}XS&^kfozU%W`pOS0R0A{M;`+vi51%D%g^-caCI(_^sXYE=F?3v4 zRd7+@;T>EUFnJgiLR&}4BE4x~V%kGh?PFnrLr?4f&D6IetE-n^DB*|R48p;;XN}3h z>;cU2glH~gzkh%(NcQ<%b~{Siwk|WOyRdDxYPmDyl+Fsv>r;4|RBgL&y)x7TFYEqi zq^BeBn3RiOIjk3Jg+f4rF?<9h6wmdg>dgFK1{)1TNWgIYh}qFA(M*QXaqCPS)B4#Y<-_f(avuJs$-m*62ijCmDd&9@u#JMU#9tXAGRUYndA%?aKJ zCO{#x;bL|pntku_-*mp4s8pMPDjxc(^?c2LlEZC9?319#=vpdo<-?!TH~k}w7%KA% z#Bwi){HB+ABg@tiW0i03-2QJjZFJ7|*xPUvke>TmGQ?w>?l;CN?Y`)=Nc6_9-;=)0E_?tn zvUxLA;B{gap69pb(+#Z;dJ1R|T3&t{7C>ZdKJviK9>_z2*7bs}dSU080%Dm0L7w-> z6-OSN7p?}O*~vZUN)mLBTwW-z)36YdX=A>OKzQU@b!VSx?&&pALUSX|WLAgrFCCtX4fhrvnz9As3fB zeu8lFWauuD`ql>iW5dI3|K{qW??153&8B z&^58Q9i5#<3H++eFW{@e)o23A2`a`fL1jsLukyjU)Q;4;ckfqraCCOaKU^diVd&e3yVUFplS$niO7Z8{ZlE)h+ZBchy$09wMwobZ zNnz-l&Hg*5rzdI+=;e%9=rBA~=mGs{4RkHzlJ-!{_Ez8hgI*Fb)L|x_nU(%8_)e6hpR_7 zhxVMG=G!;DG%p^$5@~GP7lm@WKTO>(^?aJ)JN@w6c`>#9q(h?UA=}*(dgc0sFZe$F z**WuffgVYqbExwkEGe(ed%o@HW=FwdpxfffR)Z})TX|r!VcnRWn zT8GSQXZGHF+VTSGL@?L}|t zLQh%yO({!W(WkJ=>8Wvd4Ui?yQq)mycns9|ui4Nx??)yHT?x9a_9b46-XaI>abNF= zWQ!%Zho0K4UtdTB;M+?)O5AL>Z)h-!_WM3J`y)vEhB;|InqC-(Vdnb)L=sGt6Es~m zeS@!$Yuq|g$(iWLlEj`e-uAa%FGFCc0~@D}58ao2*8@Qz@%Q=ufajpgR;oOe{LWaY z#$8o!-_pPsW>~YjXn2EZFm>JqlgU6HMDRRA!4rD5@;C#nhXu`fX~p?Jh0S}s3h&!M5bt)JMqju^r$4X6 z&D_zF>Zmc$qps_*?#RvZsOdqB_yDr`U{T|;8c226v<&g9*@GoM`*8Q)mE$8$oZUw{ z!U)JA?Pl$tAVMw^EM!SSr?&NwwnV_?K0NR^_~z7vb6X65Wg_YQG?cqPm}K*QM88DN6MqK3J2u$t)Ti87a(CW?4E&8eRSY(CrwCko^cXL* z*gc`WvtZ}LO$2k7swxtY59TD|2)H59-%M9*c$0q%r>G3$<|;}u`+54W{n0Idx@I1T zaVBY^BqOYEAwLwDoc7uVcO$Trz}9HQmS^PNLlUut{d}zUupMbJ-u--{VGz`R{xAFD z$mDd;J@l42#QrKc=wxB(;++ES67T~nFxwRP;hN^8;C#ArAul$cAd8}g5QX|10m0gh zdIOqs@AY@vlO1(`uy+#8c_Hob{;zwE4-OsoU*L8vmn)ci1^ObP7Isgy?N1to{=Wro zA0*5sBzlfM_do|>h`r>V-L3J}TO9mgFud9S2{mkKb333-pV~+r=QQD8oxt;wPL|(( zcl|qwqUW^si^`CbU8JR|R5tp~n=Q zbh_&0uTxNt#PqS^a_B+kTt=pXFVWoM=jse;EU7}fzb#jk(kU=>P(7Xl^5!hJ#$Fd? z{dSd!Li_#6a43TC#ny%XEb2KX$`3uCzdl-B%J*jE1VJsDg0*-z&c&Y2$~4TE?nQm- zw@$Jju-4hnG(zv1M0!!E{sz*rgg_G#^RN3<3|&ZWe+AA!U?7FPxQ2D(&23okO|d;< z8`kr6CiKEMq22VlE_8RP@ZwG3<(K}hot`~-%Xva}?U9&ym*@x5qR|oFB>^Py%T_on z+5<-;aC`FhQNo{k$^330GIw-9{dTotL$>qa9J8$O#GP7b;lM=WsiEEFwARneJ!Bdp z$xrru3MKSffz#LzB4j%GH&?@a4E!!ADzDA`D5?Lh6WVc>zJzqP>>c_g^yYa*(kZ1d;5H#(b1;5RQ z3&8>l12QuXtjpWZ{&Myu(HQsWT(9a=a$K8t2GwNXR@>gQT_@1o(`YLb>oHIz{#l+= zb`3^-2|I$qx$s^)%=>3#eLoVc&XxFC7_?w@AY54;aTInWT=r#oRd}w*YD@>ehyf6)i3;?(Qzd-7UeTxVyU+Em9~@+$~Tj zPyz%kTHFcl?(XvEz4yM~{A(sNnM}@^WUqaeJnLC&>l%&LA+N<$tmL!2K2=%Oa=ZpD z{mO9N9Z=tF)rr(*Z~x?5LCv82?T&1#)TYSuj8%1%&Eoa+bP=)3?=CR6GvALd-g(&l zS^kaaexUgPvQs?ZKK30w#^z+IQ6w#KtE0D8%!4Pt^;x{xc8ikF3EB15CU~$s$${8o zt>Jxe_Xavg*IF>X&+BDd{Q+Z#&)@d9fzI)kJXzC|qMcB@`?2;t7u`(L&WenrkbPQ{ zvt=o#CAeqk$(;`GIKgOvQ)lV&`t>N>YPZHxa*wa9r>l%vv)ehJ@^JFd>pO5 zC1!8rU8z$&civsRrYGx)+~Q;z8ZbB&h<^U;JerzNY7QK=cXW z0L-{u3+2F{pu>*|s%)M&j{Rxu<8Q}rs^i3h!+(;e`rM4L;SV6qTAPB-t6qA7v4yzB z$?0>SQ2GX1hSRS)T`oKPj$eFtPB!Z9z%b-FD8PHjf)@nZ#JYE7LuO+8*3DX4Bw-;< z_9~IQSAPDwgOrntrLd<&bkIDn<~B4V3&91>GN&iksOFkD&C6d5t@c=)IrRi6KiwYx z7|7Pd58G0R!jt}476Cw#?&%R!0D&wpFjY@94Hjh%wUSMb=n0U9M>Zf2(?pTfu8vD2 zX}?oG zN^j5qN9Ku;ax97~(7;DuTG*wg&mRISq$u6Y;*g9U1YM`tkdD6!ocLnHLvKF2kpHhd zktZH)LfF5%{s=AlK5DHSyxuss@Cf2~F0pqL0%I>y(|CV_+vzhLCsl?>vneGKRJ0 z2Zz2Zr~A_#Z2XVZssAp#YC?pE1A*){2+}qRC2=qQ2Id$Yd=V*7w0cC$DPpY1iVF)X zt1OvjVnl&__IvxnEp(h#7X3dmAQo|YRSaV8iKWuYlWgs{SQh(3M|m z8>>-36;D-r(i0WM2zt{U{a>A=mZT_J3ZsLfitJ>Hfs7DI;Y>*g|0zDYU}+l!pAoGh zONtR+0wvaIfiW&+%_?j!{ObR-a_35htU8S?MM+np-LtLriFBzKT&+1gS|-`W6c>J^ zc}1)6$k%O?j0|}D1}U;s@5Prh^tYp2DU)c zmuTD{G0c|er`(hs)<_5b-dtz@cVS~Phbg~G%p&NeC)6D7OBFmw3sxXTnDMJ;gyO}) z*C?}R_joxzcf3otGT(JaiEKij?fD%V1h$zEt|Y7k~$6XJ9Edd#PQCSSwOELYm@ zFl1IaATSd9Ap{AIrBsIc`&T;`-QDso5do+5Mgg5V*Vo{H_88^z>7QV}-NrDspcyD% zvO@pC>ar>j_#sXsSt0q$zHp(&zXmmeF0fNnbgCtfepYt&F#DmGafUB7j4xtYuMht^ z^sy7b{B_5%M`!T+E#TuRtdr)uf@Q|uYaT`la4QgBS)L$T3ne!$%H+TK90_JAG}|K08H?U+(aj|HuXFHkRZ_+Gfo zHL4??z>(a^@#QE%>q9$k=@7aJSG>wR4!mmRg8j2D+-M-Js=D}-I(dNOLo->}8pV2v zPwrSSI@Yq)thMm~v3aA{AKs=-LH?Sf0!FmBBFacDVzTBbwrXA0-NKT_(htB{y_-iR zLbm0QT0$34jV4J#BCi0|{>c#)Hp&+v`U5}~2*ixB^6t{+g%FDtGrFg>&qFYA^xTzn zcx3Ym2~`%PL0~n`7@-oSR~_ZZFVCDtttS^li;HS+Z?6IP>L?8B(Xzsmatu6Xp~iB@DuS~&5@llqYo<)5pWtjvrH3A|-zi`B=_5cal- ztyyq*lx;uh6dq6#lz4JA2>JU%CW5q=~Ww15Zd4devLyCiQM*u z{M%S8LuZDkFyHPS8FzDf0yg{-SSgQ&N!~BTh-et>I!g4rx)W#4v~RRsuHcn8{DuMn zF!I-Bvlf*K)hzyN>R5$5c~GcDqF(^jA0;dL6w+5>WM15ct z+Eh^U8)sU=mpt&ydV2MwcnjXOTeKcoZ}S*0hCm=io2mjBfnpRjN8ttAnafI)3z#*B z8lIRBLBWXTP1tT=C$8qw49KIkXAfnXQi@W4tenFw%9eE|{f6F$LXDqe3As!7u8CX8 zgO)L~bLLBgs63iN2!=mXMg}a0IM|Z=N|D?x?IeSHbT~~-%YNRk69$I8!|CaAGlD%> zf@+x1w36wAsrt0%C@zvt4jEcpDNTS1&%k;*T$W*(O%&C4?v{`Iigi*fft9s~mkfwA^W_Nfq3DpBco1k?CH3Hk3*E)sM0m}S z0u#*A(?-4jf`#K+W(N<09%FT6KM}`i8@JzNRs1cKJUl$Yky;mIPX`K}1=j^N*C?Bs zuKf#@OMKDSHOzQhW=Bb~T;PZ4j@QG}>uzdlN-9ViA+FwwE|<@Nf6y`|A=mg1ufUg& z?_*`m7l*D{?mA?$IeO0}u-*c_gwBM_#M8;Svu$aWs>@)Tnx1rN_eNlKog+znJmd5p zJ|icHfZ&7+WYyk8Bbny?J|#O1Fw!L(xcW|fcSnZj%Ad0NZ=OtlI4z`+a{WD5^l7R8t?0*% ztpV?UN}-PkCUBXQ4Lf%j)$KX!IU%YwJYJ-m7gQrTEsX-KP-R-J(dCw_OA)P-_@kk2 zeCt(Z8+}47@ka?+q#SHCm~E5B6vEFRPpUcChiKkc5)Dms*R!z>_tvvTMMwKRq!B4k zgVIV`TjRIX1@qVt5Js{Eu=34Zk4~E0Pk_)LpY>s0)X=3fZEj9ycPv-gG=!tUW_+VI zBA{6dSe6bMMBrex< zr#)oz8f74mfP~+fk`xohvHAF&f$sk0H6^H$R#tLXDPs|`XpZ!$k_G8WE6_>TcU=xk zj!(6;xY(lG0UqvcpW|oxWuP^XWBk|t?$3Vj*UL+HHPK)k2G*5)Jtwjajby#*L_H@A zV*y)7`?50nv!IuY+RkAhQD9!VPVG*9?X~Mjn5wVu@j(UXeVkm^8N)W#mlj-Apr#iE z9F2s-%MAOci6I8HJ~q#5wZGU$QE*dq*`u7RT&8J1rM!-xg_|~Km}KE}CtPr2rQk;e zQdQotxTIW=FRZx^LQ|0 zlQfd74c9(|l#oi&d{Vxu!;SBukWp3O{|N?wdm`gfP^qiKE!5A7ghcTi(Wofo+tn z?RJqFQ?Q`>2$`;wiLrA$N#inGr2oqGK2Xe4S{{N6^-@~Z8NBvPk-g9{T>DmbG!KrY z#;?!Bkd8n=n#?5al&oUTI;C01+RX0f(~`w79ssjNzUw*HB&o7;bw$6qp>dc3V_;6r z&xdXaDnRLS#~gPWa{)lcIS;0TqqA}JhfTTsDfagjRaHw~@XmmhxLLrKj%wieBnhO< z!S!M$j-5CNPRFaJ=$GPNWGV8*^0Ex@4_f|OQW2wG8IU*-3Wd6LPa<7;kJx2PPEb&OA1Xwa;+=t7Fmi@iBXs^`huc#k(VXv#`5{;n z(c9ei7CZR9cy!sqy8Q0@v-nT z+nP;1{Q}tO(LaD|^tmRbqXY5o`P#-0Ni0m@qGvBhm6MWrk!xGjH5|a4P-f2<*FDV9 zITAhg$a(jCT>iY3pOhgMu=|N(yQ%Z(gVzTyy>wOPH1=O>RkY=uZ{jUh3v4hISdZsP ztE&rm?2bvI{Dm3IIP7rnt@rMDKCDokJMxn&qS0aQx1R?G)Y!wgPn1-)c6dIwWh>(s zHnsQ{*DFa-{86ztU!qfkRY3+Mik?@shufnfE2_vAG2F}`VgvQ?YlMX%1}0|muvLuC zEN8BnmsBC=;07&U-AAw!9%l3>Vp8ht(apOj#qw!H_^{`(X%#{sP@y!1mrtiAf@2Yn zsj#D_=8O18n(cnHj!KUENqE+?1c1-};sLHJN86mL40;{=YG3PGN9ZEN00aV|zK@_g z^QKRgDnnY|oc>^M!AIJ#P5FA81l3#oBhFD{fIxbB^GY7@S+X-f3&g29iz6i_?zMr< z*ZAQN?;K7%qAjR4Z|W%{2|>V~b_c?*Kt$E$cI7bBA1|Sq$po;e(zL(O{cZ}1RL0P) zl%Gauo`Ns${QYfEZiw|Ceht|Gktlq|Vw~@KR8&+y3L|j#Bdf0rSXNb)&G~OtK}Fh< z&^{~@(oiVpu?58yRU9|D;&?UQ7zJ*WZo4l`*`yAd8A0hXhRqiIu#AE)tgMiXI6rPL zR@LszEji0l{}gv27ZqI@$ri`zIfqNpZ?K-4ot0HqW^rk|cuykW{GV^KwTigeh>}We zi-=5*OinN5nnn{WKqTq3drGDTpPx2B&)0XnUMUd~2=@q*0ALUAm5DRdGxTIBv4)X3 z4y3gs&=A?umY5(3;8hk4e)(xQ)b!pf61Ikw^)~vODj?*`R zs0sa*1p#_+Mf5O;~%$W#31V6BAm5rRKY@9m=AQyw$0M{ zDaTerr`4Zp4*G|0FWHrbk^7~}I5Gt#F(<+4VG=`pYE{C2-;5gp3%go0R$|r+g)YRkg4rF)Y-RIRR9u%?-py``Uba=%DZY#ElPkwKrZ~UY?zvP9ItHyTylR z6lNP=ACEkpk70VN$<6xdz`Z7-tUDzzq0FiiU&M%k>AY}QTxK=3ybN1p%Dj)%>sYGU z(;!G$de|#DuW`@b)mAfMmVJS}ft~z?%<89MZq3L75GX1yPgO5HQ{2@r3ug0*o0^g! zkHU^i{byJOAmX5x7XWkypFeSXI#;dS&e67d|3&%62;~r+gzoYUO-zu>TX@#X7*tg? zutH#5iA}Tf9vRoW^)~|zf z%SdwD55CJ{yi9nXffPfN3>EtW5{?4=`^awL!ippfPy437X+V6q&U_X2gsu4pJRCG_ zO{Gkv4T4N5HkDB{L@j(d`xMPw`_=nJ(nOORie7;Q z&sS6C6ix6+x1jlBjC96vmj}=r4TuvC5SC@n=mE1XE-ikH!*ZJlLpBrPPq*3G*L9VzkOIWFFYDl^^(zUSlf60AwEFq{DlDA420%*?1}f1mcsU0nQ#fPgRq zg~C9l@3xVJg;e2xDbww!OD$c8u@e$LY`s6Li44UMr~;OiV(e46f!qIfcxF zRoOGL>#=F9kd~c4-j@7(p0j_SA}xcU>gipM-r6dwn4ET5x4-iPR~BW?=SCY3RP5u5 zeloh@1}*aUJ+_O)NXW8HRuGh6JeF6;c#N`##}Sv~3^i9NMrOCM9?Yb#*(x~fqxqBb z{Kz!0(4W|$q*lmXAFRl9zt+nro>S4UIZhA$LKWAFNp(f$QBj!LDGE-PPHHAC)UhUU z2{xXYEABtJ>2li9ua+pcY{fhPz!rN2(gUr6;eJu3N|_YVM4P(=(w-_aVZbSbJqTvh zDFeCsm!*f$fysS^To|fY!p+2ez*`9*mL5O5#*6z2R>jCF)7D*+F?A7`gk{P-l&PQS z*Rix=M$27Ll2u1sEw~i}Yhcil2N7OUg(ceTo(1A(ZFBMT64_%0#=y|fHC3nnUH}HC z`v%5HQ2vv6dsnCTA*&4dyjpzppog`5kD$q940c?QD*LVJz%2FcM|RN~Sx+9mkfkKT z+r15z*WZQez+WU!mgV>|ZLoR9y{@nMTY_!P?li&eiK{YL@mS~loW93oh%dxZW!Px@ zz4lU(@RA@9^*%%gty_tS_J8_ibT#NuMyuysm!|^+(v;GYVopOlh0fAE$#@%+#lf=7nca0{=Ch5q zS&8F&EIAU~K~a*^o`)n^2PY@=xC!PT-!C}ENpKEHtnE7auS*p&A|SL!_TbciLib#2 zE_5l2u%!*(n!moiH75x7#Om8B(X#8_;0)`UInH8pj=X#rN{Wh?8gnzYKLW+d6=@Ti zmmGgLZ#A1wrIsiA9KZHvsmf>$|7qG270W8Tdf*6zjp;!q^JSzEd|6iXBQP4EBUexUsK)u*Dm3xK z(ZOuBK)%`-aarF>0fQOGjr)$zy+PrgXm^mw!n#p4` zwUD{yw79Sk`(t8twZE)J&3ZKNs|?|0ud(jrZ=7NzBj#Ll*I~*9NBT2L4OYh`YJALy z9}gbfsw4yHmQ&fNQQ^cnl{;c|@k2`JLt^OkF7YBnBa76T%+!?d|Q1ASr6G-m;q`Lf_y~TglHr;a&xyv(wZ67^Erb-QT{N=tpxMLnEMK z-;GRKxHW^-t3<#3D6Yen%e*FrJimmq=jSutN20niA2JY(s}a1JIb9-p#LKm{8T|Ft{E!R;!jo~k^1QH`r;nn5 zV2?fVDYLG_+1e>_PC+58ob3EDwO+i^E8JFoudDA^`NN{(PfTQFBue?BSKqKMVKkBS z9!wEZSo)}7+@!}EFsq6Zkvy=(AwP^4LHrIir#asuDr-LyqQL1LW_N_t*dKzS;7zx> zIXACBpV>XOYisMs8u?);U-s$JW4z&QGlJnd%L$8ZbaV-S>u9dFysob9w}Xg_HbA!T z>@K5i-l8w9+IEE$`g#&&rY?8Ymz3KbQ2We3Il~NEZuxxMJc!PcxBXlCaNflkLzbZW zbbds8ymsSj+EL}y?w3X8Y#x%IRX*oC9IL%B7EKZKDd70x9^*d+8vs&axB-d=JHEH# z?-SJM<|z9w`tCd%Lk^!@>8j{eAT$1Q=kw^x4_Qw)#z=*mGe# zJ;yp}v<$T*KP)Kth1wI-td*i#uF#A3K-Q-Q^O^`)ViL;A=seaVUwZm67Z(=~^wuN? zqA>U-*1p_M-!@pV2=ft=GvH zA1DR4eDE7@FM~~!Wt2hqT^?BO1uN}=jkDrBOA}~}9hX=U<$?VPvw%#Aj$6GR5&t`; zz6$E%cDLn+_N`)O)P}pJCD)kLeF#$fwL{;*3yY9$t7p3pHYX(!NY$c5KCyjQoUHNhaoxQ?cA3D&i>7X$sp_o3P;*YNsaw=|y~TZB^L2{WZE4$eH- z7Nunx1Nm{DZs?LKk)Hj>3T&|@Q~35)h|9rGWW7A&uc=#!;`|)AJK5gJiv2N=NgL9{ zo30(CwK#%W_fvWHOi#$=Ds=|zx#IlTZFB#VCjc|u%Hw*wk)Kye&jMzTb?Msa&RK+eF*3G^B|L12D@vIIv{%JDL0XZgZaR?h--*Ajmp9Q3gGU!(|z?=K|*G{9+MUSRUtH%ooO1xG^Q^l!3qY$6qg^*f6t zeo#?L%m6APJdH?`cUb6ZCN@plv5Mg>yMp@7HE#diC0Txj-O)sWFQr zX+moxg2Hgn?w%StmHVZ)BQdlKjxh^fZ8cz1m_5kHKj4(E zyO7y>G)v?_4VJy(^HH?CCN6b?@t`6!@ue&rFy}0#ocPl!y2CS65ysXjH;auq-WUKesB#qK-*@Yb^3(rHr8_FinMC z`b*B0eL0P4s-1;A#pie$q8;_=f7T6_^+K#X@-T}&vh#0tWUqd>c3Wiaflw?Ylqf|L z0NfkFYRgv-entzvPHoNPbGZExnS62n(;O)pAHIoKK(Oco05*?HCXHBdhs4XDI)xy*}Y6+po6gA!X9QiOt+Y-&MUAVOU9R9!Xm06GAD7d4Md0 zJLGZN#rJ+AM2)$jXM@ou$4yOf`NXk2OR3b=m`HW{e&j_A~*iNBCRi|0KJp0Z#ymNwrf@o6*wZ!mWWQxl_u?;i(>8MWka(-J` zjJgjD4ipP147`enF~=x6xV8rXbsJi$vK4?o7WJw)eV)RA-_aD^NTz7&4i@X)rZPug zstb7l@dM$0c(Ow2c^o2=KuGx5A2h)wI40PnGHO61{cjbdfwZO1_O{&G6(?_Y`0U7tjD1PxQ z{fCDEqiXzq+wAkKHddzo-sMfo3#8N0jjmm<%eB8~{e?|aY|8RVj)BNvEGL!^iyP7p z53}5$`k0Oj^)L-Qn5f|MqgL)iqP7nA!3hrgG==(yhn#_8#3Y9;Z?EFhErk*C)gI-P|4u14su&3b9?X-zD7qQn(Y`)_WO?X(GG8S9vr*#%6$6RtI*t z9&3LvIuV!4>9#piWtN;i3Lpr!#q1HBbxn#MrjBYRSA?b*$T554vdu;R@2CjiiEYA!?$qE!5j@?C z_WnN%j~azUG$A@fhCE+tj?Qb`B=OgeXRwlO+YX!ji4Fo5R?-Pw_Hcq@^$%Psx|%=V zwGgN@dS@Qf7*MuZT+s_r`w=_vi#X}_0G}nJ%qHe^GIMRxIAJCGf+K&~ayNPhSLwou zAGuTzSY=MGGQ#MO?c|>lv&mOvTngf4i>u!$2O$k#vN1KqXNw$}d(ZMTI*Ortm7utq zJ#}s-r~M%x;?fT`edAy-*!?nKwP9(uGkU;#_DxD8t%lW+K2;DbLyT+0wc}-&{o4&5 zd_>t-p_%bcHim0jEgnqRof3zdt;}iIr--=_6bYMH8xeJ4zi4kS?+d20zIQ7@>Q)L|Z zY3{4Ko)Q^N0Dhkt7AoNEf9X{lnwqS`^x2IHho4xLQ^pKt`1se+?==7)r1Sfk06<_J z8OeaBs}nL3Qsu6?MRM5)1;zhexKWqH^^rmj^uFfYY|+lMr%N*k@#Xz@S8Nu+MylW; ziqg`GpNVN}W{AybdOEL&?;_6$?*jghwwBr(J#FczV33kyRct2)5S5rOr&{^wJ(eQ| z$B=xFPm#{+rYWgF$`Eg1(1-Q^{-B4YQ-&||a6!vg%Q;%?I8H~U+kB{6{J817Jf|vr zjgPiKhs3*KuqH3klIH~Q0|2=s%1}_rVW+Cr_y4iU#yNkeeXl3rZV7(=%UQt1rc=K=yF+)tE#zFn))w)X?+@MG@ibJ zFQh98{eZ8^kU6*x2~QAxaXdaQy(mD^&WfsU#hzNgNIXhUB+$}uE!B>5D)P<#_`iI( z&$p7K@ygmVgh@ALK=8aRl3GDEhYKaovsF5Y~>x*KLh^C99ibv+^Ii5 zyb2Ym>ey0YtV0E;tR|uq4rAOqs^q-B%k%Sj=!eI*yuaO8vjLwrV45^r;Gcp!X#NNZ zqXv{XQIVzknuq4_HNrc0H)t3O$a8Z=+U;mW8cYN}TxnP#(LAts?64-UXVJIRm^@~P z52QC9oIvITec|fpBl4nee~seDy9gbr#w~619fio=7oS<2hCTG0dT=}^0Pn6((hrsi zK1R3YA~DeU?XZj|Brb7)~W=MehgNQC=?_O@cf9FFcTDio0`KD6SDU3Zy zn1$fuf#ZhVty=VgX2OG6GSBC0KUVp~iwgV@4u9>)+N@7|ZC?*tW|LKUu6xlPpNIR~ ztKduVO5(^A%#@Z6J{9D+6dDCHf2X%LX^T{dkUVV3K%wx{8;mE?b4NKj%Szw?ZP89+ zh~Em5kSCmZ3d?6?-}Ix^ZwN(_V5EfjCpW$+P=2#F7}u8?Z6mhi@0*|*pLnpvQo4a7 zy{~M+z+&8Qucfg$Nt$a-Nn11F0@LL9(3&;HXF!vh>rx&32WFZkLtKu6$pgeB^TS01 zRSpxJbD)rg%d$t^>a9Yo&J4fk$N^u=G*=pr8qp}%Us9I~1l2D$4)3f)SFD_p2+JNu zXkt%HqvNE(#o5r#JJ>-W{CT1<4&{9NZ#I$vw@ELu&b0!F@Q_3Z2SPg+?ym%ZY#G-OByZ7qEdmk94p2qn#uQ78z+wlK ztupAlDG&4#r45cR#;4;}`W!&+P+*3@a06!-2m zyBBs_(MOHNyn`=WkB<84K0-@)B5#Pqy9d{=8%!w?DP1|AN{@yXcwqi_1wBln0zOPe z8^CMK@Lh%b$IwOpqw1d~UbXztDo|okrEvR7ww-;2{4{W`T0h}vD22$`enr_2p=#D1 zK+zf_F=8tGBALAxO_WLty{1lb2Vd5_<86Gxu@41%z${8z2=*;CoK5>H#u3GkI)V~Q zOVC#ndT|os563r2({JWP)iKkT>33;0OZ80hJ>RVDvBtUD{CQr~F?CsUy$7ZpgZ=T| z^|?6Z91NJ;3BGW6{jEYZNDAhdm6zQQV10X?0GSZ0J6WI4j`HTu#nqs>f0g_?2l+|7 zhFx2&;^afz z|68kRUWU;214T&wd~)p>i@Y_`e^&|_893?Yh)hMbem8BgaE(!pf?3KLsNE`4ULES8 zf^Iq?0mPrHG3?=z=b*}PG9S&tTxK#FD2ZIWin_Xao`D`WV0Qg}+P~kx(-ZpYr%M_= z0X`$;XnjJOd$G2(?;#^ztzu5jPIL+Qkce35oU6WbslClXl5r|>M$=L7_5Aq#p}Kff z*_O`L5Zkz#SZ-)G=fI~GM-jHIq$s%xkpT8e@wYTGH{7%Rm(RB)-?=SKjC-PVp~)SO zyaqO8DBn<;VTYk?EvDsG<1hUY4L5GaoayPYI1E(5m4_(kt_x!xcoOP%d(^h6*!!Xk zIOdDN!8kfxs__LJ3L!4yFlNv~gSEKaSI+mp8U_J29lC)m*!AoD1r2Y?>jn*iiR+ROkksp_zP5AZuJOi_CzvsoM ziG-(^pmh{rp!Z=x;LD`omBJxrFfrFz0oPe$jyGlI?2F~xO|p}~+5y-xEf2!qgT)$yyzEH8`gz?)j@TWH$&$ywIjDF{=*Mht$-AaDx z$)!)jc~+`&t;@qJ4Mw$!*4u08h|n1$F;*>|z?U4v-BiBFH)~4?89%E!eQ^iKX zw?Su2DF_qpw_E^Zkt+_uBE@0XZ@bg0-N)!_O7n_5=j8)syf22q=N}^+R1C&~Nk-#8 zynlUW6kXzaF@7nOwS0Ts_O5lyI)3@=9TMeFK&&PfzOYB}l|!tnj6xLX@3Iv^QeY2v z#i1X*($x63(Zo>sMp4;Th*|0~lW5;4e`PVUqY{+XAZi$V%^Adjr4=xwIU;6*Iy>s# zdYt*6!1$}h0<4xQu`bA8xy_k)qCxhHS_>#$LC;@$N96JdYkfsyR9^Kr_x|$b-SCLn zj{6^hrr)+3j`&Cz`G33CvCDIVnN49>eV0hAnTtearmR=CBD+~p)0p+{(_YH`K~Qx7 zQ=?6Z_)LFTzDN#K>k$sE{&gIq0Z36xA{eBN=h?Ye+m zS)|dSVt7be7AUENf0>O6gJL5hqICozJQq+|bI2oHu=8x2?ms3O5-Ib)+l*15Ao z$~ddq{glp3S78-o!I}>>@!|0nnYLL{pEC=_OcM-Hwp*V&o|K_5u2U`Gza1sS?k#mk z3*>&=IMjudpNJd>BvFt6xf?QZztwlvg?I!v*JWAXR(Vkc2kJRJgm?=J?g2(r|Mcid zAi|Z2vKn5aEWrO}TbKeFvV8FKD5OO0pYZZe&rf~wx|WjW^B?zT^1d2)qs{)QR~YF2 z+wbM5AvuYkGKdlM5`kyjA&v3tk$|G}np({NU?=c;>d0?Bp{^B@vn=;|2N@Q8tB1WH zh6~9aN@pug$LKj%8(6N-u?%MuKIsItR;Rk#Unzpzs{+*euF`1gPF;)w`ucKw76@`e z2Gf@70;iqzCzHf4EZHH?O6(oS++!`9JfHvYQ&8UBP%QV#W|+3DJm@h6KTo&%Jbr?G z$$jjpmc;K553ugZ*z+Mx`*ma~8!D2To;x^xP#rJw_<&_}1)W+Ou6;dcudNlCT4mAC zC_54wkiR@%X>!}3({7%WR)AB++JFlz)DU1eh^nGonfD*Q49dum^Dl2Qu zQ8f{Gnh$s1EYuqRx(*=ZxQ%kFz1}Dw1ijv7&p*$R+)q|s`EL0@FET|;wolc`-gkvt ztc~lAb><}n?q8EVj=BG6rI4_nc2D=p>D}M*EjxS|avQ!e-OC+5-6*-`oKmebZ){lN zZ#xS)%6@mKM%x}h5Q)@{6|x$Jc(n&UGj@BR4c(ex2@&*Y9QvHk8a zZn^fpU3>6$_hzib%I3;LePh0(b>5O(9WVRA>}@GjTt!(JT;6^b2jL}iG$^!`+)GsN%JSmqXt_O@zIUG$&XwwA=6~~h+f%>ucpb2T z=R8`WC_Fngedia}a30eqa+ABm=p%kmrgyvW)O@gHx>cmz$-gtMn@FThND;FGB}1d@ z4MX>Si_&hoXC3L)U$Xi07RX@wIIUzvVC;`zLuz1192<0Ty!CK%m3w_n>-!{Y zx;f-C_O45*b{EVMoC}R&C1vQ<&wu^QFrH9e)p z<3pP4Y_O)gs^zxl57bl%hYuMZ!?VZ;09J7yAGNoAj8osDjH+#cOt({l>y^uB#o2Lp ztJa2-cB6+hWo7SkA?N22=mE9TaJbLq+0GiV$IF&akXQ84!UaR#NNjY|W&IQXA~)8w z@fFS~Vr*D#lLV`l zDwTM5#_%<1+5v$yWOL9W&*pkfM0;;|Ap?~R!K$Od$V43grVzQ{BsXgKTB1G7&~Yua zsliKJxw4)RnCU zWA>C=R4{+I;j#x+O?Z;c3N(8Et`0?ygblI`tQLTNXUtN1#ZVV z6btXcG#z?U6C^c0Ud`Qr40Ng&cs~)FpA?q6?FEQMv3IGo!KTzdq1im&rcXU_9KUIH z+)m0(Wm9awWULIOowXr^K8Zj15s$qI=L_vD{XXq-%x@3N-sE(uk_B{G}6kP81J*J4Ve9D*C)c zxHILxC7N_T3OgtxTb*u|kK46K`$UDz~( z{pFbAzQ;#Qu+nC2LAXxz#=ni5IU~QbV}sCsyfq>_$+_%la7pN?@T7_(wNc-&bb6Gc zK{rS2<$5;X@-;`tzN!ZxA0$I#1|LTGUEyO7=Q(l^qNl|pqR~GJb3N5fJ@y)>4Q6;M z2@oai*EeQm&=Z%Kmu`CYng7#V?9KS@uxUF^iGJM~YqrqVGRK0SxM}b!cCer3mGecQ zOZz2Zu=iB_=Zj_K&ksknmq#H+UE|K5-I|UOIbd!Ak-cM{)Vb}%V#zDvlj+|Km(I-7 zl8AT5o&!JcIE0GeLceUa{^p@sooF>l(!Tmd!bFZkjvpH*8j*Qi47J}%JPWaEoo?ZI zE)(ff#~K$m?ZF{Re%$QqTEG)~0+j5O2x)e-9gF1n_ENEmo-%@N>kbHKq5VjFA$tL1 z(Jkgb25fDP_GGL?2u^|w?H>C2X~o4LNTH9?;|S#QHAnRRw{sd62jvd8i6@3x9J^;& zCPo+TkG%o6EGiVAc=xq+_k89$RAv&vX;8fMlM2X>=S{jUWQLn#5km%Wxk-{P>hxgF!zu_q zHCM}R{dxB~;MR8Zrz&(syX)jz^zK!Dd#X>+&On=sBnDLRJn`-upNg1fbp+a_svBzO zWrB-FEfYb=`vdFyzJv_7r4^R@Q>$o4U16X1iVtv8;JhH_Dfd2TNVfxr*l=pnOBnj8 zU%2?17uyr@+2a%$DZ2$hWj<^N1OD8(J0WR4_?MxSUTY5xa_j~h&J0+%rKZ}0$v`0I zoLlzDuF~H-&d5_-nz?JAp13D{(%Fj1ev=ZIF&y^Z&KyCUwim#c+GM%dbw`eK;Hegv zJ43!SlZg{n5WoPa%1^`2ewGwwht$wS3YYRLW>z4;dQeZ^8hlnaGyzT&9p#S7SnX9Y zu(mmB>JENZjxVxsuoKJtfhEMeZ(kAr%LRywBxIVB1Zg3%nCs49p?e1r$Y?TYl}Mvd zdHIwFg*f7(SlS2}Qiip(yAN8|?|t4A8u!~B$;`Y;bwUXb1Np-a63Jdkbo8NKqG{U8 zt|2ww3`JcQ^k){(5q;55P8?;fd%g;Rn{RZ69g5;a&$sG-!nsmg-+UZv-tSy)>-A98G2LBn z`|C|s0!QyC_Y=K5!r5!D=wek&TYpg|^MRl18|E)8^(`|P{t$^FPRc&v6c66p!gua6 z!cG}g3OWJx)%*6~yi0tp|1p1f_x`3`0(^hf_$E_O&u3gLxkc!CxQgWS7!~uUw#_WQ zN@~_ui2CA_{hFLbn>auu@vAt+r!`x=iX@?&<{5zoMCoMG#b$ks32 z$t^F@1s%`{x-04Qvl_X%#95r!2Z;x|88>|9KJ!Ysr3OO0!v4lg@g?Xt3(YXL=n#Da zuzNZs)o}gUfVDiftRp`Odj`5bm?p-?4M`23ZWAwsQY3zvbj`!1h|&CAJ#83v%WQ(N zi~4pp4Ryd?BC`QyF24_ZY>La!%Ju!PBqo+XoEo|pGp zLVwk&Ch=NCT0F6`hid#)Y)vEFraQONY+NvH%R3+Q4%hOR!+G5A#9pv>WC%wU5!U}I zN-L<%8BzvlrJ!`6uKyUc$I}{p6*cV-+6ve3`wG3D$4yg zZABFL{OMKU7YT)-upy;Q-le4Zlljz|FFzA2cHR{BKXQH(MBpRux1EI&z>(-_esRN` zjyM%ko1HmvW@6TaZ+l->l}q$_nrU_l6;-j>d#bm0vqNM{;EwJRrh3lF! zkBo24f`-mI!(&@N*MjW~xB{8$pBZ?%;x&jKZ&VsCqq{GAtqjIA>?}p@U!sJoN#^K3 zx~GQMdVOrZ-HIfAt$i^O#KGPqQTQdchZPk}B3E$U8JvXMh>EEq7~TAZQSGz&3anN8 z(wQ7{$+y?3wnG%41W8P}>k~gL`ga3ssVtem70ge76!ywRr<_G7#!qIg-w{XXY{t6| zQbUK}m7j7h`pj+s^R#&++GvnWx1YHJ33tYF4xpzFk>z|Qn0`f{r)&KE4E5Dst!EE> z(Om`bI=Qv0>*%Mq236Y6YF!*>qMzeAz^hdj^UJAF%<{9CNDz{Wa*6RR?(|L=f5bUYpvI^oAVFHN6ht9Uu8;_Q-+u3ZG zcZKB@91(`)QAEKTk|UExe9WiIBeJ-_J*?`4E_Rx*xRotzHodHjGdgri8H>Z~&%;_= zl1*EzGqL%|k9Sf1`@>{H(`!egODa3pK}EO_vvE>DI)kpXk(b;Jxer-b^kR(`J})z z=HVywIP(D=dAURhfr~e@GUkHko}bM9J<^I}z2**AQYlrzXdsrL!QIm3_{_&vvvTfh z2RE*q$0V^hjUUA{G5KE97GG+0meP1}Ja&yF`C290m7Z*AT*>xVHmd!4`n9J&W*7zL z71;2@io=iJYUVyuyxZ^9&irjgJYl|c4VtTTqmbcXFHxzdxy46<^)MG#<#H9`XJOMa zzWtfzH!V4WRo~oyJjQDNamBoMCrENazT>>L>EjSLnZ=8UkEOjP7 z1SU}^uYI1Cc`k96FmS(p4D^V}5^QWC)GNZOGw3DB5ODBJlnU{^n6cSz?`S{I%Qfan zR!m2s1%#!KbwgKOvzo|D&eGnlB8`STFX7QmD&f}O*%cSzfPYB5DloLcq#uP0xxO)O z<{Q4C+qQf+B;;jECZM2eEI5LbBsO(HdL_9+Ek6^?^`j&M6*-RKR>ddeAZLiy z$Hy)5?q`3j#ANCTXwj}n?|I*VQf|@K7I%xQ;ZqFdOKR0x@-gUxtwKO8TmpaGFU9?d zm&5tMJZ7TN3}PVFr@^3-`tX{w-+sPlElEE{;!2uXFgz5}WlrW!e;n$bysw6rXTI(_F;DHR!oKhqQl?VBot> z3mbcMdkrP6c{82L0d?1(V>0F!4{f8rQp#ezPesX?h@%?gB~~)kX29Y*FIy}5Xs&hV_;r)Jp>AC_D&AQCOWKK`)Je{|+-{%-JiA|gtK5_6D?Unu|AlUX$! zF$_#HQzE5Q6fx{~`qmN5yUP(Rwk2g}1TFaCBp&|EZAN!id4z9}{~%1l@C`rT zzi1*%`GbD4Bvl5Q%1;bxB5rNTu99aJdQGW^wnAY2>^_Ko zDAl~?x6f{gwR|=I^+qC(FobFuLyD;DP8bp9!C!Ed?BS7dZp|-OwC5K(UTDX2sPZDB z2F5atEuJW$DhsFQ=N<4%BY1c+Vf$2Pn9};(4Y}eA#&VY{XKwo$pV2dQR+BETk&Z?H zx@(-KJx}hG2Ny_9F{${dt&Co zQYBop7T|CNQL~SOQ7SB zt5*Ui%Fv){w@$YXgM3>S1SJlJdyMeyg)`X#DI7Qr|486vxq*{+1Y3@>R4OJrV|P%_ zMEeb|9s=O~X&1Y)9($@go_oTnWP2v${L=-4R=BskF5;GspRcvQ7CrYe0=d!K$o_QQ zy*KcOP$$v_!J-GfAvuL%62h@NQQc}7`SRo%0y7QU4;eC_7%qqEjl~NES62kNS7@k; zGUU#wBtO%hT0fb;EY-!j0$voRyA(!lq8u_GZ!YPnqpa}s(SA}*k)U1Nh~|Tz5fUbr zFl32A2GHO_;{qfn3wMM!h!sGEM-aHyGQvNH@jg1Wn6xDouDT*`O%57+;_XBJq5h%% z{=%Cg-fF%xnh!W(x4Tz6K^pGoxn98oXUOyAvj zO#`rabLbXb$A%|F@kYT9TY(I(sjrd<_3$joB9qgCIR$>ZkjEdGd*_%#Y#vKQwz1z^ zD0=mE2tXbg5gZW*7a?00V_Q!l$Bocm4@F)1RXSUuUQYvQ)kaQ?P^{Z<-`l$Jt^wKN zr&F5;G%aiD_a840Cwc_K=5QA~xZ%V7~RzMh@ShA2V*`m-oc2Ydw zRbW{~w4=WQXp?m&u>*d|6mdX`(up6yw)|CSx&f@>cN^RFiTB)NeY02$CL_%Fl zt^A2UU^x@7VA~GOnpn(<&8H6|>Qs_2KahMG!xRa*t5P!m>0{XeKs?dR{S1O9#tMtZ zl!F_R+_ohpmg!*=xR4z&`SIr!oO+%<*m6)%zje*PEW7s>opum`A2zo`mL_g(IAIig z>+KTfs8u>KPMs87_IE{&wSGx;j}g)45GyGiKX2}AHZ{WJ3$Z$TNMQ1hfQw0;XfJ4P z>V>*VFX8Oi%cSY_cCXeCt1q-IBmTMg*F^0!H=&gIr)Q=_vVnrw;w0#WT49Vgn&Jd! z&ky@ILVQf^U2k5cWVpf!$5|`AF9xG%p8KF>N)Fbd{^_{2ZUv&j$`Yd3gUOA^KSp4+ z(dAQ0ciLasNtz50X8?W<2Vn{mL%Q(xk-6?g-P6v-foZrHzT z4es_VbsRV$_P^kH=4%0np$}a?WaofRTDbQ8;|9~XqkBZRSd!T#@?7D!H=0+Oc0+_6 z%pCej7p{LnbPa#pe;I7IB9k&=6U_A0z*-nshVbcZ3?k&{-;dyl_uMljaz^|Boocj> zQx~+n^x%Hz2)l=cHsoN3!joU_*iqjIkjW)Iir>$YVn`)OzEw#`peD-BBtHJAtN((P z_+b+SJv)scFpdP}EF0gFklFOtfyg$PWf1_&0TG+pT(19#2z0T$&ZR8RQg|maF*I8R zZy(bO5dMh?|LiId=W!sKqm)`so2+&hd;|doob9cq;;Pn;d@_nZU{0lB^E>&I-?iFB z%TvZ?sbRpm$)E75mEalSNP+~tXNQpG=x0|y^<7SyS2>WQB@CI1C1h_nOlDvf2k{KKT*)dEZK~ z3hp~KYI9$;)r`i3-FuTyI|RVaGXiBC@gH*cc@uFcVNAv|NwuI)y_KK&CeVC{+;#fQ zg`oT5qijQU+E6&pS}^5>vGtR1(sn~SY}(u(XzT1YQAuA!2Pk^xh9fz?@$}9v;3OrFfG*stuzmuxy>C!QrZ+nvpqmQ^Sn_=|LtNiX$clay6 z^J%!P%C*o- zk^K6NHzpNa#%!d{w37vKbQ%R9pnGJWASWRdEuwfUL8YN}`@3NHE~qbA}5)x>`Ap>z>aWWC!3qMA-cR;q6D%nJNNJU1_7qFC_Gh#L7lQ%vCyg zJyVX+IG(n$?_Mg2$TR>OHOD(CJNm#I+aY7C2R%)IU9d}?Ga6ox?Hu#prp;T|2GVU zdd58s=K9xL3c0Tl}JS?wVL?O^~6bxmrs^^78{g z1?~i!V$i|qVN{Z|!dLN+vet(mXSl%Gu70XAQ~7m_+q|zA&quLos#m3bD->p^{nGgN zM~&Tf3%ljcHgedXLlKKh$C4$t(%Cxv<|H0^=mnEu_Yee}6AGa3PM-(21U4aTaZo!T zZ9No!?Y>hZZEq?o{nU!I_Ny=9wQs|r+;0!O?PnyJ`pwEhql3qE(1GxS$Y4zRkeCwK zW3u99{4!VD|Lx@3te-}<^W~uxCFD8>)%p4zY8q=gZb~L~)nwKq$nRKlFeYunAFD*= z#ohm#fXJ^DK{2|_-v@^K5p7|)HW6V_rk42LuIkj|&6v}ut|~H`TvMp7eWDmJNKehY zCgqGk>o}m~2?L^hwC3onZ41cm{cB_6s@%b7GRHzQ!DBsjS4Y$>3~%lpivgk@bau$< zzd;{;m2jBv7MkDU35)Gq$Jver1j_5OLl-_3E>*7nK*-037ayIx%9kt9Y;foq+fH|wM;RjzhYadyI!&jGhn6;(ZL z3g|>GIHbxoNDb5pz>fdHUSBj=-m-nLa4 zmhjiv?k!GlnVQ+hwTS&i^o-^P^~>0sKi^ZHL~F!Ydi4fuM0Co?JA#<3Q1*El=FG;g zpL?iBUcs+gw4vb|ed^h+h4`Y9?*v}8gBvk~+p5B5|GyPdl6_2Js@W@9eY7=yS;^&GvXz&9QjrsjJ@ z&^m2U2jMIA47b<9Xl*Z#J3XS10n`9tMrFR%Jvreqf&~&}!5|+$<@aM%)o`LaG_K{t9Hl3{{n8Vo520we2Dke z>4h&b<43&>($V+jecfu|_L;68qGdtL?lck`0WS)XxRbujvkdlJsg&H~QvWT{IgrGn z$GUKr$I8g?_AuRBNWCgQq_STX_aTP7DTj_8{mm$gc^agmV|&|pK~t7i&jwPY{4p@^ z=k*YUQ(anTmCb&7SdkU1=W$tCNqTS*NClhg5Hh@ylph!rw7M&aCB>;Hvj9_TZ%R2O z&)*9D#qGHDB2EKqQIQ@)9OnJyQU?r#`HMlLF%7(R+JL-wu1MArbmDWkMqh#*TeZQ1 zYA_xNLUw*zwxhdPWm5XkM8(eSH{P_>H4o{KcnKHkYWbzzZe7c?=7iM}pISL^tl;56v1Lt1zJr{>`QenxfHpF$nC<`=+l22$~JA z^S^ZDHuVZ2%*fY`6q}HI6RRzi)O9CCr7(VMYrqjFh1h!q(=G{rJfm=R!xl$yXFJIc zSM%ukL-a>x0NJ~x+B3nwswv`=qiJ7V!t$>J!ZsK+$BM@Nb+CAPqYJrSaL zBh5t(U}PiDZ&7#62%?DWZ!wOj#+DzPcI_bL$;WR6G{8=deKZK~%C4D{Q1BAJ)JBKB z$?c>h!WfBxV`g*M+${aAYxr!~m+vK?#QSm_y>h!w+?5r*JKK`z%WYE19ON@atYrYg zC3vmQsGf-YXo{cQAOE-FC~*!HT;QnS<(SeEG{TS(g8y67F-(3a!$?Io>X@_(8H7(9p7Cj$BK%NeBooEMoV6$g>;I1^~ zU4uN)_`V9gtG@e#JZj#pK?!7F++v5Gb^&7iMkv)hu|VChzh9sB(gfU&&u58mbM%M2 z>+8jp)$(50)o}!NTNknNj{LWrrgV~sUOP!t63)u=pQXV?47pa8u#@%~S!E4Y^ECdP zU%uiV{$ZNl#LzHF(ps%deDH_Fu}DpPW`{2BWR4k(tku#=CW0v{(Mh1&LGr;<-|s1X z)wP*U*}04Wd}sbV-pT*=0$?S+;`0&N?a9-*-=7aE0@KTlKLbUc$=UdR+^6AVVQoe_ zwaUsWh&GJ$w;MYx+UZXJ0>MCKe51exoqpX_Tmb?9{<=`MM8%kxu`YaAp3V=$zpzZ@ znN_Xr?m+pcexy@9q0TdJ{IF0>812x@cgv)y7|%CFv8Z+*OX%sMqKxn@^%2qGwMC7; zer(GN@x)ERA1o@mJnL>>yxuz_7IaP%@_DA_c%logB40M!+%&F~{YT}a3qWR<$7QN{ zbR@+xC}xz$^FV7Sj$a5-RT%~XWv~$uSiC&Yk0^;6MopD!0u^Wlc$1Lm53eb^q2lIciv^av2R zb*tmBvk^`j^)GY{)L-@L&?F;0=5>1IdpKm{KM1~LUoSoUMXp-K zx5ZYahzzq0CJKj)rdu;XVn@xPv%(y8?o}qTU{cqE)l^#VTa(=-KQs0zohEAum>j=9 z-Odw#L()?$;Ol_q;K!D7>i3Z4MABi#QjOY*1|tvu!%rRxcxm2QVpdd3)KX&yWKU=@ zoq(Ik9s{Iu7TzDa{&6J=AvpUHQ&?A|-0C;~%HGb8mdH7!WH0!#h|7n@S+)gI$g~sb z=p#!V5o%fq?X6V5+XYa)}#ptijb zO9W^(gsV3P8a?rVrN#hzIV|8L06;xLxB&%$bS~{7O~1i#!z_3v?qnD!**AJ@&`QGTmr!a zXM1%WOHi`og1!lL?TfyR`fQX@V}GFxgd~H}#Ol70k%oiD8z4f6x(knscQqPkLerFtlqFr+3=5tP0ls;$cZ z92)BhL1N=9Q7im-ap5#qqD@lF!SA5;mpCX&^P|{MK-F!n%%+A#i8-0$$cmTx|+yEW#m}urd!%o+A+s9r(9C z;e-}h(lNy@?NtiiN7UJ#rr3_g@S00#fpBq;4T;;*B$1U%7|R<<#A-__6EtDRM~22c z#76D`#%JdDR{%iuOA>#|3&ywiZwDs7T*{Lhgl_?71}%8`2%@4v@`*9___FyCvm2sK zBgly{%O^btj#y+w9=NoQfkgxnbrG`%4WgX|-FF5hQZya-$n>0}|DkIdV_W;aq0}WkxHtv=-OIc|?TN)Q zsh5S$0SB)^jk6xSoNGFDGT-(?GD5V{X!5pw-M+#6PXIw5sn8M#|H|X0^6@GR{h_!i zAkE&+ED^*$V#SF7O-Y&9cp|W(%CH!RHeGo!5a7Z&-n6gAS!NFStzUMwMkIb$tk0tt zK2hzP8lJd;HD8vC{Gqt@FX0^kJEANA5p)UQ-VIwPpv##f+MDP7=;Rk<^-Mv+CdqGe zut+%c9l*)OAW8LiSK_Zdd59Rz|2{o{E<);sC+6HW+-(PW>~<%K*9<=kjtdy=aX`j; zQdIK5pZWNe{`<-n&>}DHz;H?bn?S)2gWiihz<9_Pm^h1NM%5lOVLy~{Mk7q~MqQ<5 z*|xvG-!N&XWS43-d+e%B#SKSqKH*jSM4WBv6x;B);AD0u^xxOZKLP|T5PaK%k{^9b zDV=mNjo?3_5?sfT{E$y=uV+2IPcAvpcVXexgR2=@cHu0!$uZXzJLrk7z9>M9dDC&t zbFfm0)E*K87(bE6EO*^Z3GQh3y|83&?)tvW+I#CpS4)IeduMsiKgS!b;eWArWO>g) z$OpN035u97hqZ)65EE7Dv@F9L*cv=>r$mPN!A?iVs~2rH(bo1wZ0@p!Uf{cyi;=O)$`Z1&Vwq5ogNLtx%60!+n{*P#yltY> zp=%9r-0Q2qKkgj($&oK9XM76|fO5%2Mz-iGWpWER)z*9w+6_vMKT^-!bo!3*E z=VWIqiHi$@Kp?vGC`H^-?RswL-PzXtg~{Sc{$G|07k4L3_N|Xjrq>GKXg{a!jj{%} zhbxH*-?oAYzGYc(t^mx`D1nV31&8`JTyc+_S z-Z9h3viJ*dCL@z;ng;+w09PXUU9dUdX2k@U6Ls}>Io&Y#+dfuV1%*qJSsd&MqWK3! zT1Nm#dwX|xJ<2JV*)SDhiVJ%nI^w&%r3U&p7*b=bST2S=;SbS7J6^ro{(fGkR^9%= zp}aD}Iz{Ow0nD5IwL;EModY*KUph7HP)S@BrPQ(Gi1}bQ+VT=Nm303FTz`j3*SU8m zUAog`^X!JBvCCp)Y;+&aQ7?=PkQky_W<`M0Zjx$z4kUtn&Ii8IPOJslZSU+9lti8R zS69i*r8ThiE#BX~XLrUfTj-2p4heH!mJ)_z(3>z6Tapxh^kVGS*qM|GpEvXt+0p~KdL2)*9~6h5wPuVeGn?L$a7Fv`v~E2;PP@Xh zpm%mCG(IWp;RUo`rxwqzS`KiDmiwF*{0Yd}+v!P79eaF5j*Rs-<;c+^6}t_r(Y^@A z?h0i9*}|gon}|dbG3*2?Om)qvphY@HwzR6>Pmg`*#QZg68B8DLv4ZKyKf{Mr<=HTJ zf2VbXeoq&icA&GOgkm;ZyjBetHgG+TN2ITKekS7=<_ean4r|_hzY)FF1s&6l`?jLX zk~jBvwa5Yw*ThDH!9ZE)c-sB(M|bZkxPaOc=KQHjjoQfeXl*tOGi2T zDue@p#c@L*YwQjl_QMkn6Zx*-%Fk$3mNUuUZL0DV2}m%^-J5LZ!x$Fa^Z)e3FS<_2 z7wC|hALhEt!k0h<0DS)ZISxya7^;Ab)1$$2B_3?QYUld*Y9Q!a9rpDTS0A{KM~dX)`4p^lh8p~|1vFv4 zfzG9c4akD#2G?_R=la{%96Ik*oS)6lKlFjrH$=vBIKHR5vr!4CR=@o8X|F8w;$o4p z28Uno9T8X025A=EZ@bjFcMR;)pVj-lsHm}p$rFNm7gah-=}?NE1;I{KdgELZL>Hco zp)sH*E>rFqe!p4j-0Owa?+AP#ljqR7e4I9l5;Bl~Dj)!>2qUc?P?l8I(~bBXgTz28vF zU#=@542{K5CqE15@>u*99r)Sg>tF z)!x^Zyi-TrqOVv!?RJ6fl`tV!6tHRVVw(eI#e7og(oPxdU8U7PWan`x@&os*5Eq|A zEgeVH#u6%AVI^}YnL%v=jH7M( zW19^^c7?_>4j^J6_+0PXge41vc1G}cerwl=4zIiQTHjn}J?V0n-XvNUp^M`z<2Igs zTA94A$DK(GF;`e}*IhjXdM69LH53iVKHF~-_rIn1L*ho+euzjS|NO`Yd!-+Esyvsh zm2!o>9k#Lk*KDRN?j66$=HS#{Y^fC7drHs>5DomBgf21`_2JquI1E3Bj6k^r=vFT<*BmX z`|!!^6ajyD@*Ns<_O{4oy1IN|<*xl=Z!bL8h#jVX_m`WqdOZ&2cdwqC@awJ<;ipvj zXX;dSCce|8u0OpJk_xCdomELZL@R&_30L;pR0-8O?7}5)p9Q;M?b4RfNm*vl1l!m?*jL#f0h-CnO{1TaS%JEU}@Z|o6*3pA%4h* z2f5TCiHJJyu`SlYV{hv8kM-mI0n0000vi-dixN8rJ(i$_rl)xHKLfMZWrHgL9+f4# zsZFn|Hc~JR&i%a&gr6_TafpNz?PN@EPZ{XL({5C9pRX3ezWA9FF3>ck&Ex6peI?9T zsW`{`VD4lWrv3L=95xG1lr%N+p6~f6WX^v=t z6cNNQ@~c7#Yh0z~r_j#51r70s>tga?SJq<&puifirSVykcSk9D8l4)JWxBGrv;P^~ zz3!Z=T!nYIjekX@myNFhSZ~)fz%sw7lm~{>`$5Xq9Xz^(GN%_R3=g?d6vtqNCY-Mi zn=ShyaP2G?p%msX7wlhP6j9!i)vHK6H_DSz#wh>23f+Qz@Yfg?(7QUvB|JnC#(vm~ z@2D1m=I_RHqks z`eL%Poh@>cTG&XvG4q+uE8wCKV@Uplu+DsO4>>>N4dRR}Oq|c=NOkFB5vje1SFFf} z5|3$uM|`58(x1B3tl0xmh{1Kf-w0){u=#InaBI`(t!&f(?o)IF5PqOhM5nhDXrPcb z;8tQnO)QW#f;V+u_eNKvoBIQ<-++w6)7b0RzKqE*i#g?}RD2RaSQr)G4=FehjZyR^ zO&7*GZW&dStZYeHl+5%Ov=aSF?)fqesYKI=bA;1E6+eh&YSO9S8I{SHIk!Fk1?xR! zvl`{y6oW<;G`o41MH<7Df90@!25P&y_t?Qwy${Z*gbJ3h!x8GcTTKH;(&jZ=jtyGW zbPINpuB{TVYsSAUTS!B@N-MOX)GtsgAuzF%N%W@-hbM$OjxAto2lNKmQNPdkirG#Z zCvb>G@uSa~z+=-M-RX*n?eaZ!wXYwYq2Fp%#qV0Xde4iHo5#zmyN;&w??3fQ%pNG8 z7ChkgGq^*&I4oF?e_C&od4)?vkxta(@w9oqHy+|QNS7SU zx$@nzjAR+K?Q_2y5+x>x4fL_Kd@+M|dOeCp zcQbipwOhChB86c>Fw;gO6R;X6RP|QxNb;^ytX}xtT)^`ZMi~(H6&}Z}f8e%XQghY6 zGJkYgg8XrK0rb0-K$wWTTV|W#!2(x)cpyAT>lfx0Rysa(D%dTy>c9ww%|MA80u;&9Oh#Uc~ARSG{qyJoH&_ z(pYg*fLxONJef52?37g1QOab>;K(}(Mb+mBQ$F>H)lk>NZ2n-_J9~m(doJ{KNNF?u zk6w^S1xOqJ`>YI}t7n9Kz_;OT3gtWkX%%MHqk{KVA&Z>O%vUtU)9VjNK_|#{XH?D$ z-!E(lM6wW*zGA|VnMd=5pbG7^g(J+V3>h?^9fUoNE~br%#W)UTBz1sYDtq(!<_bDr zdP;n`INIp}8*do|F?X%+uCJY=wZzXO|I>S`fAJQP_>Fdnd;0v{_0$JoG|4mAH~ZPZ zaZjhdyix@wnPZKhq%w}TeE8@^7x?v|h$u399WM&x(Xx~L6 zY}+MXfURa!f8ZpV_y% z6DWi&j2fj11MgBCE%s{mzkeAU=qEny zX=Ns1pFFuAB2*c(kI0Qs(NbfP;f0TF^dHnpQ}`sS}S`XMSNrMS0Xvzq#4?XrBJb+nYxaoq<^ zlof#$0aX%%iV74*C6FMA6h^w5+M_`0$ea;f8Q@SLuKQ7DCVt&{VAFM}cI+L<8aIsM zTcYua?+sp$+liP2co z$y}ue+xvEsfr9(B77VFh9Ovm3f9t7WLkb|tTl*3ThYxQVfuA2pA>;95tl>K2+nV@l z^wFjxFU%uI%|{Ptx%XsuiQ7^U%3RcA@MVATPlD@gyYj3S7F@HzCvzBMaM%66L<4W7 z4mjv@L#^PS(kCnUzM#KJS(i9BGs(W@9B<+Y2c^v(f7tbjSn8UeSH6XadDW_Bm2tpP zbgApvEQ_VcH?8ku5MmpcJ|IxAbvEWz;8~*M08@Nq9_SB|&4-j4Ip%Jq81L?(O4?%< ze-r!V{BC&?=yc7C?Y${zjFA$Th1O+LJAkBbiVd}3vC2Bw@;AZa=UEu(QuZ#r=*N%j z$?o=-fs>nrtW^20p{9w98o#F~X_u*5tuL;(@wB=eg1kEn9@FT7bpjZR?|A7{x{apWmqzk zT>}1;0^|C%>))Y7bNntf`Lwj}oH zeV@@Gt)La28${BQ{f{rh@xO|gKkC(Qr7%qMxFLLEfWofW>tGKZv1!I6V@z_DBP)8( zUrW1_jlRde5z;+{2&d;U)28{3B>kRK#-oEjyWs{2VlfmKA@thPe9yo|hQrR~js2?O zmzU>P3h5lFpX&_0$H$faAK!8`1KhI3ZmOe}kR4UdGpzhdKM3xF^lW}22UAXK{L^R} zW<5w5p6d`iscf@{XCtrwA93P0VqpT5@Sco^<7Jq9XEX}aDhD7k@vz_DYWROxbgV@M z;BO4%w)X2ZVfV1|6)Z9=>wPG43Xrn+?fJF{EfhaJ%y1vMZFhNnX^PDiO=3YzbE-ff zfFtMk$zm6p-aL#5S68hS$l~lOdmBr{y?Ndf;(4{I!e$M$;3!?Gu&4z;0g4?XTT(Im zG^SjRS(7`u`d$L=%9hJeuZLA(j*m`H>8?m9 zyMl;eseNTEIUNA@*ioT9R>)Er@uL%skm}lQCw2TQR`dDPah)sSMiQ){yFFaSa^oZ@ zz{euM7T&X-+sPwU&Q)t`d9mZPuR#0K(bT~N0P@m)xnQE_ZOv{QHF6&xpNyA|+n!P^ z(DDbH8J5_Bw%#84nESsC*W(c$$?u_U^t^fKN?IjfN5C_RT+1Q$v=wC}@v( z4a`gvvb-`gGlz*%eGG;AQriI?k43YwZu*i-$!vz6lo~~)E}u(SEY4(p*;$Sgt(K=o z-mXqLFjO}@$DaAG_TQBk*F0oYb+8wygLFpMyfe2UCihM2E-?wPIP8_T$JNDno>u0O zy99-#f~5T5(iQ2=WmQu%;o6+ z_5w_ChCV*}uGsS+;gF>Eh1td*GuC~c1PfkWzk8TScUi)6>cb}r*eTV;VT763dvIN} z7tO4*g{}#CM|gP4ghwmpaN&*w9#_4G`NUK0!FW%0d-g(UU5*qfrqd1MmJR5+mjjwk zVA$VXXS3tblk#gb2Y4h_t4U&pu|Iz}aCgvUraz2+3^PK&SqLW2RXxwGRk`d;{!Hx) zWL0536YxRQ@rQ<7sxAxbhRV@P#3(=V}z@-iCd5 zGEzepG6IK=dVb_6SJ4?InWZ6m!BULX;eEo{Jxw)A@1^D%Dgi1|T zn&aagZrT6Y2Ei@My~CvbGt4)V{!rR)VoJlSF9O_}A?yH20fWTh>&E4Gb!me? z4cu`B^#686&>ZN^7c|0M_**h(3elLYcdvNgHts%etlhDJ{7S}O`?Kwh56Y+}D7|Vr z*9nE+?JQWpPonmWM8nlu{VKBdOpB*j?F8BE5z@%<*|n83^1!AU7vc@gUdipk8)nJd z%}!b-h1q*@M>(%R5{+A0_g56)TC_1Gs68y^x}N?CS-YN9MAui%LOCU-a z#h=ISR2PdHOf8pGJai5kj&yzcA{pPF)(}anuY2!qNoIZue3J_+?vv{-BL^sYLaK2uMCJ#XBK zwg1_~Ali?m5||ZpI3L~eIdaba59WQ*{-Wv=G)c#?aG_IKL=u);yUg?w20S05B5?>T zD`XBgMRIsPzQzeh&=lbh^KLYG?GGGh+1Sqh+pb`5M!~t^T};{{V+s3&@1NV&4MBmA zp;atHs*uD#$l@0Qx_QE{k;o&M->gy0oK>!OZ&mx5KXV=xh-Z#W0M=d@AJFuF6GgvS z#~ud`!RXzX4ZG?cfdA{#OvB>&{m7N9V^qe;cl6lxnjP;*n~4U>*KfCtfX!RZt>|eZ`woR(lm$Vfi-XLcwE%@jrD^zxqp|lRW`e;ll z^^eru;qh80QnO~EcD;=gzX`^x5$^(6Z-e|yqgCO?nwkg%SiveCLs(fsG$B5$6T`-h zH_Giu>}keQ5l2mCrmihAe%ohvd(x<~0y@IwW_z=}NfMY_rW^^Dt^6I60cishcu7Qgl8(zU}OZSl{@)U2+f=LZ7H)Pr+X8MRhEGRG8+})JGm` zeJ|{_*o{$aXgLTP@;&b8O=g7~O~Ed2F}SuYj!;et?f|2p{qp$yL}r4<)dja$dM2eo z!Y9yLn=`sdZv|-<)rb8*)W=Bv^NLP{qTN`OY})?Eo&>{I|(?zOd> zY^OlGPp`>O&b@W>h(K7>WUst1?}$>j&wpg^LofdnN_**Npky@DRk-YC>~@^IOUAp| zd3$eO=`_S!+sq6VNlst@rK10j(4Sv~<=LI|bzqE>snW^OT9w-sH{g=+6Jzu>qM}_EO?^bYP$$aI;^$=NtI#8#nFA7f%szYQvW-KSC3-U{RZ5*Mb>t8?B80fQ6q?Qql64EXYxd z!h89CK~6$KG8h^zSy5Qnc*|OX+(e@=zeU?y zSd+cc`3Z>)^=1WC96J?%cTr8=MDOE-mi0~Jw_i@8+P@~8WWe?A3($Qzxw0-%N7vP! z8|r;wKL2Eb)JPOaR4~R2KH*R7&PF6)WJL1$o5wWpyx%)F84Ev%^4`I@)g#`P$oZZwOutclff~nAj)lPlL9|kW z_w*7KvuLo}o1?!z>;0Zs@wMRslZ`n&5OT(t)f9yH+&0XE4udn=c*7z##<`o<`}6JR zQdU~`$?KGIwLSV6yy^+nft%DNy7H19u4WszucyVyY6*lMpPt2V@>PMH-YI(c-*1$q zgJDDn#uZV8LX7xh-dIE6g)AZ>b}-4{M<5hbW7t>P$gsKGbS_;i5IkqxZSA68zeKM= z^QW(0zr2#9D?3{y@GGz}Yx;LdB1eyf)59tZ5n@LdsMI*A_~nagljn)s|EB-Y{*^p2 zP7suC`2|!6wBqyDnPg0zE~>hN6@5p6`dqa1L&>;alcqIV{tgADmZ<9o@}A0%&{9pN zt)R*5#PgXSS`AOI!%}kcIvNsDx)j2qL3L*Lwn)fG3MI<3%1!G?OHcaebdPX%od?Ui zt@`J_+4CvllP&N<;?h5O#{f1NQ9imR#kOrG!RGPF0HUB<;W|HL6X1dCE}qZCNM&O1q>qc~+v z%v9hEA7IT6!@!!o%I1A|Qd+oih0uFHbo2E3lYd)~lz4EWJ&?qkX5IDeR?d&#-gC+l zo;`Z8-7R;PcDp*cs{OdUs%n3$%dz@R4=fH{ z6~BUVu?vKCEg(Mv1*%3YsUh?Mwf9XGHps9l__;!MlQ{x19ugGLr`wo(-?>>D=1x{? zMpj;sp~g*6gniM|(Y+fSjE=GG1uH;2Xl?KblK!eB8B-n*J)x*nzkdDF*V{6{p+r?s zUyKW+9dn=88ZMFZ(=yE_g9l_e=ne}(hp)>q*_5n{Ch4V>NiT<%^NFb)kvz>W z2BNgBfdUhmCkhF;sN6}n^}QLE*s4#I~~3QwU^Zs z+%So+fybGn9FO-KwEgTpr2BKh={72j2s<|^y7+ynRp`K*3{ydptPEAeYMtD-d-d-WBV>-Pr&F4f9jb6DN*zUt^sZzfkljox(Z zpL}kQDt~`jn;r8N{|>x)@A%el$GPxoFqpfN@-XhLic_HnM>wKl{QV9isl%R%NH1e- zX5~Jswo+}>H=0jc+Umw_udBlFC?7l7`Fcz`^Nrjq+;2^5fzOd{VS_nPqG@#)p6xvW zu_?no%PASw!~F?`u~3@8=*bAD`eCE$x^;w>q^RFZU?r2y4)jFkd#eR0!g@8|WyY}8 zPq9kxf%N`V$ezuqtVV4BEa#$)le>={d{CD?7u)xSh1d5+In$Pv*X0Q}@L93xg)_jZ zW94AJz!dInRN@OJnI}>)WyGkFt~6{MZCtHMU96Hl^Vtn1Kn`qti*XYLJVI4S#RNXV z1htqL)wB*XxOeOF2U`s5v(DN3YRP64-^S>VB`S_B_S=kKHi^jE*JlQoFf)>^l{C8D ziX#=;bNY5AFgAocoB?c4X{UPcY42xzgSb0qJLAL;`mcHAOc0HluH6xc*ZV+Ak}*DB z!S?00ktG|*l$yicFg1K9a5u`4M>~a)@Q6M9_6a?%An-H&nFcWckT>&kjd^X?mN;3= z9Z}hY*d8~0kKCMP-I)Q2L_qH(+weoPSNK;jrb#|}FpA$I;0CybwJ-knTB~lUW$3;b zR7n?-El|I4PgqNzEa4-+BRA_0qbSl=D^|bVXD6NFlUg0{U3;-xUrL*x0j5#KqwL+hrNCR(kRDt49GTWLa{hh!pk?5E!uSMPO8u=H zvi&NFcJ+Sn{^K5pVZT!O+ksHx`@PS)*PCgk*Twhy7X0_u4k#LmP5INAlJU6T*MxcN13oNvoAI8f#z*9Q z(@;I`#Zft?-NQ3cwUd`YB2MsimHv%!y)(y5AFsSrkT&BMbA?iWc=uSt(*?52BN1?c%^rfQ+TyRsaQ*E$U;RTC2VNIkC@$TXXn{IiuEU44g*Bn|CrAw) z=c{=nDc7uT)K{WsCu}HIp`oK06BlolJK=J-T^cs;;~nC&=GeG?+RuB0aIfdVSy`Ni ztBWaM$#>hbwjM{h*&Et$_p3oK8)Vh^#kPOgm7-gnKP~kpThr%z8qeg#!#zU!_qMCW zE^l}sA5Qb-dA}YF*~#(5#dx0#`9KutzN zOZ&~Ead)-5NbJr&w>3U2*mpe3>+UKI6r;oBVY`54tV}M6VI=mF#OLg2duzn-z3*oO z6NfCyr9%^|)c6hC4R!m&M0?G<+336@sdij1OU~BI)3q|={flt3teEl(Azquevivis zCQp%6sDniAAX{lYwPusr#dikwIp2CA&ym41@_t3WLJptl=e+wqYKH{PNdU`BG zG@qE5J@01!{yu&`@OZ2Z+D?qOI@^9YKL60`J?yTqK+nrTO_5&ph{@cqG-<~a%j zGa6~D3Bj&{e6upDQhT6Z`BB&Te^S% zoov$ao4iW*22rIzBiAn&SfOdlYAVK9m{zyro(qB!V&`zN zq8W(W&duwPFKD=upvsJpknm4!;nY+ZGNf<>1j0dLUs1pA?V)15-cN|*9M`k!VPp5- z`s!`n!7SO#!C|aqW_^E&JhnR+_RHXtNB&LDzqF-&_SW}1RZFh1c0;o|^!^&Y{ieyv z<2v!9ckK}@9;Y@RwRz*xT2>sE#l681uF0Lw-EoJNf2(EIAj%L^zf*GwQ} z`uy%u(zNAvV^z-8JGrsw?hZFI3Q7NVim%T5rblGkWu%Vh3r^w+732#s;qJs>aZ-eW zuQ8ZK<}ET61OD-KKM9}gTfui>x3M9%lB)SaWIlIry7dd>37OG)Dt_4MD5#g{x$R!f zJ76!|;`C=7!S$p;AnMCQwYM8_aVXxK&M7FIBvTi7YuJe5E83;+rrI3bjHByjtUqSc z^5L|NCR3CSrPa{F+pdjqZ{Ub~&kNsEQ1wE<; z*Qe6&X8n5jyV0d|jhgS+?TuaaxCI`lIB&b(l5P|qYI~$*feXY6Z$%%x^=wE8k2MNc zU18Z|y?!)Av?sGZjYhSGMBKjwXKFSqxP1uj2*?C$t+Uz~2yfXHjC|>Y$+K!B78x_~ zC%xRo$J-65QM(>_b9r&fQVQ;%>ueIqY;;qjCM^=&?hawX*t&=eMHbH_31(w39#qzq ze5XnhojZS#w=B;eopnYjQCqOxtG#Suw!~?q6uLjqT87cQ#@Q{ zKtojx4T~g{=*~z3T}z(LG?Do~Bj#-`cz<85Ma>g2@HP0D(dwLASejZo3`2*wx(u=< z(k8l`_FbUgTc�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 aS0*TF14hj|O>(j5EN?=CvBCx%ed(ZCoRy+9 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�fyDT|VNR%d~? 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ò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 z

f{VmeMwf5(dGy6bCE_5F7Q^P3r|7rnxa32p_exrEJdzFe~q1g2&MO6erc~SXP4#RA? z!69RSy~)_&c<)&~;r3;7EfK3rZO^CcjIxLG-T`)juf412m)nd0EstfgSJT$xo%cDO zX)A9U62B=ES(g0@AB@pceJZXq=u>Mfi)CoyGh(^Pc54y=y}1AHD3K!C2~>$Nd{#CJ z%?1g6l6K0bg8Rew`KSTnFrT~kWiMZr)~2u-^ODe{rlA5eC#WM}*|=J|i@_YLuC9)R zS-ZQ7Ff@)RzKf+LqokaH8HWJCXuoak!mKoq{N*oZk6jEejX&vq4 zB*p^TlrY{>=Q&aoEZLxaIqTBZDNE%brlInJoT8qHnzYJ_2cHXJZ4HY1Ls(@uC?E%s z3IMBCRvgU$iJX=mT#xFf7>~%nv0i`*BRzZK}Md{2MqZ~j8Lh#AIdILHI zN7MqUp)fdtZY%Amw8wYq*)(i8nj+TlpyNcOB==n8@O|s`Ga(U|s)|50D7GOb0Bq;I zKDT%#A&&QhON-nZ&p3?SIPi~jp1oj1c3+=DHJ6^e<4^2?#Jo5tHQqQ?*R4No)2_a4 z-D(zx`^Ch_kB%Hl;higSe#3T;`32k7!$o1+*1MWr1FuCagQIleW#mh5m*PmT>q-6E z2dlk}ZxoY}q4bWJy!od5Teb)cDYsVV7tKFIMJu3g^35lKhb@+-_|Ugxes)wp9X97g zPR!D3H=Wtpo<~h?+U)=Rz}TRk8zRLO@Ct3#e4txiIr#0qRZ&-(A{>Fy-SFu9=z{t~ z0?q|Rlb^$|s3eN_XG!YU`?4G^T(O(2YCY}c_)a2=2CK!?k6pb7ca~+DD(2@gULIyn zZkM){B+UN`v8UVn*pA^hVFzc^DK9s@KN=p9_)hdPtjqmXW3qXB2j4q4l~cKEy7wAK z6=`n2R_d!&G6M|k9#qo`#=Dejv6h~IAeQ6~R}WQB@F+|bn!{M6#bQ3j#3VYB<8N*} zA!D;r!?x$xzoFK+bnGFHefzdx?FJ?LHUN^bm1pOBnv&*FeHTUbLyz5A=tVW(7)ZSX zzjvYuerPbqL-XwGMa0C|^JG{>6R^#6w3y?Mp$2&x2(1BS5RWaGAdm_R3!^Gvko%#F zAU;0LnG05wnxLEu8AVN0lT-Egal?IhUpyrcVV91b%HQ2-7bd*a;KZV4XQbz8V$yjc zvPiX+mQCqL;9Na6rYJF<$~wTQ9z}~olWD(6xv2f*bc6>pcc%OC5~i^PQx1~ig?^>| z#v`R^8P!~5Ufk0Vrxz4gzST9op>gztWA9y8rD9A~Q_RZ)y?Gm+%GWhBD$lD1vHMR# zE%VyH{Kj@;q1q<^XccI}wWehhgv118vC*=&Yr%IJ9UX0n40+^4@l7=&kDC&Of5E2K z;Y*f>`!Z09I_WDHO4L1+{=9Du}TeEq*eBAnJ`(p;uh? z!c+V8ay0mp_o=qct3IRJkNM`#dNp>+Cx*Rt-OB2Jj}AHCv)2H?Fv^yJ+pgQM<}E$< zyTcf=S79?xU=OhS!7`=4xcM+Jy4 z3J+_I`k%)te7>)Z=$;Hj>OUCD>z3;n3srbLXB1lgbPcXs8SuK6r6kwNd`@}De~kV_ zcjX+8VViq7oNX-Vg{Q(XUch*n|EaaJo;jdP`F-xfKZwwYzX~{Wlrt&)M7if#T4P3W zxMZ;!bHGrOKu(-5Sj!}3kWx}E)WdI#7ryMz_F?N+Sj`=83^3(QfnrB`y&evXMS|o% zr~@7=lrLXuK{c75;Wik{JOf4#toc$&>wA(eXJ<)$l|iP%Z}+n0FsJWHb2swMJKHcx znqjTtfSKqY47eR%-u)J^LBh6i1R|veYmqzreMN?FLfH$d1nkx z+X#B^gnn&~u_Fj*L)VtfOuABl2kJm{gF*Xi_P#0jZIJUBTSH{Jh5C%$f1C~S;1_TRu(a~*bD{<2U0 z;nbG{!Rq>|SgXMwQjTyFZ(2P*jL@}o+}UO+70r9wM+5+8Pu#l-Y`)uyZKZ{tD$j&L zr7`GK#LtQb#7|PHGH<%36cgEAkP(B2U|vz&V{Vs2z-}pCQH$csU_-oV=EU#N`XE1! zt9~=*mYt!Vmobk@cS0P*9M@iB#Xly|=QM6lNngD}EB$m*J57#+Wrc__QC{SeylvUI z>?jl4-pIU}Zfw1sOSjE!_mB#Say4CT~LCc@Yuh2+j9A$_V(A)9)shbeTt2d zdLDYNrFMrU9=lr)n=>S$4;F{Wz!#U5?>;y$+gFgZIG+g~x-N(th&Z=bP0yuPKl}!_ z)h@Yt-UVXNJ3a9jKqj^v4Vh(Bn3&QrvXK)2fRS>0v5rVX&gD@HEg`ws@3un&$Ddd) z$p)UZ{GI1W*Dy9Q;)2nXw^bCD)USt9&bc2AL|g`ascXHjBro$iq3${7EnoGsO>sXo zSP?_&Qu7IV8ZXq|FfTlRW&T*YyB^z5*~dRpf0(1!mT;@zW_ z-t05I&%c(w(|8bjbU9#V7LPlH-n4A)e))$(6`{`6otU+B_H8Q&`zWEs)kTI?u9(0I z;*_csPeFx=Trwnk%F2#fWaO1UZ|V>hr8~s$=;N$p8!oEVIPWtQN=nMIncblH9>5(5 zbD}V_v}9HwT<`CpQIo><^&RIO;^M$&mPE$`)}LXF8sq(>0=Kw<{lTuIkokwr*A*ZY zFGV~CCinwfzZ0iabSmy%}Zo;DfhSbAxJK7znN6yckZw zHm?^?LZwR4y0^j6xQ<7nCPYGi+^Q9rc+k3)TA~%mDW_1DLeRB_zUzu*HDcW+wp*5f*o`^^-r7W++3zZU9}u8+#kO$S%evv0)yHYJMR-e-Cq zxJnNa>-)Q#q|KmG6B{l!RV9dfb^E?1!P9opZT}&vIe4!_PUSzk>{ul~Js)+D9nP1) zE%!-uod5A4>nN!)E3l*MxRP*lZ-wOZ=bGn7Ct|NNAJ-xIZa7ZE253_)!F;pd^HfDA zBj@I9t7^x5d)(B+ysqkd?rs_n?tVJJiKw=6)6bT-;0m@kgMA}ct1EZEs|qx9+8ehs z3A|62-QS}Tb%^qqwe4O03^m|C@@jR}@xsi1XWS`PYHM;Y&deyBZkk25*p#tp2ZdrsahXu}}O^Cay%)1gjX0Bm@ zwbEUemTy0jpoQoX{=cRyHQ};M4*sKZ>QbUBp|LVdf(<5Ppj7ipvD)pl1yi) z2GBy2`5nhU$d5gC4HQ>tIZUD2q}1rYy}&rX*{PYwgBBjfN7-WTf8-53c|K{g!JKzV z6%pJDWl~QDCy_?LlafRsVdi&=4ve;S#~4vOI;@z^9o{{vg33522datfZ8fFF^&tAyznr*&Pqkl3Vt)^F{rNFY4SFiJZZn|c z4L)`N$EBVFA|tiagwTS5d_Ssk!*~q|AYP?V6Ng%kT%MHzLf&iR&$)c32vQ5J8QX)e z8~&orb%Xl>*J2S{dS}QjLzUR!8}ebkhntWp_EsKV1$o5$=b^24r97xLs-Fp{C|xg3 zh8u*y;4}+mCtlX#{d1d&ZOX$G>Kko#pD}`!a`tA7)nAQo#(96mekC)sn?vvOSZ);u zu~I|Z^(X!G#^L1u!`E9zwHdbSg275C6oM3YEACKSix;QGHMqOGLvbx`4HS1MUZ6;E zr+ASP++FAW_MUxa&78C5H!K!Op1jX}-ItMA&dXSIkF5%e`mzlCVF|RI_suVcUG^k& zY)ii|7`i^G(R~xpovk=o_?eTx8zc5`{YN?V zKfK(wUY+ZJQ*W);?n3|3Lc}|bqtR7w`Q&9=Fnah+%OC|E04q)FWMmknlKQ^4RqAW1 z;k5cXkMFv+e0n*YgU)EYKre;-=7T7Tdc|A`@eJW1TgHgMWiIEuP1EG0boQFN0d4wd zeWiLCL=xbX2_teY_!Z(ffgNDz!EPocgktZGlj+Et9RCf}Pney9A!Fp1WLAmDnj-li z=RKO$zpWQ)>eU;6mSX971=2TD62Qukf}&2qDu5>c&C>GM)SqQ>oTQ%dGJ!3_bGnb* zn>n=%!Rj$l)X4jC(G4C%+6Y03Y&;BuitekgV4Sez62{HLDHe&#Y5U(Dq+C~u_r4gjAz1*ZHuJ&IT(Gawz=j2r!Ezwz``^sAOj}juS^-r^lO|3 z)w`@>oacHDkjs$<4A%nsoAN9rf1VfdYu`l+O3~29`HsOps_Yp z;6nUL-gGYNhSsT^!VjCXfoCbfLYL3LbTb1tnH8LwXTly!_us6A0fZYFwr9t@k-P?Sw8O$ zRBOR-2w}O59Tr?zvCX|%65!{jiJ%xqN6Mw444!r}^sq}|EXKnr#o+1}nu}kE>bJ&a zoH*_~l-`x*(jAFg{5t8*VPgf+Ik+bU@#h$broKfCy*~v8_JHzYntB$EVW;tM<9{v! zG06@h)v4ZV;*8;k^xA_U&{v|LU=b)r(9Q{le`r8CjYMXui7AEBi*}9EJpUSCf8I}w93nlcU_H(} zwe%3ur15;#gQ8IlX=ql@NFW7S0mAj0(vlJm;e;d?4EPqym_>soleF6Go*Re78<5<>mN)sU zL2S!}Rz#jjXME@=u!q#$x9Wk0k(*oqYL!1dy$dU~AB0lWV^Ds97Z5;pM$0x$PG?_p z#donI_BavOY?@A;2c0J!(Lz8|w?JTzI9M^55k?9<{lPq4;o3h|a1{Tg?+qYC(8uSK z5PwKk*RC_wshEq|`l=p5<1|k6c7W+vuuPI#8Ik)<_t&Nf2!1Ls7fGw}a7vIyat{dR zGQ?{jiu)d6EUAH0W8>mXrYYYK8!VW|mhrfH5$qQEnhy>TM!IJsGs9AO!x9TLhsXR^ zSh`-B);gs(=~ihn*|IhTS;yr(0ufZoXl;()0@)sEV5u4QJSI#l{jnbE+_K z-w+{EnCbvHm{z`t6J43(e>7a;ug=8``C+6$fRP#=T2GHI6+esxsLW}~gY)XKu3w~n z4*5d&pS$B-jHLa?DqY27LS|>|nFMeEPZT4}gpm3Jiao$?$Ii1aEz0F|n|W#TE4Q!8 z;AGLtCz_L2DF7%)3l#(`3-F{{sT``L>jT$sk`gU^e28`4qfvF8EZ8*d?OF58Gs5Qg zSw=RkFs4MKz`Z+z;7vfe(YLb8WL3o}nD8vF{5B^1^`8ntBIy)b;KLw88s&4V3LM4! zJMMZsO?r^nD&F0fOo;GC)FX8<+99x78NcjAHH2?olMORu^c6Y`o7)FIrDFweTkdy*sDY`^gC#5 zJ_|Lv-Hq#3vY?26T=1_=?nOCF!>i;A_)B3_|D4!|DfW-7W!0spu+;G8Ya{wcJjchO zFVEZm{R7XYe6G}py(cX)*OhgLSp3ev*GKRgpB*s=g)!WP>l3AGAB_a5^WyVwIj8Tw zjrx0?KBIPD24id|03jL!RtxT+pH?(sQjDL}u@QCBi(0{d$QAkH4;q)r8Z$^YR24$i z(a^kIw!PmYj|)ui(}aCnb$FjWX4AA})09Yvt9Be)$1m@qhqt#iH7+xRLA*Zjl>>t_ zKd1>Ayab5Iq@<**(2Ac7Y8E0RB8LBQajj}Gy)`3BR&T5RqV@tvW(*N@Uw+u-pcFq_ z+0ksMA=p%4g;-N9f@fwBL=~2xyv*-@5OriR;w@cV->b z;uiK9$M&EW%0{-aV~Ny*bc&aAF(F^Zv*!ilsRy*zBHn;v>wf4~xo4TrBa%@f1gxtE zTt_}1C8oVq(8YQl;eF56Y1~Jg@b<9{>oX1kYk_twR~P}yunq5Wn8N#2uhnAqr+t+* z*ALMV-4DYEbFduocB>+{nT2Qfk%*e-Z4ud2uc^r|U!S5^?tb*|c2?}w$yg)#!j9f) z;TNZLuFh^HK7Jn+;`U{g3GeoK9A4?`@x@7)#MOiUM;`T#Qr)(IHl-dIWrs{|8Xiy*!h&hcgvON28HEo6gd{uCg;by)`9S4o~n zOVamQmgYM2`lX9@MXP_Hz2D@M3y7k79Aa&u3J6N7AV8|=z6wyRRy-V8vHiaY4F?GY z)4x#{mNqr7zHX{lD3d8hSam~{%(Kvrn5-#Cowwl)+ctK0P{t3-jrCt2)I|(ihle9* zAB+l=-q9m~TFO&niopJ4k8h8>{8$pgp-MvL2j zYTOE8*38*RKmhS0@$Wg}K~CbHuY$j^b-&L55*uBaK#*-<9S%r??! zwb8?)=UTnJ2X4W5u2#oou9%II-_7vNTGNpjn{UtW(ymJ+v5C-{TifN`J@3Aq?5f8(IB4`BrYrv_$-0kmkt)HuL>mpfv~SeupKVx$fIbfUn4EY^vsVS0rw=zwyW{ z7zYHZ|KH>V41Ch;Ew{PXCsy5-9oJ1H;Sbns8>TCj=aR z^B(*;ZuD*SXwB1C6kU02v#TJJOyniZeX#2YHNl@G&HKMq3hd_3{H~aWCp(Lg_RGcV zS?%qTbYj;3CGk8rQ)C1q6Bze6lZu^kGtTh9fL;j(KymP&tOQ7axLZr`p|PeOdWX{j!c&&90} zJw+lG&xFB8Wo7DF)JQT4iu|u%!F>>4yrDd&aamaz;fXDQIR@f;P|%BXD0yJLh(s!8 z2^a)gepBEcpUxR#IVmr06;}`oDXOxFbv|~&%+a8#6(f+Y6r)030ERcXK^yfr>F8I& zVwYak9A+b#E-&*ppxbzKQ07=I4rO3QTMJGlD$oa+X~P zI^wttLkG4M>ia(A^bQO#P$0;-vuWT$L^6nLNZmI0^Dv!cW-?RE7Om2^(bQ>>INDTa z#MmtnhS}Nl;~H>bcAUs!DT|! zm0_EQLiB0hGyin#U_IdAjpeL2#gjsYNXOYzYv1_Cy~==p@48>osUp9YEw5j9jC8xq zx3CLN7IODl&Mg1ATW{M)Eu6O}$Z`6&0K{SRqrMfcZwo~57#WNkS1D5?EbcEfbf4+Y z7wwf74j9H_%jVuAHJF6K19qV`Pc`r7yS$c-NOxq#I!)`fDJ|sO!~Z`@2(g9ndU}%OAOHUvgMh6+>|+#xziIN@fTVV@m*>#H z=5p5uy@V$j7i7?otf*^`FLB1|{TJ?xFV_ic{!4TVIX>`DDp>envJ|@T8olT1B`u@- zEdu{7g7;(wbbD^0KN@%c#cX;iSbFd@rFCqUkQj0>QQSVHOmv^O-uP{PTND)dcejk+ zz*zfvLgBJ(3r>87FnAq{g zsm@dkFs_kG6tmvn^`p-E3TV9nkl_Sa=N~ptU;wlhsk`^MJO2la5&(?iu)y+L$Q~L% zqmo0Qg#pqYfDg6mG7Za8U$WyvShNiTHu#KYlD=jd2(NY|)b?2F-SWV&~!d zXlrW=rfz+;Ki74#4g_z-Z;=9RBZN_dl)Tf=luTvnWgk^k77pCQo+#01xl)Q40h+<$cT0nSa4qoH6;U zFbH*=3;=lg1R6SDne2`+zyPPo9xst96ZZh<7hOnp8@6W}*`%v(Gn21Rn(3u=xbvJ#JZK%MXLnDdTS? zi4Y1pIYt~j1YO^SM^neK9^`knTnvyOf5R1fxo$3A3)o>Ys{N}|<2@xI#xP_x_5Vlv z6SlOBlDxnUPCEb96|)6yNCX?hQjA_ULyt>9&CU~AC(oFF{~Kw)8}gp+^}4kHVWQ0cXaUxlORu&JJ$k?Y9o6w1cU=tkv{TOOG?jU`b;IVO z5pG(#!!{j%5^&NFca_lDCg3>`t|c;OdxYWTr~gw9IJF?V&!o9bDO!EYAYkbGl2SkZ zU-ILw#-$_5Q~wEoo_B`g4eDe8Pj?oLf9i}WL`8Dnk`|!@C50;KgYDn1T6`&s?!KZg0>S$7T)fD-zYzSR5a{H?@UFZ`VdN=<1B?n_0NUK5i=yn zIqSwOev3bT>*tm5hH;k+JtI5^N7CPj#Jp#ihc3)%o{nI+ov$F~+MGxn6M;I60oL#l z5djw4^g-cYTfC+YJug+5`es}36n8ao-j09stQe*Cw-#pR;a28zm1=7npwl=Hh)~`;pN5Lj%niI zadkn2417aM8uI_p`}0|MTY9!-TgL9f?!vQGpO%F7bKm>jd}3~Idv(vhyI9p^mQK}H zkO%La(di>x4VAMld-E))_wLIQUSbGTe1~=V(Bs6{R}=pQWlRi9I$^?(5j{6u@;55` z3Rx@xgZCNS*J^L4q(I=}_JM7WKVo0Zio*0O9r?mZ3$jO=2> zIgpUpB9L*FbPPGmg*4EiCZIknQygq3eC0z{{6~ElIH0!norVcTU?F`f&EL+XJpW*+ ze@t28w+aiX+%P83hGq!D5_4$r9>S^Q>95fS98CXE7fe|lwyXyLk9Mz#kFykXH^@#< z2CK>9%=kioi~*W@iZP{GF!9q5li0!bYCX0L+oq+{Qx3$iP5$^IaQ@iIiJRb&hY$u( z0mbu&d@xX0L_~y_cg~IvP}qpRmBud7t=*C;)9j^2zT5`tsy=_s{fVs5un6e#<7A+I zety801$ajQoUo3{R0qHr8(xt3QHyTX+1VK&E&1SFxE@ktVpQ}}7}+g(<{x->Zmz&w z+{Cx!oCCZjMmoAwZXi>EFhWCPMtdkEfNBrs@T%Ub?sv6pi9%$q$FttL@7UW&hpr1x z&e??j6LU`Rq&V>i63nes-MEO%ZB=S{w>@NnI!{{7x9-!2RJeE{q!FHQ$r`kP_5Y&# zFFs%K(;KWPBLrcvszZIdQf3nbpoO35Pzhh&qWQzVu$wy(n79b zzR2-P<;SVp%79TF=Hr*0P9-SS+U3!SaFz~;%dIz}sr!DY>4t~Z9HUqEy~D8;dfVB^ ziQj|eR=IHniUOt7V1CO^21WaGPkgg+!+@J9MShgaR(oCD|Z=W2a{HaF`kL%o(`4&@9taymOS%VYE2xm0Z{l2iz{_d*@nem={m7>vgF?1G@0fOt^k+O8w3!C z!qovWtKD|zZ*K7JSwTyfKrs10geiM1X>|%}o+|+&Ggj(wEe}&f57);Xzf+SXYXUN@m4!Z<$%I3# z3HpBpY1@jd4;I0HvYS{G!%y89Q%)xzC76N`e(GBBWjo{9R-py|8R$CEP|#;DU{Rb- z<*tsFSF(xgfm!GXPS6q$9rrh%Je@|2bPG9@O~Hz5eq5&tx<{_v-*w+zNlyeW`Bs^r zb{(cHNWo z-`Cr~+M{qkKMqx*JpNnPf6iRUds<-b_0e?wdJ;DS1)M@9BW8GA?Jc8wS z9bOUS{5T$_W5yJ+SRJmPU=%mXuUO4C7+-4fe|8Muw)FGa)vNBjjB^ydh^1p@matxo z0)Zg5Z2u<}z^7Tqm#Y_F*RA}(yS=1+eU!BL+#2M%on-a^vx|Oqp-q~ljpzFjhmL2Z z1jPxv+bE>&z$r8eFEbXQ+g{slH}$xrXc2}gCyoEnBrFaZKU1%FR9l^hj|6a@(aAc9bt2^EO46ridWQ&Sw-*&?gkD^<@W=8i!3JvW(}9R01617*OfE&gU*ku!4kw z5+mI&CfLBc5>SCUTZRIiEpJ!$-rk-?MV~;;rx9RdqYp4+mI4s43evnPjn@}fa%2P_ z%z0hAX?#yfMKl;*Z1eo*iaCZDbw+~)+m^muAx{@&Ky1Ik5&w4GziO;)Yz<^QLzAGu zsKr7C3`2|822d=KOI7+C19STmBfWOhfAupeB1+{f@zjiOAw%^ahXGPojsA1B_Sqlk zGH~%VHUr|~3xCJ{m^70=pLM$*|G|yUBhVSiCK24tz4o5l9~O!2F+hM)3kFWB9rzEg z{hR$tq#&&@2ODJD2$cEmwU^%5PSrkX6j3RHFjPg+eYv zZ2XIAKh5PjM+09DPUU<=!Jfg7nM|QCynKPD{VUef3{cE>kky-Dc<1BB&C8|h1c|Py zSi|S23PwLq?rhXraqSacTPO>}6rt@#x0rV_fLOjFZO^7b9L+xz1jz}!@yUbnfj~mf z|KQ{|Cns$;=o3{_4jM*WTE1V_Q(5_6T@dK}xLM7g@DsT(JTUDp5D?mDOxavN4L4Fa z<9Frdf2kc?UPV+0n4T8^HvivLO9sgM#8#X~;tu91=twi_L=yMcZf4ra*XGxLI2Zrb zw>@f$KY6I$D!4oLCZ`f-yz-~0q)Szm6q#@}Sa8l|hy~Nh*p9c((}VrOZVGht$}|)2 z$o$bT5Q_U*U}k@q=iRZLYMKn2Y~H?Fn9@G^tb3hxn65zgYuR}EC*jtEXo$XxstEP- zJ9_$9&i_zVMKHw-;ISKkNL=)7L6jLBB2$blJp~+M?8cDA2#bbjo?@#fYJoQn9~l2V zh*Ce-Rlfzo8HmWp{!407K4nE|z=+T3I$aDx1YO!q&QE;tpQ;`A7Q4v(%jCNDae50~ zl8G*dkYZLB*Lb%K1ft7P2Pp)3ER)$Hg{f;rk@_QxNad^BfInDoVq<|g-c9y9>iiAU z9qj4%Eq9;?wHPU_8Dw!`69oZHGC+&5&Njm5S7caU;B;{UV&m=pm zG8WH8Y%A6;LDIz8Vz<=Cjbkreo0TIc7)sM>6@2;^cPR%KRYD$oJ*@AhxXXCsHA=hx@ zlt6;0$G%eXFTyQ;KxXsnR2Zj19P3oQOp_2gW-)_k+(?e@m&8b}cWR1>@W!C=8JjAk z8fEi*DtBC~hclDAHRG+H?;9 zvLOxQ$V2bO=g_8VaBvVvQDy${dP=uyz_o3{!6?X(9OMtyN4+%W^R^;g#cO<+vKh=j zrw911f2^HOe#Jp&Y*-1Y$;2gYEtp6Me5pSq|8@-MnpVB-m2RSTWF|-aWdXFG1Q9~P zmi*ZF_L>^KM1th}Lg$48&ZL|%EVVl6@@39j>cc~B2R>6>rK!NSnUX`j-?`FP6vMRp z+Fu8VWPkvP14~C77};a#$*-|+En^{@g7NT&IGIqjEa2PoIW0N<07s!pOuPhhyNu<3 z@z}2=X980tWsJNZ94GSgnScR`0f`O^aKN(exe11FLo1v3%sOfWuR2b0MM`n5$GEfEe`B3ArqB?Yd-CtvQOsgYMz*jT<9q4WC} z0ir5sEKdajNa91uz9y-;_s6`|7@G$GcUtp9{f~4=h^i&kFKB{&aV))aufY5H5^JWk zqEsMmLZNI*#&*??M}LA9rDt|__U9wTkcI(1IOzpj(YYLW@5?b#g@N5y+Am_MC{V3} zylj-ir4Gr0Gbg@%)!Pst!B`vmv0~9QR@b(#HWVWN5Qi zH1uFebxs~_FP8w$yY_LBz(NVV78&Sqm7;K_tNM)o#-Efz5ffCP&$iW{BRq2cwCF5T65Wi8_o1C27-u^Z( z2u94Cx&6D(IW#8lUIYxel-#n;+H7`p5-UM0z{*Gv>LG~Ox`bM|&?_}wxpHS+^2eTP zg?%h+z>X-~@(P2DmmRbPA8=m3{CPO%Z;i2e(fH(fwEXaqKJ#~1B1m3alJbxe5fK5e zFTP&(!-s7YJZY~F`je$UFYYuX#Iet?w;65mz+dW#`J|$PA@zyo&3T57H>(u^fjP%Q zBHSV=XvS+A505>i@as;~yDC40;wR6NX0h95zn`12Q3QCXwctAxmzPmU5nZb~Zj$uacH>HSFKv^#BV z1R-j~PVpt(*u12JSAO|FzNs>(52#KkSu1E{O{bRdz!+Z&aGZ|4^NNN*;tXkT!?|Mk zN~>-ETs7Gk-jml$sSeQ6BOo9KU8Y%iXO~1D=7WN+eQ0qcjz2Vl7-73O1=wHYyc+)| z$)RrDG}}Xy*t&@A*e!q7IaHFh6_PMmw}?Q`&ks*iKsggAnunv?pfs6eK!0Ix1PZ`&q#&9j;n)?L zdiFt>AlTfFz8rZLGk%+oFH>5KxsGN!4^6W2yX7U_H&R-7^68l@4RW+0xgCD%H>3-$ z`eF9bl!*-eEtDm%0mGs!GsPETH)IH?TR0q`klFgQ^n_qK1 zcsf}WN+QI`G?!Ho^OY98T^O6jBNqsmewP6kO?=gBdBF2x@<~_M`TiGDK;v4E0ao)$ zz~moX@_?Hj4S<0BHp3{DZcdk{Tsi}V2OfQDINjc3RLXqF<;7n!^xNt6P|AFsTNv^C z%io8_UVZ=X-{9ezsD+*H!|fib|IS0;zVkWr%LVs?3aLQY0tAb;`a?Q#doQsyLsSD|zeRo!xm6#~2JCi% zzRS%tNpd{IpFZ*CDg!k=Ve7@=nR2vl2C@O_AaJ{9;Z*{~f_9=gih-HEbW!tP9%S8(pt8-m_z4I7B-Ah?y6X4>zr$i5zef$YdM;Y;a(U91N|uqy zam`QJXPsYackJpudX%1NRNH!ujP;l>?DjqTHzr$v=D8XMxyUx^3wJTib+8OtKI^>o zbLjWR0IHA&iNNRtNHB%?{jZ04cLedf#fkAQo0`FVBQC|_Fs{#rJ^yC&cAjpk9?qvb zsa3r;;^A8wrjlR~r&CVEru}`t&Y=H$_pPT2idE*{kB8;!>kl3aBnkO1Pt$V~9XFZQ z#Qe+aeqRpGZ^H?W0-h!)mVI{MC1rR&mmeSUYnC5I1~CUK1kd+VMY`_}T{Bcl^#WaY zLKLe-uGuY7=a`xJ_3}IKid;pn_U^&BiNa@u^i`W{dpo2S%7U?Jx&x zNG3t*q~PGxq@gG2WeB3Q8vVzwLGqA6XS-!g#0~FY>#Sz`$o7zGa*(P5D2#1jqV#`Lb2o0YNzvgH+@^Ne=Pewszj{@S&GcNMue*oacsn*sjuYG zUS06Jyn`PhUp@#|moeqhev~Wh10Zd)?$p^k@Qw;U2VG2v{0oDs+-^cex1yGw&6HL4WTEy8Sl~%VsRbb2$C;(KBx5i4;3-?^)lC z3Ha>g`*N{kcw$8jf4AVe-E3CE3Ou^)v>5-&>Auuuxzff(5hcTI&GVysZ!q$>$qe=z zC8%?M$sgUig)r_lJH%}Z1GKXSrp~PC7JDxk(a7Xqck8Od%5X+kJ)(_ z2|t=CQb_*RG$wQr(@-j)hrYkPx)XIl2K4ogwVyTC|H_T`sj8yB$`}Pegw7<8I_8;o5OOtxn8R3 zc&oWiO!==Z=aJ?Ip#qdSe+>S2?alU!Vxg1GxPhlzt}lOW#(_vd)VBOd^@z~q3K+bQU^Vh+FMCc(2HNhdRyl(1pO0hfOuT*!d&0Re-1&8MIph|ux z3k;HH;Cwe&({XYurq9#wx1;CDxb99oxvt`$$OF&jigH;GL{@IjKFz{0kIu$kF%NJD_Oa-k~x2VKSYV`QwC#&@UDu5r~)l zAW9JWYW*^$IN@>RclXNy&BH)+$_Os+AGhVZg_B!%_kB#Xo!0E-0p&oiMeMT86gY*~ zDiT4pw(zI2`|7m;p$N?O_o9lgtnw@}&JOiRuzc?B^ytkpSOss}P}u@(&cf{9kgr!1 z?t^~%Tx31H^V6e820fY%2;2S27qk_74mrzM>nxw_+8e*YY(M9^-e;Hf9QQhNWWR|O z^R3Ygw98fH*fDs%JIm*{m~TL(a2_%lWVt_FlvUzpAak9CMf%^7yj-loYZg98Hm%SK-fSYFwSr{iWRLJJ<9; zj>p{Xyg;*W-JL(}y-U)HtNx-7^xgAY8zmW@is~sg(?gOt$1RWmNJtTz@*NH zM3oG$i4U|FmZztIo#@niadh0CQ&v`1ez45(RFO>L7YKElLLpKRemxM{J4aij=|l=N z7nl?n5+I4MhEXsvP)Q^J3AvDMY5>;cY$H;5?#QKk&7(HmdOV$ITpEHXz^gs5Lh? zR{}y9K_#!wg0EPrAtEB0LN~*M#(_zl^CIh3E8EY!w2(0dzexT?ofHKXDzV-a=zGHz z%K#9yK-&E;ZBTn^>2AI}*c>@XeSpEt(ARBb%}CVTLes*m2gS05?B>t%d{G^UN8n`! zwQ<;;H01xz8laOfKLW<}9Y-yK=xxu=<)dy#Bc8>t!1L9py8U)|?j5;r@9)8}F9=|e zn&0t0)My>9H*z9i8_^TRy`7g8_4wTq@d;xK$>x8w00h=MY3p4bg%vL2XkxS=i89lP zWB2~!&~<7b;x}u8u>rk3zD9SezP<*|&s~ht)Rb{VNJXCitPB^lwQagnc3|ewbQXsx z`+6B?#xWrVmC{{PwI-1VK4VBAB?`YDXANpD4NQL170(58VG|xdKf<|S(f46p$a)T9 zZqHIQ%bn`WQv^!g|KcN$mm8n{oScw7jeUQzr`m7xTL}BLWArfk0Pi}3i*=tqZnfk$ zPuLqh&onF?ktk94{2pvDx0Zb+2B*v}7WTIP8x z+ikELbvyTn*1SBPU0S|yj0IesCr!xP-IxUCwVHUC+-j@>AlV%Li$_V`6q|;6B>98w zAs4crSfcs9cOI>L0K|!EGnxS_XxfIkJlVP}zJh`4RY_f&mRhPlTcpXZ8CSHbM_7xO zL!ulluv)4nN~TToZq;Wai6~@v9r4ZGKn135Ra5+_6Ugs|G+~0QvY?@im9cX?RqAD5 zOVB_7l8E94q-zgfth4Yp^#@{!Lhn#7wdJZV-fk{q#~YSu;z>({VX0?rx`(Y5FacBB zU7+NlNIH6PQmmWQ9FATzXJt^en$xQwhAiUrS2mTRsuhajfy|>=1q30YpTSRfE- zE3AR+K1>^{vW$^`0JMb-hlzKF$BiSwSKRG^;uBVC8?)kFFRL~OozH9;6)Jz#Ai|H~Phtdwu zi+tW^yWh217+Q7)gImZ(G#E#|RyuSRKS;M+V=@#jYceDWQ<(aFk?=AaFqrE;{+z$E zb=%&x1 zMsqTEU;?-t$FRN%5^d`q?hYO8+DVN=Bup zr>mE3^8<{@Z?k%RHrMel{ibYy`Zl2Bpbe%jKf}`~fQ=V+68C}n&-d3hs>D41lFo3a zI8)X8IBFa40m1Xnzxh@!G)-cgejKnMP$q;dOaNiQ{nMv6WOn4SI62)wA--T7b+F=1elAa#Pn)Pz?$-}3-04l`s zsSN5cH725@sFL#J52ebvIdZ=UX<~{P6#~iL-^71XO(HA_Q4K;?h zF%l4Q1C15~nkzKiPih!_azMYq}@`|O^{7V-M2zb-B|?M>IKk|1M8zx~V`)Q0iI*$|DA&bzJkN?s&{-Z8ix z;p&0Mb>xiGTldge>#mKhvLuR^$z=XVlJ)M5hZaAFi6p)-c-~8o*2_VS#Sr?p6ZgeW z4f&m$>&M>QaC8v+!-9FsTKj$OJ8~auMQMnn^xjd%`h_n2J330x6j1b+w&L5LK^~QJ zwYZqn_N!-{JeIgVP)^lI`=sV}Z4;)K(0acejkNzI^f5c(Wus{g3uHv0b0Ia6km%vG z{R*QiR6~tDP9=)xE`>nZ=NO1yxCt*KV9TMbBYVR?szSJME)kIT-|#G=8glw~BQh*HnO$S8k{pPye6S`Yziv2Sl_Y0+mZ&Ws7~2mT@2mBIZ*AkB#d z|4To0uX^vA36P!bgFpZbQO+MpsWL{=M$9io65a8Ba|6F18B|V=EwfqC)Eyh0Wt@hz z7D*E1;S_ZQI2ZZ9V}={$z6Tle+7C$s1~3n{pVJnX6lM#u)Gw6ak2AmCw^a*SPt(ru zaA%Uw@Ng!ol!4!c287e98E66YCMmkJ?56;RL7fJRIP0ukvGBv%sLg42-jv^eEkS^Y z6Ji`|oh9mVs6E00I9?>sx)i}ZbyZS7i690ugyxcmMYZ?FmDm!0LC77$AYvzFv?(_c zFh4XF-H=U7f8EnyVyUf3y)N4yBpS=W-F-U}7zi(dUjI;Y;`=w7|Gb%M@>{FuLM%{y zodADSNARjqDDWbV-6mh?4)?}`Q1{>$W*P*s==L6qz~JsfO@T1SwSmhrw!A_;2&9?q zGB812oWZ8=mE;L8eW~BJRk0{I&cotJ5lkvIa9Pha$nSRRCW>c4Y4qQ~I_~!7BH_a2 zowGXKPI|BJJ!q-IzrT>OJkZ=!^6ypX%YFLT7nNLJ#R9qeLqI_^25XSHYRlz~C9X2H z5d#$)UU(jf&c3p{^>TX$=Sa5VR(Y6q5NE90XZyVNINag9o(cvHY2b_1Z?0GdKK*<^ z)n5(_<+49>q<|W=-_PnO)>AUp?aBH-mq^{Uw-{c)M%EaePW_u0#* z+8XitqEFEP$>4oAnM(lhRq^2W+On?_q5_QHZUK!xh>N$l_!AwE9dN9NxwVh!#_tq$6NX=;N6D zP9JvI3a`3PmvF4-uE*0x0mk`dKwl0Wd6sUni0`ez*VPQcw zno!8YjuxjU7Oh%yrctvTrpoX^6Q<8rvtA2$A%AN(HZ`Tmoi8=nj=c3HAic>-c1ESl zi#qH+5tdKJ(?NkWL!n$1sw{2IBPax6Kk~E~@PK+3vcdk6k<@9}dwtK}{RBLB;!^T0 zN`z;=JxG|1#ME!S)<6)R;045d4Qme352uuW#Q`sRl#M+z1ca$+ij0iKk4h;iZvXAs zxwarp{nyCcx`x;@gC*B#(O(2OA{ZNVs~?)lL)y{(fdCAaAS^cf(Sso8u2k%^npigf zMo9eW%9qROPw-NOO&$(853%L1LDaFxOW8s1zhBz=F&}YW(zRDlnEYUbKcnRt_F8W= z;O5U;h0L#BMWDd-HLd%>g{jz_r--n^skkq8VT0>sp%Sk!RK--(w|Yt3O8-iL+`#zX zllWvx?_`#Bg~WseU4#Ue`#u&Qw+P%mqJ-4u5;}$DpGLJ$o@%}a_$i;{qs17CJfFj7 zorasFw`oV;=N`(njQl+H_R`Xrk;uW=9Q2&MUw<)B0Xm)qcbz12`CfdjSk6yri89<^ zL>=`I%AdwO$xu@;N!g{8@6tsFFyp>$xorg~L}T1O4wex~N(k{k6KqyNq;&J}N+C&b z_%gSBEAO9Zs|z-xtDkFJT8lnL6!XOKQ?;9QmqB3_%b%rZAIR4jdIUGy}*=DP#Z{ z)K)!GuW!#lDGy-eJUH->*F-kGbVm1%6GKH4pUMSXgX(qsa8NAgD@o%#nC=ej zT~wZKi*tVe{35l!Y)tl`zL%HE+1-CGE<{9!c5l70UT)@FNY%XsHrhtQl!36n4Ij$Me5Bgd30#4^@b z+7N>a_hJC{8)u3JnPF*jXc-AK)Do)X%AEH4I;`JEANi6bLX810QS#N+>{tA#e$zh# z%-fZNNmHN1rLtTBxHY}!27IP|h=_&|ly3*Xw%^JuVoh2!Usevixl!_lGV|kby*>lp zWQqi?)`I&0;dlcO_n7hRAMSpQ7HxPp4Xc0koetGIl zg^pC55z@n9kRAalU}jyo<>90cse6G$h8|$)cslLx63!`T$?xKXk9AK*Q#DywH~%|l z^2$BPiWpS@>INVs44TP+RjcV4ebhOpR*(qyJxGrBbr*#la4h`E3Vv~5RQ@hN#G`i} z2MimE{FXqR`lr$`P+>jGLCik(Yfx5+38N={3NX+%n>WQ1g*JQr;wYN>UI3iFT4pES zqNUhOgxjznma+)!vA5^ID*z6y1OyzU(3(8WlLTbu%+*53~uB6J&+-145mv9Qo$~`1=32`9K}K;iZWJ z_X8w@pdj47>d)GiU;1aj=QRV((n^db2%y=a*vTq2yzp6ZU}daLMtg`A9mLTZbcIW$ z#EAbl;>P&R0Wd83uLBVNP9J*}Y2w072^wpHf+SjGjolYj@PbDVnH)Ry4+NBmd2p0q zpt)qWui9+a-B<=_M0oW{g$9iH{!}{d|Dx-?qv3wTZ_&|7l!@q_=tQs4MF}EG^e%df z7Tq8Si5fjh2!bGb5WPk3M2lWWAAPjpzTb1tS@*8He%GIt8EfYAmgm`fKYN$`&}7GD z{QO$a?G;2v1zV|VfO0T-*h74AB9vPNQ+7(&M;Rq0W7ILX2G=e=>!Ehl;Ur}R$OFkk zmPu~oIs%Bi>~9X;xB8z9Nx8B=YEUd!aj`A@FKYjPeeEaXQA}Lrd%KUmY85&qIEy%? zs>bkleY|Xq-#?0CN*lDD6EZe3;?(Q*l2Ub8x%p&0;b|Jap6~MM<2&X(g&IL21whL_ z`zoUT81cu$Eav*LypVbqGXy{t5nBNT+H!7>fXRS+_$=cPpT+u5ApeQU$tVQ;Xlg2% zGe^i}(4hc=C#JRK0c!IVSo}#>}PI$n7?XIs?79=dE(D}^_;Vhj}JE) z7s-QJq@J!W=965h__B`)H7`P`N^oMgu6z1kY=0s}5A|fgY$JI1p;SRWM)%5x880CF zgIDP#BmVq4&JYGf7QBC+J8qb!gnj3~xJVwV2@0(DM=+dRv0S3h{nlf_@|&ul*Zp12 zCFa9zjH}IKT>WHWiRCfupkhN(8)RW62>CYSQKy02{vy`8say(JTlq(CvOcC6|C_|WNBRzMojmf)d0bM7ocor)VNiL&3et1;x} zPhsvCQpdl2Qq4{kyY^&CRNIjP8)C7AmVcDUY?%r%KFm{znS*3WD$S$GCVqcYCH8jV zH-M%FH!I1|lQ4kBWcdf&4{S-s3A|Mil1Z8$gfZXNwa1O+^*R3VJhd;$Lf%wXd{i?pq!&5vwFqs5aIw7hKxZ)MUVUkU<6c z;nWfnoM<%o!KjK7f-5ikT1T99SX!#|qzpMx5{Py z)MVfb{HDQV#68PIq{(Y=I#3#Z(`v}c*i19%_H@w0v|f|lBBl)#1T8JJhPMd}U|9gy za6pCut6}C!(=MFc6jJL{%u*8S@_U%}Xa2_c>d* zZ>onXVsz>F*ZEtom)1C7FV>Nn4>z3oqq ze@kNcl^kT&6Z0$rRv;*-uI}?neW+}eeO?c3?;zPpRNnW;D$b)@4_~ohw?BDQW{~{+ zWHK-}qbrwydQvxAqaOO z+_^Rf%F_>I8pQVKFQ;yzgKh@SJqhsev?kaV>&w+3$vLR~{n88n+bfnDp=Tw9#i2ys zK6a?xDTh9N{9cBNE%YV}-_py$*WHfUzmMq7PDvS-R6-A&i~^9u$oj8s_8C1?<}|4Pd!@Znd$K7y zo3Ax!pN-;MkH0tz5}OlWJYfhydrftKu6XdLdSp2p)?Q#PbNA7lCdF9?t2#Pf?{&rr z5m(#+G?w8dz1(R*A_rGBvl_?KVLuRI0}cshE!{Z#jIG%?C_uIp^RXe|nEa_3+x@1R z+c@<@A4u&0#q?NUgUR9E9#})+U;x~-*VVy+QuOTt=z&n}y29dQ(cr{0)B`1vgiCtO?g@XDFjTh90S{D-0M`7GdcR zP5|PR66aQw?Y4YJ-{eCYeI=h8azOfW5=`jMIg=TFmY2ctvdgfQHrFBfki@y_WPlfv zjuTF|(?~adPOGg4V-9tVG+GsYD`JID{gPt*g#cxaH0)n)B#oqJ&zVXRD}~bc+FCDA z4~8eo=K@#RYXMlQjasasbcR6l$AS4alfW_XXKd3 z;Vc?6ox$IYoIBVdHi>_3y=0_e9s7n&>Y0*WOX4!H8WLPccJT2$+er2^m#rbnNo0eY zpX=iNp5O7g@v98avk4iyTSv)><=ge=NTceB4fJ+1uY*>cK%^@fd1v4$o85u1`@~Q~ zWLD5zUiuA>sVU{wn|mstYzX}S$Rlu}K))6*vvTXHA-+2Mxb@P2NW`1U*L}V)5=RCr zuld@}4k7j5Tj50Vo`?u%6kT;DYM7sDe>z>FjS&xhrMd5ekiK6xKe$NSxtBRvm~?omCIQTR`8C$^oaHuB77 zHQ{uN2DX?J0sCIPYm9T?eGNl2F>T-G)cDLJ_Tr_E&Rq$!iT?kD3}9q;2`7z*<_G*A z-KX5hz*+H`?-$OWse^8IN82~zc^l5YG)(?8vio{mla|x!Fn+uEY~r!Bch|$Y5G0R; z|Lq+-yJBZg+9{*1r2bhtFXvD@^)yaw;q{ zdWzQ#)AT&Yz~$DmSDmNr)Qr*I?Sh+!DofjLIQDewcHW#X%^>J1N(y;DLbZoLQ2lp< z)GJQOpGDGKqTzOk>sx=oY1U-__TFjUTZrnlb$2!Q0J|0U%KP%Yl9IW)u)1vk@8fsL z`bs6fXWDrP0gVfD@1F-&;n-f@-fJt}Z^qrTbOb)7`UB;}zcD~jQP{jWZDm$D_N5uN>UDoJ z&hF39CmZE}qqX<@gPhy1EPh)r7Q8GsAcQh;J#b7PNPZkAXRrEVrg_%;{WFr!K$4h!eEvQX+B`5xB{#V*1Fp>Z6DcI1F=#1fe zeo-aLObG_ug(U)3-$ihtOz%wD!U4+u!k*?e8r1Eb%sW$k-4t!S5CPWLoGRfSqrJ~V z)}fswitF+a##zHyz2XH-kH?SXO-H)~qQQoJ$;!g*dwHXSj!#9V3%q6dx-Au$Xb%nq z?S{Wd1$c9&P)HQ2zt#nnVmBYtqbJpVr(3Nr%^OU%m_CylCfX~wPDA#ye(wc&EO{C8 z`o0^!K6hQJLgYuc9a-p)H6G!}Nc+UYT95YF(v|^3>GqCiU_&tYdf$BJrz!H#y!A1v zKLzP>EVhwzHElXjZ)ViAk=4OGYxk4IwkugJeOXKHaB~Eeph8>6`M%twBKWqk@-dr^52Mg_xr!6%9Ta$Ma zt&jbRs=-NP6_z*5NbGzUva>=BCJYvUpKFkIT0@`#Um57h_RucUB9*ME4(CXA&ja#sUuDuED!? z-TE%i5bzlq`qiqvWbRX*y%?R6 za&+sH8h0D<+Wje=8SEW?P%42TRa#GTU6ZyPgeV?uZrOOftW^&48188cGH!9&p>KqB zEbfze^xPX?w4bmc437HX6#-SV6^)h}h$9Rm>Ij*m^TFfS=K)epP4Cga`UKZqHf^Ql zm^N+I;_$vRpK~S>XvU#CvGke>&JdNl8jIKn3Ml+;86^B%qge7(ki3Zgsz3Tl_TxfM z@R|J{mfcHzAKgtuaE}M;Vpez<8l^<-HLy&+ORGU`~c6zGQt=6;}44H!p@D=#J2XnTi!^H@7_Be<95uuJ0O^uzqk-EGKebfn z`?t2*$*1zZ^uc-bAzEkn*pTAFqic41#M(>$fB+UH;!oju?3*6x{D!!>B^l*=g@$r$ zm^F{%)?b8c8$PJP0l_kk#UPma$k9{yEOJb|i$-2LM^x=YTwGkLb(H5Jb~fBkj)A7P zTQbBUBmHHeNu4GvxZ;VloAuw9PEJk*Z{CdBb$t{|Re%37LkJW-o2OTYhuP)X*@3z3 zVOiX2iQFp0uZ4vlY5d94;)Xg5{7~F5{~y&M?hl?o-dTso|M-dO)?L0m*kww%E%#|c zArGQiscYi)F9*HI%^R-&SZRn|{r2OBpfN;^n!@(?ZUUXIr0ji`iZt(li=Ov*r)zjbcZ>E?pBYVU}X{IOo zFk~}~Zwt0P_ZVcu>LXc+T76glejJLykO^phH$Itp5Qg1`4}lmKa9Ewk&zNIEGNdm< z*9#S_3u)Z`{6>@y`gYp?*m!YY$z8jwayn7{hgk4Jn8?u<)1oXQxA+Zyp9;UB^DW@I%4li)3yh9WF}K;+qGn79%HX`h=ftSWypA7P9l% zKa8N;>9J#gjrsMee`0sOX7n^lrS}-v56@G&kf_|8K8M|n%O;&_NV&yu^8>X>{w$V; zOC8ZylgxRyBA;0_!IodgPY6;c+seMLMn5wPcHWcL&lVD95?nueC?kHpX-RZT_|B%q zZ_!flu50hGU!&nHzRd($>V5b2+YiQ~v&y+5Gya>@d;eQ%tfgT*{%pu06qkkYD#3ZlF2tUgKYZ#!>-r**SxBP(VEi!XCwqNudjV$Agn$J zKNaH+H4le=QphVRV%x_hlYaq(l}rgQn2A5gGvc!vQW{1R4nrjtJO;Q`$}w_8C4>q;aX<7VRDcvD=bvjh2&8k9 zJdlSnmJl?LWhj@@8i!rABCe#ZhU&S0JPOOxhmv8884;}<9=_f7d0HanlUpuFQ9u$7 z0(Ejm1F~^UUL@~iu<~#DndNE%&sbbsbaDuO7elxz@j1**Qh!qD@G7Ga^Zk#1XY$OC zt6nf`^XN5b(GAs-m&F}bc9kPS&+!0Sgc=KZ0-Md7=9(Ib9Ik&O z<@V@MRVXH)pdK?p<$rxo60|#1!leY9jz}hIUIO8~^sB)-mC`EeXNWv5<0s#r1qD-l z_=>6AgFS1j-LWo|T?e;bR*X#g6)+T2GisThFMYX99Y&ikbjahR6?o3`CbC4cXo+gx{jw(oV( zUmW_o>(CB7bV%FHl>P%+@|S=60vIvv#W0G4cIEedx4Q5WgbJohVn51$>`|rTdswK` zmiul)Sz!}3mHAt)#`FWDY@%keL-dG~#8zCI=+~=gnOK?oYmNua)nTS|{uf)}`2;?F zkwbnzgeXKNWKk%pBxaQf>jw~pL=G_%hO-v`W(?kyb6%>8GeQ{#Bq}04ra5bsP*Rr! zA5UA+X+I=RNgoJZMx}kObeuNp$+M3aZ`ypf3nndQYeX-TC+e)q#nz}rZ!a2<2xFhw z39Ftsq3A-PO>+fnm7cg}Ip}4!GNqLX-v_)AsS#b>T9Kf97IVN%H})K$u0TOfTo2ayGr{mzKN$cyoR@g{C9 ztq4yZ62){Ohuv_z#~uy0CAy_cFdtZf2|xZ5x@fLyVz*ZuYOJq;vs?AggZaAFddugo zh4pWQqeFaD|7S(Zk2P00j`i9@X_njLn~zb*Sl_NSF`H*Epib9 zbck&FyK9%hib!g5p1a|QXEE=Szx;b!2CIicW~p=hw_y5^&wrY&dRyI*ufJxmTycsF;16W#xzgd=y!~}__WpTJ=tlGU{POR;cw^HJ5Du`r z8cT=+;Shh9oll=6I<11T+6~u0&CuU_{;POpc-A%Z0HcuSCsIGq^?0JJ*93N=;HTWw zdCI$VJbM$j(vZ>?G$g)am89FSI+RX_Hc9gx*OMuY?rIp(o8gSGsAEuv>)L z-ML(wdEjEsb>R5r)Wn8{nb=N4W-DruywL2oTj(FE9q*8mh?!FynT;oe68oLhG1|Vz z@c6ghn4_(MqgIEZ@#=cd;T|MKK4T%wu$AKc#ps|#!r+x<|Lt>hatojtUeAn>f=H0a zr~lcQ4r{xvdFbDUjNM#h;xAaOu-)ch!Cb=$a@Sg}AG!BNsHD*)J4f7SPLMzhQ(bTj zPf6oegN+J)CfkTp#X6Rh6dN%meBpENJlmNhRUC$UfEz;&`hxfr#XuI#RPjoZE?z0$ zet0B9*r}rBLjE<`T+ruRoGS|mB!BA*nJjU(y%5-FRT~gNyuQ7*Ae8?vTli4A=d5KU z3o+h^pCp~~gDeFmOG7>BoO*62z?}eb?Xhnbf9fb)t$R5K2oDZp+78j1Zl%xM1^`wLcaOM?w}8R`N@7+q3`5W zx-Qm=z?NH?Gpn7bkGMzsae|De7A9(~rj2ADGT`dyV#)FIhH(;7 zaKSxYT-NiHk{^cap1%&h`+6kveOkET4kPFToskgL@TOrJPJrn$Udw|U!Yx8{-B5^+Mg!Eb{=f9ZJcaoqL!MqQOlnFA%*%nPTQXv*1+vOMMKh*F1;}y1y^2cXa zXY+JEykgfIf`4W1-lSG8HQV0fEo-rl&Hm~dx$d7d7cY3u$|}1#TrotARFC;g6?uEP zx%^eQb(z;rp$xdEdRr+-<%kl9hrn)|T$;{Z-O+Yo*1=L~+sL`O(CcmMXSc z^J)2F-WYbv42*2{A1omi>d@p#pbsDT$`M?yA^dWNYe3= zoRpMchhjjgH~BurQck7{F;(Zi^YS)K-Mo3v%s*d;_6>}uxrE>`2H(stuO0hpXb>qa zfToOX&_hj44Rk54=1PRgK%)%u*-VU6h0F6zb*Jowz=&tGTd?&f?iAHNWSh-kDqyd_ z+<7$Y`#M{*AW#7F)kc-3=D^bS7!Tkb&ty}XhVBS4!oyqNLo;^T{Lm*X=eM)NTx z&y}7X`;V|m<==>3__hsn!-tJ;nG&G#$*L?u9FK1E9gKip6P{(^B!o`0e$zUN2El!; zD~^la;b%bo&5_E(9vyPBYEg^EL-&~8fH>zCqZRF{VGz=r616xp6FJ<+ zlz{6Yi55}t*uSR6)5^dNw^wa+>Fg8zXjFS`{Xg4G;Ne0e+d%nfUTeoBQHz()42UR_po%{%!;mJ#zC^ zw@sA7x9Z)(_?(MFAM=*Ibq-c4({MNIzzT>wX8UI(VFv8J8(ZVt+;e)tZOm^!o4h=S zIyZKUlCUq5Wrs>yDbVRFKyChwO~g!A7|l| z*(=YBUgCp4!c^mM)A{GKtaVC%`)?0Plk&~0fI7@h`nD09h=Q)B1rs1kDg9L$w~a1#!h(WM1P6J)2$0mxBp2SUtJc|Z1^Mn)-PjE; zDeL{E72qoOKkxRbPnrH{_{7qNB)8wX)13zWoANuuMEoxHG%h6}rr&O+I3d5jPliKm zUM2v{BTKcQvV|wlrxHgGTv+HJ)bCMg=zE7>PYJsCxNJsG@udKVEs*}p1*l?7XKFu! z$$14pQ~`<`5YOI4-Ps+pc)ty}-w1R6^XS{!5qky7#*z|nliC-@)63A6U4T}H@y{22 zD@ePL`b+L__uon!?d;erbrP9pyg!f79R!#ViZpi~THvzC(`j>KKp^2)7NJZr4LEWP zXygizBo_IPaGctT2E=1%=tDWY+!(ppF?~(>j|aXGI<$6Y^olDy3WeT(kWnw%-i``| z+EczHW{wa?Wxk#->%ImUA=D2ct)uSf;UDX#f2#X)m_uh&D7qxmE)frR#x==m+fx<>~fzM2f(;O%}$RVwl?6fJtj~J7y zJMOg4*~YftvQ}Xu$L^fMB1;0=O<{|xy?4KSX95qN^Am;>0v`16C-JvSmb@aqCHF=xA0}VWu4+n9)r=ccjYL**%3(MS*{Ve}ELr?` zWJee-;9&2iu-N@Rs*K)=QTS3`g|iVlx7$? zd*>hqP2KoNb8e4PZq!{os*(1vov5bSl1!|*92+G(QBi0PrnY2Glc~*JP`4OG>WP`t z!LKvWAs~tM*ITJk2N##(F-py6MG5ov#UOh`86pL42Du+9ku&Ur61kHPw zsGGrp7k;~c9LEU(3N~iRsV^RXxA*sdaq0=AC#N%OMKF4B@~b3N1?WoW#P_b-w^}hT z390|22dN#$5CbH;;@|?j<$e+K(uhEy6TVWC%cYnh9 zdInM)UBU_-BI!KFj9pu%rWS7)<2_n1pb_^~jZ{vB35BY-jD!1ynQxzYjTZ&@H%j#a zk0#cZlY!FuCI7uGq-awd5u{khWB0pCf9hF8EOkJDze_KxEPUweYi<&O^r1wS`{^Ob z-$6n_NRxKSabHKm-wq^$1Pqqdu-e^rV-ndP`rokK6M`fy^x> zwHYwSphP9&-kb`xga#0xybZI6VU!?HO03j`z_3G~wnLcZF@B`tV9Hrgj9;C?+s>zr zXMdylkUzBm%xfMCBc_`?Ce|YcFLZby(Ak5}(Td=VB8lw@ToxRD0P(FmU1~xw*(&KK z15L4rP^s-xNkiLe?&1<7o-{7fnw~ezkC=e7iex-)CoX})3OJJIe?K*@_gt=++oXfo zvWkiLZ^Iv5Lj}$(F$3HW=j%TBvYp{_Fpf&1e*JkNZT_*>D){a+r>W6@$>4AV6eL3fcyK@e|oZJnicC$61`@vv1*gHi6=8 ztLC^*o)8nCOfHE@wgLk=cZyhyT)4l9ZW&Tk!H`IdcfJaXn2)Jw&fw0YMfU}3rt!r| zDWJ{KE*5Id$0)Tmokv;`@nsCE#Lv~UKapYP_3N*sm1E+(=13Ctf7Hh_|7{TR^n zuZj|~>7Vz5v6V$I;{bNE3$>b8KtMo3AKfSGBd-1R@DI%&=jA5<)*S%QZqcvm=vzev z(Zh`At;79Ez*+q62KZhGVqXQ)8Kd#_TzeQQYT+hT-jwCB7wbHDm>l5m-zg>lVJ61g z*95Vr4?f8Aq;;t-8gT#Tj)AAOrAtLW0{iOSy1c!bOW)cV28HRlc)e`@Q7J5Dvjr#Va5tBPDqtZkS4{n`jsg zWiE{?DY@RS8Ra%_HNpKx5)LgX0UFK*PdFbdmgJ9Qt_G7Vsb5gVPvO+exw$OPX- zk#befEr5bg=BhtQ=18Obe`_9r`fD>-A7o7=nQD>fCcKB5&YXkXRX1nqIdh5vlaK90 z)+(H7>gu|lbKC{Lz|;;|^b_=3aFr(6G*Hd>EGjUKFD>0o8@uMFh=)$!@FUy+LQ4Ub5y^_McXQ3vnud-$*Cu=Obut!gc zKVf<^b(MGZTZ4c%us-JNfKMnt3s8(L`N3&-Z=|OmFsLdgGXIEJ{>0Ruj1CWC2poZ_ zzSkNfP=_8i)G-M@AzqbR@z2&T&C%5LI@#zK`u-q=W&eA~K@0E%g#abs-yxXR-cu;L z7cL`BI75gq0nkOC+}k0ByM&r{J;s-*E}Gl?e&m*xGzq?oWR@jH$5fPyV@LN_(3GSj zidx%m>033SZ-~Mnit^XZqRi?Iz-$>kr@^ie*wJNV$CRI-Y)m@STo=^{FbgR2y1#^- zdwKbIvB@^CC81a~q;$^@Tq|mkcbr!Q2n37(lEFM@!8ehCAGyx1`aRj5WYU;9%=PS>NhC^387SBtq+?k0B2!lo`1l2Kk%{jU$tDX+7{PkJPcTzs|-4cAY zF$~U{vZzU`fGMAosYpiqa}< zl|5#y!!7yKZU3Dhw;S%n&9X=D*ZYIk7p6~y|DuqA=jY28tH+P^bJ|Ffkg&y`w)>Us z#CrPbx3??w_X7d+>c8&R^qVn{VQserqRVcRWxSWm($Y=SHqy0jv(FnoVvOefevkEl zg#8HXiTWga)PDv_>9Q{J~E0&l@F9LPxTt=6BwG#tIM1m;VS-lO_SY1pH@XV+ruDrA8(E&)A8b!A?227XpJL zJ8oh$@x9T-%R=hp7r#OH+XrQSo}5=j?lc-jum3AidMfFtAFdz&p4rRAe^i3BuqK4m zxm1*u>6YqBir)zg3iP^{OgXkK2cL~A_pZA)E%yAFsOJ8!Kg}ApwHwKzB#Zy zE+Al@kNZ|;w{wVcxitA1>{=-C7ga2FoXI!rAA7*`oJ51Y;N^rt*TMpDH~ZuM(Wi?q zMkte8I&^Z!`Mz9|k!&obcV)@qm7n&k8aiaYnloi0;YsO%?WDkvNq^Zeuv0D8X+&Mj zFD9lHQeu?I@sIqPaL9;o|MIZGZ#A%J9*1GOkwHP^E4JN;WOW70wc>3D>80ei@6FRX zqL4;<7=P98)T@;D>!f=^b7~fHwN`2$x(u?BRvpc)bFXnVR$*~SO#03G|G|k;ZY~<;tPiw8yiDb zZtj+r=pJ0<=Mhp_3umfZ6EM=+J2^d^5;>IwS(1xy$#>W;)n>fL$?*?-!JT3{Q;-av zD309N-npiaeR-9GAqe!*9G#v{b(x=XBrOXDnLNMH>Mae)3WP}0r;SSdFwjsTHQbpm zSpj;G?vOES(2mMiu%n15-+MC=D*xjzFyg~|(6#!5eLNXGtO1Mk8)7R&)dbj*^ zwwk+)MW9LuB8typLlNPZt@WVX=2@W}N3Wdkf(5s*j5yxK+;7 z#p+)IayYj37CWgQ^EL12>E1c^_&GHpc<5`njr?r6j2M(hl& zR8VhlARKP%VWw&x0IXA%gMGUP&3t>y%u!oy)EiW?k;s<4`Rs-|_qAy_>_!67G!*b6 zR_0ESw{7#%i|y5d8_H$*yo0Va!{>gB%`B+*)05#?^1I9BHI=-`yOn@!A5_nHZ0%#- zyDB1QJ1PblB=u-;5A{8VCKW>ivez|uWK zu})kMkjgo?Ak@u~F^@$T+-@7^%~4$ULa9{m?xoCO8{*4X86d;R$?Up|epVVO!z(50 zy@ZTFz>x66o0gfNVYTJUaV2AX6=Tk!75Vb z+vrVtVbPL*Zy7)!-%miGOQ`G298}%w8y_>|^68XvHY#JL`Gj=&vex`!Kdo)ks-@R( zZKdY2N3{7oz#Li57KjnNO%#m!K+WsFPSkw4GgF(%W{xUvlDYP*Xg=+ky8fr%vPmDQ zp(<1K-)6ge+VKm>?m?EO7#!4iAlf?hYtJW3w_bM&#u#W!edFTW`g!n!5hA7nd}X!m z1rl<52nAL?K;@v?s=yl_9M$#n6k`HCYhpdJz>JnX%C=?>%-rbDnEye_yPB{ z?ri^-C1();)q9wIUT)(%lJ|Zl^1$2Mn-z?=ko}qm#}CMG0FmNKT}T+{?|>seM*((N zhXvnnw^jLynXYg2`GGN8w1eI*I7R6V4qxiP%3l{_=g}$COPKN8=zH|{rgt12zuUb_ zj7%+zLDrUVi^=!Nz-BevFYC0SyiGf-R6?u z4vX;TW54e|ELS6L9){H`#;<*oC%m9JLt8<>vCg|pp7LVME%$evPQnHS=j)`Ft6ole z59yU2$Ji}g|Fm0lKiR-*+W={XU*rDE60cZvG%SD4LCU0-_yx*T5VdB&aUcfnK>_6O z41U)b)wvN|VlyUHt)RB{$qca(x&~QZwY6RGihLLtY2FJ661hxhgB|@Xx<6^E4wlX_A^xH+eKFZ) zcX!4{CwbofoCt;D4YY}U1o_-`Gb)V`y<7cjmE)Iruk4#RiMWgtb#1vo718-^c(!@o z+_b@Q?maZ@$BYI(1eFf(mhqcAnQGtf=3Fl$jQo!0WiG4YZ?EE)wupg?=-NIa5Uvpy zd=!=gJIbBRxvq^}zHhBxCg+MJzjQ%d4-y5f=)3wY@7?Vc;CwGjLjm>HmP0*iB`0t@ z%=O;qE*~N3JUS!U#ez4~{bc#Lnyle+;4X#EyPntVZq;Ys$knfN^sm_QK}BgB0wh4G zl_}pNDq7mEK-`b()0fY5L>8DU?uL=K-8eF55~HwXWZTvHBnG+HCUK+pvEi+G+u1rI zu-8X&mHIL+tyTwdHw!u|h3rpmf=I1wzoV9!Pfc zQ4u6DYpLejjor@n{u2SK1@JNEMPsy=eM+Ysn-)uwRoOF0UKUXdq^XiZUQE6dqO;;v zVNbW_u=~r0-|OYUh?^U(*}Sbx4+BDthVlZE?}l5?Ue)Rq>pP{|tYX{Axt+U^iQzx< zKSJIQ2H%|C6o$hC?4DhH*l3EUg8aPrS<#mN)=jTrweH`_J9B$PHj(qmStv1xuf;p*E@%R;jMGkDI)++#@i%T*RR_x=7(>)2t@ za@*Aq$f(0xw%BN>K-FESNgrw64r~b{MO(KTfv1m{+^f|}(w5-s(bUev z<>Fp_L)5OT-`XfioJ;fWdHwB4MevWCl+pXyie=a!5o#^M%OdiZKfLtNkuoct&HRGt z;$M80Mt1O-5k2*3dkw?cr)61eOna2y@^PY7d4Ku+i7_?(?TP+^Hvdzkp^tFTW`bO~ zeoW}R{x{k8Ma0g7g!#Bn*4d+!*7;LmGa}P^aX(pA5?MI%K?H_c*~nL^JzsB%@VGth zr%$~up1CLTjnIthHYfyv6j7n{KMwLjfVmp1YC>g`_!VfQLGaf~r#K@{{7?B9Y_}ZPN6mOa+1VBgoaQ{8W#^W<$*Pc{rxF`0@$P0#HNjU-52bI z^z`)B#IlENfu>0vj8bXo|I*<+#$qvb8YXy-n_!p7Z%e^F>X~jc%Rg>3D*il%v4(zd z-t&r~%>8pH^l3pjYE4vHT!*ffd(aE!T+AT2V*!JSWSahVL)%Q^v%~E=0ytxzUuWi^ zxH4ygjiK1n$`^u1k_K<$*GNq1CWNpA^l_rrX9e8lL-Gr?Q*Bf--V}v;@>pZ1)m-r6 zo%DB0Lq3;^VvwD&6_8l{(z*CGE&I`uqRh5t%JDCk?pw+)jVc`6gYGmqkV>vlmnY3k zl0-H`?#=}|sfC_3Sm_TL^TYs=W-L`*@;xeVdo^-YD04XWyjGGN!f;|@ZCHQPZA2zH z1r5AauLu}DmbuGZ_V*?oLG_%P-%<+Slkg=WsEwgdYq7^NGFYhuwI;XHg6Mu0q0)$! zZ%%@5k0NExf`ev2P}^?XU0>!~G=>Ect^3ba-6}%d`#J1GryBn5e-xqy#p!2EkOC$R zc_Rg|`S=#NYpaXb{Z}AdLgRNnqtT6|l}!xWqp!2`Z5E_in7T`V=r>GoAuiU-f@13f z=|+=l&2O*CZ~qwI-6D8z=XNSCi^+LSJ$z~tPj{PAyGXF_w|m*<1w_1q&;d(8I%h!UzoXm4GETArftE`OqEi82MhW zJh3`;H4f5nxfZitBasIeH?5Ji7R9>6n4s)m0WulTdr?pmMs8<)5Nz#Qt(@6oQAsS^ zDXU+KYEUSeoSU7ci0>`Z$mz*waha#4rtTY&3Ap$P?L@+?zvKtI0U^!1XY0q85!7$D z-#sheTM9fKwxr0G3YbQs^h&`HR_s}BBz@2qbd|}o)__BEbMv;<#yx&E%J^PLWnCRM z|YX?4=)oQPSIrWEG|HQNfqMASi={!#+;z7 zq{U1M9eB?-fUkB+~Aw5 zizUE>Xg&}V<*zWnJ#Z>ZnO@*?i$d>Bui>_e`6}*NIJsl7@;0N;WxmkTiNHv$2e%~a zS)4?@TUV6il$iEccthd}2xz{bC;guF{kV*>tgTGbBH#6 z@@9zAmVS|xx$i(`J($|e`2_nsKxGxB{Oy!^&LEEpZPLhGuFs@CI4s)$ z^3!~LD95CNKg5DBXaHx;XAxiJDU0afh<8sLkj53b}}bb57V;J zbt-CkAf6_;q5F@;I!Z*-ePsg2{*9?|gCo63z==NshQZx;4`G zPeI9y>_)EO$-IVyoS4eo4s>V)!$;3r?{Kp9Th9LYpByg--CyaHt}X`OzTa;!_xfwp z9C%3_DHA=4Brf+=jFUmm1fTDi$zgG7ertb?g)N#ouQugaYgWPgl(*jK>5LCeZ```C zs}Cda+7D=Iuk5|+(MrzA(YZdiUI;eLdWb0dOC z7#^b*30P+x79m*)AU>kwumZJI?N`g-N>G_};SCNB_MOVT8lN7y;KncP7&=}6 zQ}hKfiL>WYU3?%8Yx2+W!eh~|LN0^H3r*R`W&r$_oo5j}?^9gNzRe?;UcfMLs^%lb z$UEj^Mp@ON-CT>j7?$za=mY;SVKuzyYmV|GhIc|#tIcR5E1f~xF@g__oB}C+=OJ!V z9he3m7!w#U*u|(6AIHk$s)uNXdJ?bq$3U5E;&6ChT=|01CvgmcESlutWN=T-#ovZU zcc=3cj2XRtkm}$*l9C)}RSO=7mrEBw4+p_iOfQ|LHRl7{q<)3h>Ui<%2C6JJZ!>I* zb(HeKOzHpy217&#LD=J;*aC4$SeM1RMxG;+Vv1Vx>~U=CD#2p1#D1-aI=vOVyjxP4 ztG4DFujQlK;Ktp#;d9++lN4vmrOPnHT`mIkJ}pq)s&>O)O?`bO+TVMWx8;N&cydxl z1#uzTdV{5_8WH(*;}6k&M=M=%kI~<`zV_*+4B#seqD&$qO{g+jkvnB zf5VOLJI3X;JR!kwWH4$4CnsP}gZ6%F8P$?m9`h)6uN5&Gy)28im zsh%E5j|iDqKfH1ub^CEXDO_=;DS5c7zxD~NdI)@LrrGvf|8B$B9QhJay>5Wo>AkyX zLR>f0Ebd>=wBBgsm|I%=53>+TMlS~-xX4D=9{vtj`z&>#e7{E&6MW;@HpNY@^Xgu@% zk&E61bY?JUE8(n)#wYZ;qc40w4-3kUX z#g*f*4F6JC{EIC8V_qL0e%D3=)RJN}^xNcKK>570P;dUYg^(VV+w67G(#aMgV9|*P zxI1=hxmK8-dX;Tt*~mdiG)Hhtq}F`CrRc~~vfvP5jmc6-X!cI2a$?E;!j^|enr|{c zP%Q7eb5C=Tcal8qt_KY-r0lzn*!rtvNo&Q0Ol*0f_LP980W_SY;O%UBBtE&Q?@^zV z`A)$g56@9XDg8<6=z4nSLcpk~6r#Ru)rvmwfd90eKK2lWBwxHrb8Upjo9pCy*64Y- zEj~{ZJL0Ao&*>$Q{4L5s+VLq4PFhGD*^7run2 z$e`VIyE;1}smpKLstz{uA_d8wJ-D?lO=cAUQ~m8-pnd3rv+3a{M#sUTvEYmTYeY+4 zNp-OLqLFs=)G@^ouymmouC7EXOvV!P;1)==1oRH*CPBLd1iPRLX>9br*q>uoN!I=` z?l6C0!3R-&1#AzRn&uHmkkbssobveKdDwVp!PhQjb*9K+YHCVL7-@j$xwVv}^SNme zQkUBSZv)aczrLchEAyV;=qZvuF9ywQG7%MFWTA^;sxV#LXYS`5fGR3<0G+YW)d?)v z&JMoOpA@%_DOc(K4s2F}$Sywow6rt;#sGY%%68;x>mn5@&p{f&_{79%IKhn-|FQt8Zb&2t@90CA~_S1$@Xr-GP4#h~bqQ?V2j8`855n64041N8C?mYtxZT z$r;O1BL&Gu@1ddTtXABE1vcpsmLN`SP@oq3X#tcHlFKsTEK)nILN#cTIxwXQAcWV0 zb%O7KIBiLnIF?WNK9_c`#WHI{o550t+cC6xHzD^#9x zS!OwxOL}Cf+@rlim}vfVJ$v=&Nd>GRvMumnipX#9F|2THeEE7>zxn+2FycPib%~E~ zUfMF|IP4TZ`u}3;&EugC-|q1tF+!$NCS)nemOV>knNTLgRAk@xeczX|g+Vd)H5!tJ z?AeoyEhPIoX)yMEU%z*s=XpNAUw`r*_uws*JdIa0mg8NP;+4iZaL$0rO94)&R=@^rhU=8FPLIe|8z8*Pd%t5t-xbboc8 zHYqd2hN)7s zw)>gt)#Ez>XQ20fLxhK{Be5cI+F!4{g+I%rsqC#*aLtb@th5YC0a#5mS0FOYdmJvU#sMad@h3RAUL*0(ig;<7s8xc#0hH5xVTUQyH zV=2=bf*qKEK^(q+nU?2K`-|@Lj_=)+iR+(X3eDy_cVee_hCwO6as!~@;*M?I=r@-s znch5|oJzbZB%#UY;<@K`Fr@KB)8iuNs#nbX$>a`wZ|BTiLTuZgkwMU+U1enM0@!#Y zU=)%pE|YUcUO_-_|M0Z$Dq|VHnPa!(tGO?z@h7t7>#E1v$xknvoaB2iAi))lJ1ud6 zG!2}Gg8$9}xeZd*vOe%IuDc|L%ki#t5AYh46R9-z>R1yt}*mRwXt}w|5Ip(k(PB zsV*-+2T_2%OiCmHCtT$RY?$=6mpxSu&zm=7p0>*Xb`jbywj)EI=Zpnb>DJdNkC^uM zW0q<^GGT7>==PJ#$8$n7aL*OFSlZrWhHNXRoktejp&T|z4xdZtBOZ=d84S-(ydiGe zJoRJZ__0<0G;lKkw50&c25oSa1MnM~mes>)<@Ld1loenU3OU&2-J_6Zu#hrqI}6Ga zWBd7GFG&vC;LFO1sL;zjQj~iT#t19nn?^tDZE<^(&WR4=AH|~peIXj@FsN}8{&p7b-Qs8j7JLq*ln z-$F@|bS)_}qF9FCpFaEu8BqAtOH4YWSEGjZ<=Z4aF~os*K;FhRQROZEXrcx(CWK4U zCe}796h;??;&r2jOc+-VTdJGsbAL@=>v;*>8;Va6r6q7zc69be}Z_sm^=;68+P=jS7D8)@Ld^X|P6lR?#-;tZ zb1{68CNdlp?MgkpH&3~a5FfRVFy!A57vI3XsDl6Q_{ywqjk(UX_is5>m`G@0!rt{+ z?67bbI!tX4qo`t5uX}p;ORrQ;k#3 z6HonRSR#=g7H$%wd<*T-N0l?a0`Roex;01f^m3tZL7i!K2wZF3`5wN zNz=EcH!FhCr;JVYb5!&lk3-#7j~pAc?8Iyv*YqYHgUfF2yJD5YcoOJM7?h&5C^?W& zC2q-B(KSDA;7@|NgpdzGA=_CV2H9H}=fBAouRl{sx{Rdj&j}S#PTL{R? z!KuR1=0dA`1xa_#D=}OFPVuUp=IXy8h~eL}Z8CY8bd}=Onjf71dbo*h5(+g_W03{~ z<}Wfh72uygfA-C?bIzM|j8P_XMwau_yoR;(u|qZf5cVDr_VT!GD|Op<6}AM2Jv2W7 z&KB|~qolYv-zEwhz;k;skQduI>srv?eCyrRcetLBkv5X-cH>&KSc|Sumbnb;tvczb zo68Vm$tVulMcbR_DQ#qk8}Ncxl|$B7(Kae2!w>Ie1_oIJnq32@b=@qM$R16hWV+6~ z4hY8UbE1Q`gIo26C3k*<1p;**=bmc{LLBa^-gQsa-l5VmL=mrSK7g24&R=QCZdeAg z$MKRAroRQlu+nxOKMQj59^MSaM@U-p%=)0y8add`Qi)-@W*ZtF40|MSTB7sJzDd$1qPV}rwj@D>QdKp= zfFbD>gb*;0@_x@&-pi2;KBDdtJG6FEfF^J->;JR>8sBLRw`2w|j0orcZ@D1->QNjk zR=#$cHIIQRx-X1T+o^hdOM z24cZ8fhXy(*FLn6mr1iV0+w!6`*-Z3h?UhK8IaKMyYr+TK&Se7<&kMGI-ca22!?m~udjpG0fH?*HyO843T$jvPr8Z1Rhz*Zl!jZ1Fdx*??|aV;?3HT zOtSy2EzU=ReDvj2tATXWW7qLvT zkPB{1ShsO^2uUZAJcXVrJs+fs!){*5sn}(y(-+wDeL(m2i3;THdg#oxhBr;rnyAGS zk$NunN>dCUE)f?x$ctzy zjoc@*zd`s&%`$yN3oyJ^-V$pjbM7h=-ureyWglXVQ_9j*R_mY1=*{MyPO^BvH|i}O zW43JYxXlGL59u+!Y5Cz60?Mrk{0S(jB%5*1%LUgYDu#RnA}K>Qjj!QVa^+om`WEgc z`&?@?fguYMQ8hpFI9o4~^9)}3Fmx4^9p+0k9Wyr_w4SXhv7NR* zTC3mEX#!3Geqcx}8CNoR0$GuaCHe67Rz80m1i|smmMzt0s<)LoAR;?z%%o9vJfvHN z2^|9-H)!?qxOtPi8rSS_fEBPk{o#V9b@RU$l?x!HY40E*5UqgnB-K-%ICQ@XFwq3r*f(k^t%`gi>ZNJ?#TzKs$(mjS)>$*@jM#^&@H~) zZGCT^;R0s;Zp(xi<&4Y2o)ynS`n<)MF6Aboa>P1MjWwcvaP)40evLtClNfx z*KKN^#ABd_Aa1yOd1>>48HULx>(0@6KL`X%&4HQ;zD5QaF&{C~)k(sVeZYwHCU9P= z=`6G7D0ZhK?wY9cz+OGA-f0{9x$jAWtkv-pU;g@vTdqv4Oe!T*5 z@igDn3(AL=%yQ#NKE)p_fLhCF^PbVscgDb3!pS5dV84Y8KSYJ(Z4SI+5_q87{hd4V z3bJs(_I{=<9m4(B6=M&N);+$KjmI`u+d77JwHTCac%$Z<{#(2+_8bTvA3r^tk30EM z7j)#+G@EX8(ABgZ^fKRPRM;l1wiskYZ|cwZ$g;+CVo?C#D<5z%2yyG(su*gEWo>;s zRtlg=7OYBnpEJvySTm$bJZHD18zBA_=AFdT;XSzGVvvs5VgC9(lkE@cu}`ubWqRX^vgsUrFq#&ZI}OrN#P$->h$&pK{4@S>JW`T!e+ z_&+~|KV4Six-#tH0)aqsxi2F?rZZtrI7t4AX`2g_Biv%VO6^S&>h*8Ln`vjb5)c@e zz{NqbstrrqV>Zw;d=!YP_Pw78rY|JcROi|q+6t{4#;r162M1jL!q3;iuKBmqe8{bl z!M9!V<;jC>gzz8Rc{UB-zJ0jc>LcV|5Xy~J&fBoR_VYj~^cj*GVns_dyAVoFmdkD3 zFZ2PWyTsochDn1MbLHGio1ODvZCiNHnXOb`RN3ge!bblB0!hvahM79g`KUJ-g6}88 zjb}>?fl5$;c2&mbyt2k(Ep*_Wd{{B=E^*;o`un18Jq0*{b98Gfy##_)D2rk<0DV3to}J7a4fsMn(UEq9*!;3E~WD zRpF)JQF|_IkH|ZVgp>63{R;*EU!|}8lX3R9w`rxABujcxa+uGT7X&fRc%=D*cGbr* zuMdX!n)L|sTFCuXsL70^I!kzx1y8V;3S#`z^P-|9J56}z{hi>UPe8Awd-q>-7jOW{ ziuiPQ&^8fOTUWPKy9%h2)m4Eg;T}uTj4d<~P7=Ltw&QyvpiyIYZoe;Yj}UYw)zV(Z zPx~gr*98QgIWE^Z$OO14e(2+`i&;lFTn zq5xMyZ>kr72?b9qZU6B5LVN2Gte|6R$}yg^d_i?)v#d)n9P*#`8x#Pe!#^28OGQlw zw&Ht@Yr~&j6wa8-l+r~r`vWopr$6k$BCVEy!{LaJ;?j~5IjL_eB2#~K7}ndR0dgOm z#~qamXbDa=1-s{`rTl!fq(%9bX=m~D+bXY1`H)EbKkdStr3u?nAPox-T&#(T=d9_D22E9&FsO`l6cYOZgSzs%36ysn9D6fC=l(h5CX3YL zw2v7g`FRWw?sWR^l7p#yrZ8JE@ij_Ttad-sty#i%O5&628lXJJUn)lX{g_SD7Ri>IOP}2 z@6U2Q%^TU$$H%Zk0octXk@fY9PqP^M${qFPfK zI(pR^5cYtoaL^Y1niXW}pbCK`Gq5R6%zMV>k*2xS?&8=xJ;$0^VAc?q zYSrUFwwZ5pvywve8qx+HE-fwn5~&^^y8390+XQ1?XjBZ?dCo|y@-MmqxX+*0L%gm# z$<95rNxO`IzsI0*9=Fvz=2sXO4EVDFQ{KBOb8j$s>zw3m^lZ?`Q_5?_?H_+&EJpoP zMrIJuM7w1UYn(~;(k7>=@MZ8Mz+_wzVRV1~Ss~;@3gqOl@syrLm29mpc zljpqH%ET9KmDC*JCc#_^FynIaR_jVFpDercK%F5y|D@0%9YnXB%{euSMv<%Dt{f`X zD;jnJ{ZM=NWyH4ciJzQTP?{wLM4nHrf|6xZlKZLqJb{uW>HGtoyi5OmrcbX)n#DcX z{C0@nuw$$8IK5QMcED-#ojf1&^S8a171gLp{PGXajhxN`*e*DiX&8DP)y!1pX*Pp#mY82Q7v+q4bp*|IUek0hqN ziGYa~9x~9?9UB`}SHi=OM%rYYamVV z+pv=KA>aF17B*n@PFqV0+Glc^hGTDcS2<6U>qq^I;43hSGXCB&8QNR9?U7d`9`g`E zcF|8mNfNSCrWc!(;f8%tAUD59rTb2-i;SV?O0s|TsC^Z4w^p4BkD8J!Q%rRgFi>)d z=k%7?enlsk)itf{!G2p3zADJl)0pG;;=kjxV3=O^!DlMIH&Oib}<$9iXX{WOZn&_<1=RO@&5@$s>;qPjxa zBb5fW>FpAcMT1OeWwdaA#g>eO179!L4oJ5`Ko=yz{h!dmjr=Xyz5mzH%#CcfMUCe? z2WKy^4nL=aL1DPRtx7W>`M;Wbd9rgTxZhJvnegVCAWeEHHUIbVhP1a5t@4KNx&f$`Tcewy?Z~5?R zlzSsMA-X4a4Gq=Osj73j%4raeK_qt2mR}GoqB*52X90xp!#JCa=dOReIk2_o>pC9( zN*%#!^xp@1JDL=DKy!Am+7v`MJIUgVgkr5X6akL*>ts#8?Sbb>q+Zs+^3#be;|_4} zqlqJX4V-Eqc!`*z*(s@wLKXrYx!HIstavGxm`L)g8o;1#ThyTXkmnWF>Ce{bQJtv5 z4;W8_0<9v4EV(tw9sbBwz zm0mSQD=BchMXIJRxa$@^zf1tlc3#JaKI^Z=%;6lMvd<(x0sD*TIr%aqe?LFw*>DY0 z?x>p;5`*l zBXGl6*h%1YVd0B4vuF4j5&UjIHqP{3pROqW%Pa>L!+x)i=_|_jJ~fmBeWmlG)>bnF zxD3c&x*7UQkqmM^JdggRdv6)~vg~}E7@0mdZ8al0C**7V!089bu&z7YnGDh%Ix#v4 zpaQ_ZA=+D;zup&kYFsSQ3AYnZ4|mYK;FG17At=)&bRHRR?qEc?P-sX*d z#9v_0Hf_%fL^|8Y2i@Griw(PcLG`*9zXb6pajl06EjymrIlcd%iOGBMwOinDa?^UT zpkK3v30=)`M9t%F!veFk@aN!FK(T`XNoCYt{B1Ssozix&jG$XItd*2Zlwu%kamf8#?yrq^bdGsc9=)?SDZ}$a$yS z2ahz+_PsrDmbqZ1fYW+XHc-Z|o{Dh=4k#WTJFlo%p|6ear&{W072R`f4|`nB4|ZE0 zT&Nh@PrNRpZaVCC-ApA(v&VuL+{|Ec5|EVMGS88j(q4|>x_-ux*p-N#$i4T{Zw#OLE^O(Zl`&y}ZPomRP%jst^=YQmEd z`0~y|_RnIzXITKzVIu0%Yez_OAe8{|Qym)M^*3iH3!-b`F z!&+={?+`TV@{5l^d-9z3X4iKivAcFcaNxPSMe4nEk1c@mt;g%{XC@3jS=zYgfErRO z(6s?vXWNE9;P~#+z7|t^l-CzRFZ;E6_#SP!VM!tq+hKkoN0MaNaR+h|$VL^^FZKdC z8k?DKlVky~NEa3*&4T_Hpdti2gt9|H<+^3=j*xFv?{$;n7!&%6a+WtT5>dvWVu|hg zG#reduLDcKw4Qs;oE)^f5#eOq9PF-2Z!-M6HSc;9-y_3r>f7KFFEgHZXvDx5brZt; zdn_ENE>MW^@2k47$Q{m`p*88gT`#w1&g_!6>jYf53H**qKDBd;b3mMPmbs}|7XQz# zUvqa=;@P3!|Gb?)i(dBgSD767U+7={l^|u+3XoD%l-V;WV^Jn(UY-`o`?Za)W~~wJ z&XVW^w5Fuj>V*6K$))AWF3Hf=7FO8JW91GbG4 zk+a}Qp9D6IgG#v)Pm+o)uW4{dvjj5)U3i9w`Px9ypxC9!k84089^P^a{yFMY^^ofY zp9yQI3t)ul-`L;Z8U80KkJcW2yLkUqURyyMOzgNPW_o0doZ!&*>#`$voCwz%f z#QU0X2S>w~y1JeQk5oEp-u<8^`@Q0kJoaQqIaA~C=eT44g};*2Ermn(V~GH<=d|Zz zN4(kap7+Uuk^6`spypi~J!#!@U*tx>z$u;%zN5NKAXXsxt^&}Szhyx8sd65t%3G=_ z+e+1b7FtTcXgfLeT9(W79-TCrz(e}pxW#T~b$6>lzJPED5I|~^)~^|SUpQk+Os%Fv zrdQ9l@L+{=^{qJdic&V*)skV6Oo}L480em+hnjBk_YHo>OS#)*Z zqphZc&$C7ghj+10vjpnP7s#chrG!4v`p9Ub3a4`-%F{lcqBbYWjG}U_Wmv6Lc$Ios zI@MZs8n~h5oB;4_KfmaHKSLz3i-sg9g#R=fyzY% zlDn^ic?n45?EE57Q)~3_ycJJr^ev6UaOUDC&)!+2jyu0L4p%lnmrBN_ch4CMy=4!P z6rvm7#Kr3^?i~S&45Hdk0jZ#F;Q+oYH`?Bz$Uo}9^H{AjxU#et>FdnJC?N><>hTqK z&qUNR`!LcD9YCFBchA<%ze-hof$=VbK;NR2*nHFHj^N3VI}Z+xCIlFae4A++b5qFv zi(2dbC|EmKE<9R$q|)u%;Ha0h=J#<<2lpI^r19Xx#LR7&web$}7SKY#VxP0vw!a*0 zou{Mll3iTPVFH8`faeItMzOaF@MC`^{pM0D_u%R< z->o@n$X>B;lIzLr;B-sK$LjL#ojjF2_*rA+)3fQ5MUr{)9g@h%yNQtNUL(Ck0|V3Vf)RBaq>CjPr=?I>Ns>0*n<^}E=Cu@UJAd-3*JS51bi z7sA+~Z(_RXGZmZQW(a86B?Vz+v?juyHC+Av)NMTwWom`PI|(jz3M8yRHZDxf}X+tY$%gcok@^ z!4H`mE@yFp{>$^4JvBq0My=sEu&--nX{Fn(1?(T-CZW--uNh2zZPP@uI6Gpuyd0+L zXZs#fEme-4XEcDfs+4OE>q=$OK)btp?ed-k1SDMrE-*ASG&X4>cp#RrSN~85dkq7d zsFqe%4vj)>E?PLJ&=N_IP(-or};$m1dTp`@8)wQFa{!5z& zXmbD;@xBCh=Uq#KR#5{m`9Pi=_zOhksxeCp*}lNPgi%x~KTzvO*4VpwgM2AZKF(0e zQPqaNlytscLChs`{7Z)0=ndf0rdUdp%*)F&f!_?Zx2*7FU<&>+=qX7>f$Z=XkA_sX zR9!X5zk}A60*VunZMdw=E+Li$^h+U;}o=HV&dOB{< z4wSF#UdGLX=H_P4y3G7S3-?FL%AU(3m)cygs7r{EZ<*lBM7()Xq;(1LSqf$W(s|5= z7zf~HwA51vESLm6Ciw zZ>|y_YVuN`_m0aCNw2SF6_%J*O&M(*IyTl+6+m-IpY)4V)zr@`7&{Dy*cS&m&yQ?G z-W{*Hc}^TVd@D}oa$D)p;r;-p+0R*ZEJ_pE-P7$j_7%`8c046t|3(4&)v-Eg{lqUn zKVN^ivga#}n;Z1KX=w@B^yG?)2O-fotuR>I9WJn_ z4WkG{m>3%yo0{g{X#M9rtukRR?(p4s*lnoTKswOdzh#Ur0)MeuS52_p+*K--OOwIp z6+QeqMKQ^N@I~R)SCZczi>&`k=quRR*T9Fs2?O&|lb80PEmhM8)9Pz8D)GU6fa-xl z5zuLi$WpXU?Uk23CvpofeB=N7mP!K_qfF z1yJO}np0IRC+EjDHe7H!wUtW{V{dObg!Kj+fIpXpOZEcJzP&n^w9s_C*~JEc+<%gK zjta}}kMU)Lwl&2|N3tB|&dx9n1`5!X1_TVi`yC}548cfILW)-N_0v<@>{9(m`&W1(zLmh+r9CN6GG`U~*$xLZN;5$^#_ z=!Mtzc`vk)7Uh7D!N4eT5*OhkLUYAujH@b|MGX1)!pR|i4gJN;g!&gT59w*Oml&*MB89)YT;%h%=-1>)xu zTprMy$w*5teZ826L8avv3WNKkJeA+V{qKlkJeOXzW4C2_B&=Li6uF>_yQZ{a+aN2M z0+9#fscu{>B}POMK&VkFvf0331pKvt4R={R0E}w4Z-{VGHwoNp_wGsAphqh#+=}0x zO+S!h4+VC?b|6dAk8P~qwh~-`!uVtZPo1K{``-I7{8u21n5;{dI{q6iNEr;^P#g%T z9k0&x+h3m!L;4IC8??o;4C+#issblT@$_@&&WV#45!@;_(JmlvH03e^6r0bt9N%lS z&x#=4h^a$43K=ro{;_c4GVg|b9UUEW2IM3qM?fKQevHK|)fQ=&;PLD@>HOVjS;)xP z0XG&Sq8n0n@GZ+eU!TV!<`joEVGgtClbc49JTd^Cs>M*?AIP-ck zIb&~mIB33DYGeCa+24TdnrWThuZx?>fq$l|0?WeVm(NB9<@SR1l;m{6Hm1|h{u1#0 ztIYW4jwc6Cg0_keJJiG)ccN$r&U!1|GjW*D3612F$4XZe8 zbfC~AGAp#aWU(O636g)XP9g-J^tgH2k5wI=XY*g5IX|M4n*4y2W~E=@u@ik}v)D0d z(?wd{_-SS(V~|XE_S$i&>fiY>xm|(kRyH#U6i|y7Q|p@DL||oPWo5<1mEm`H_N23{ zR&1kMzt7Kuhe9|0UL?)sB4ougrPnfnTh@R7%Pbl+_&|6L9(Nx1Z(TFhe{}v0nigl^ z6JMk6*qwHdlpS=6?ez~|s;Sg;qCs<$1{kubKyw%&>R zteN4pc<##Ao6W0or%Qx7&aEFa26@_A-gB=qY9b0CvjV3(PlK#_L#WseH%p?M{JS0n zP7G20ZD8|TGWrAlPAa+mAuCV9Y0utNX%6k5Whud<%-+D+eA3nAm^{0Vg!^toFHSJq zYROH3z;PqralbP_?*11N*m1tcJTXh->|zmkwCgnG*&iL=uG6>gVtg?1pxCEkzVwx9U=4hED~R+g4{JRTA(?72PP=UMka zQquZ?mxR-l|I~rB*VZB0pD*>=ee`D=L94mJgriK4AIH@uBCJYun4z7Y?E*pbKe=%rh0WJw4Jo25)bsO zLPCFzWUTo11{mq_fi#;G4$&9u%^c|NMf>Gw1P-H~jDs9GyKkpGfA= zgW@|&X=S|=O)z*6ckSHH@sD|t-vyUg6VM|IY#k}w;wiyzD45|r@mEC6d8<#4m72Dv zn1c>Rll8yM>Np)toDhzF&x^gcd}hv_a_Hu&-O#S&bn_Movp5v9ANi?O1N4cp1BjZ1RLCk z!|DVBS|b{zGMOM!8wZRACua|S4NncAN^`vYiQbi@297nT(|p$ zuT@>up;WH7&xUeya1eT3~!4S3f(QBrI9CQ}(1+FQK4o*L*L2{pI=E7nPTvst{(D9kOfPcE+9j z`|^XIWw99~OE=F58l?t#dzlp$x0PN}*EkiPTh*3x?mv**(!@owq<%0fJy!QC~7UXR{4{5^XL8o^-*A@-Upzq!FkQ>rH%m&p0 z>0L3!dgEn{PAXJ=<)%ql)c?YH@ z=G}{?g-+f(K*4ANA7bi$K)+UZ(j&dQ>bGAf3a$mx}9F$3Wh}agf3d1lH$ z&GDEVJ*aW56cLr6gM%g1fdK}Ctna)0J{wrmu1U}2JBg)IYQ;8FaN! zE0B+RRqaP!AWKbn;L-ah%|6I)_f~)|@p=E*gedUS5&U{OTPK&?`og1ws_Ag^o_)=$ zw<=v!T-gVMPN!?9rRj#AD@#s?CxWLfdsUT1>Ym2W*W#-4MH} zz3C;w4k?cl(pJR^;*sxEV-@cZdb@qsDAL}=jc{IRCs2c1i z2Ay`&KW*Bb8xQiytY2$s+Q$>dU5>0u_%c5%3}jlF{T`#OIo%4{`K-TH>?M14%gAp< zuE}!n2jkR6 z``5{E_eidGck66}UfNX>HwbIt_&D||ug>XYPtNc~!>pR%{;y%fz1iWDjNK*Wx^xp?Xs1@9a5mt{H)AO?qTouKw>>$tgb5sJ1wc-}fkeF01Ke z{J^S#c+9Wdahz8<;S<6_23aFKN1g`c7P80n{btn*l~n6!$z8>NXokt{Tu-}&>l`y*FE;;})<;hJ zuv$E~X$U$CR8A#pfjd;{+Qjc?J>s68Q0Yg`?kfhJ$>X%{UZV-tsGFRdXn{wVSYO@M zwF^~cP*S-mNjmVa(khaQ)y8S*-34nOi-SewqstQ$6Ttf0fp$~IDKIcrm=`;fk=!*4 zHt=lvxt6-_i-}b@5dw!jKvHyrVehrgXV0ExF>>FAeusPsJUM(AaZx9E7)&`KRP>JH zWmh2}rfSx8)>Q}GMPeYr65rsrr>u$Tox}8nA*P!f{FEPQ@nK;IGcz;98-0Ol-lu z`joVjJ!ZnzdY9AbsguzR>q#5Ie^&bRaMZ}BtIDE^=BsmGQL!OWxNQ2jTU7N*;D(e= zPlG|-k*ugz;h&&}wGqUA(r~~94viJ=NnLf5uDLF)lliAp8;vKuO^Y?dvR;oUzZq>% zs(PJF=wnd;GSxwCXV4$&G(WLz6KO)st62b!#KXX5ucd zFT!t8z|GL_cYm!UkQ%0IW5{mJ=V~`poV}=KLmM9d?Ee+Y&>Pfz;G?YK*y7W==&fTL z)Vq=(J+=S3lJ(YUx#7vN$6jXbWA&%0p9W^WG0LqM+@W)(YlDN_J=kkodjFI88Ylmq z9`ZX->q53~p}{naXPa)r-k2{mf_ghv#H%(#vdZ+@sO1kzuc*m|x{J>(h@8K(^M!A= zc_rwS>g@0L%F!!Jx2~TZRi6z>2p;{CYp{O9@mRf4K$_U-`!n9kXwYVzFfNg2E^cs;JPw-8|b((8H)SUh5et+J%iNpeL3YCo)Mj=dkD zZQTuMY1{*9HAuj-u6hV2YD7e7ww`T`^VOUiFx{2$iOJ-xv3>|KYY ze%pB=3<~|_UFYWL*4EY_a0;D385Ndk%w;@PRsCVJSbGu1QjMTfwpF?pNtD!U-?bpW zMTcbw>G*7TCCo*<-I(@<_Dc>4rwK)#8_di!GG1Srg1VCKf-27<>HKGkZNjTZilllY zn}vnNe@Ij?J1wo#N_55Zh?%gDf1z#Q(Rx+ee@TyUUu<{Yhh$I6V3YM8yE#@Kp4yjen!Mz;ONqi^6FF+oi^}HW#plgwrZF4JY~N+8r6;S@0=pHmW>eI^L#M z@9Q`|bX5n!|MP6UJjutjVLcbhOLDZAPl15BJ zVV{K_EHW9p-)3cWIvMy&?S4pg(}xboOP`XAFoRj8i;&rzN>1(K?_|@lZ~?j z5=*Sd?cH7TIHxNO~us*%tD?nO#Hq(*LgvBVcSHicE|a4 ztJZgS=EvSn)jTgLClfdSp!L_$)7bpqk?DjDzU-e3N7;m+9o|?-@Qzcb1fG$?-bLX# zo^fP7&ECsy&++!oh?UXa6Nwdi59h%$9$JKi=boQ+4y#cdZL+8=v#r_Ay zGY{!|qPyIBuG_PY8(6(xs>r>9SvxIi>!Mr1x13G8WdlnO3A?x&e8mmxf@PJfwQDBTb6W;|DgcP zHW|a;69IXqsHq5TfybfI{QUeCW4QP4-vjG}G%zoQzO9S_`7UMvy2N4>U>Zo$+#J`P zJC)&_DrKYgb(6(|yb%{~-1l7ePRlnLDU+=jB6zvFqU-|J*Et9t%8wq!DA)~s2BUDc z2ThN;2tK8>v{awtDb%JqUD_*)(OeWDn8?Stoq>Vp;^`}EYe4|%actNbQsru?S*mpm zG7`@2O)jcDIilx%cNrn>I7I!J<{jIjzv>;kB$Z(rD$H&U6M>9%vf<&O#y*($tyXB5kM0lho1rh; zV%yHkx;vgNdo{Z8i!1j`o$Lq)^^g73DbxAry%8;bD+s92zT|CRES^W_KJ>;JMooZ z(9&a5h{ow(yWZT$VsiS%ZEx;>^Zfx3&2Ggy8?NnC^#JHNnH)qND#|H7_3}G}wUtd(|%pcTgYA@PlIsBUuLC zbIM}29UY0;spszZwInhuq3#bmuz%`e$QWorFm|3xnQz}~+&Qr^fyk>)Zc3M&Jlm=Y z+W!?j%x`#IiaGmC<}|bEV7Gn%_u$NXYob-~fy8_d#EY*(Vru<>Z6c^Qi|TYML3^e_ z%}Vd;$HNw{i49|=G;Bmcu9N@vVsdfzVcb#I@A<_nrw3>WN4`=~KN*kouwv$E&Q7_Z ziOlVZ%E-2wWA$=)&l^WQV~e`O<=y|hF6FTwCoky5%+f<(cZBoJ`{%mT#hnaA?=K#( z=5wZZ`D88mu(FFuJ?OsPWhsJo!+F5NOr*^-Y;e)7-;;29JX|Z5PdE!Tbvb!%SB%=n z#>JhjAML5KWdoN&1sHeUrRGt8%RMaPQL3@&=GWhcVS=^0hsh1@TSIr5ej%{GFO08n z(-OrI;iw76A)Gv_M4K-$%(XJN`LkhzE>cGznTm?4+J3^lXUKtMKiLDl1GOvEiu)XY zGqRuaQsF@7PQ&!{v};WU(uGvLRtsjAi!73FIXgg?b-1$x__s>kNq|;e)i&^%UXA8y zo!va1Zi(1i9wpZ5+X1K&{Ap)^N=>@0(Kns$luUY#I{@%LRn^hg*Vo_wcz>ppD$xH7 zpc?J%?MZjj!zm9RJ$fYJIAM+MFc*2cO=%n!CrBA8l#c;);4Qcr#35P;|IN7b%h1?; z=4VKr*{-~3-Fz*(yV!~YvSqqj4>e1)RO~~Z+wv7d2pS|0ha$9D@}4nfd0)T|M{NQb zgD2z{4vkH5aAV^+b)v*BK=3)7Diuk1cE~SX<~)cH!m=i=`6=^qcSk(LZTG~S+2|;e z5HOQjQu~(+_u>oDgU#=3_2;PVpZUY#)4?_p!GlQSbq8%Lv+V|?;A}X&-|63-AZP9C zUo@wBssm>>Wo##XI+-&9=El#42~+!N+LL9SZimX@pWl-awu{*O`lShnfBEEIvP`(1 z;-|m8hmO<^XDVHpl>R9(x!ysz;Wy4#e0T-dF&}-leMOMP6uOz*aHMAB4{{9_vmZS< zhc$hd>FMrIT$1x_sUz$x4r9VavIs`^13D7hWw%z&me!^MIw2gAXWH3DCz*C72lHb~ zj)&uf!)>;wr@O%7#-_WlZl^owpwMW=k7Y;j;uo6M9#{5M$7jy2^n~4Hw(PUa1a7%B z;Y4Y<^&Y(`-{Itvr6+s-a}7qaA}xfodV`=hkYlUB^{S@84qh)(ovcsGc;Hbj%~ak& zc=G8&LGkqu&>WvOJ;VL{vy39~_!6UlzO&JTUA@x{I=$LNMS1nd*;YnZS&rKF>I*hX zodSf`i^qQ2t(>+NF zoYl@UI+^^R&vv@p-?XDl+EeHGIn=Z&8YFWNTW%O=f70n7$&}$@ZBYF!%G0U#bl#}` zv>~n`*$-R-*=nCFj&&T#IX~DBEM2+Mru=AFS+l+78UHmBiKKW_NLiV=&4YLFQ^4Fs zupXhz9Qw^gpMwJLy|Z|4#}_vWjF`BwWAOh+)0xLZ`Mv*ttPQEgmLXzn8H7O^WgSb5 zeF#ky#=ev-r6OtULzb~Nk!36~vW-HNZIm*yZ|#;TOA->2-+6z2kMBSJOz!(W=UnHy zUa#k?`rn{82ga;%>iDr^N0P zyPS6@R?2+7_1aRJ#98msRnU%gzj?F4rSKdSjAw4P0}$Ks=s)fNhd1zG7X7g!s_k9B z*?eSS&VO;9ly%UEJO3s->GiCPjLbltuJaZ*r zz@}69I7gv@^w-AZQ>*GTFMVgcbIQSmkU*j!SwE%ap5WlCa3ww;`rp>H>wbYYo(Cz@ zD&Iy{=fNfUi;u*mbVFzYjnSW=zh6DLxBDV0H7rMUPJw_|WL}Veb)#?s5XTY-q@cN- z+j=(0VzMGt-BA9)AQGq=r&sE1Ux}nd&Hsv}FX!TrG?%{msjJ$oaW(m5>0JN?d{PVmohkZCHh+ad`$rx@zsv)1t1yt*MS4+ zbLZSaFlIIuT$r)1G_Ar~-nX!>=!gFa7Vjlz%=VqQt=i~4Q1Cxf!S3$v^_A&s8Gqm0~0Q;9Y+(vvJ$9af&n>9uaYKWtx7mIWWJla16gX zwJybazqKdJKj6JylA@xR%L4ut9(NLo?_1J)i1Og@Jo+%ACrlgSyyf}k{fuqtZz}3l z=*OIcf|&5=`)e(WK|{;Vov^uvNHWUmD$fgdDcG+X2I1S9Uv2NsZuTIQ8l5F}<1lMiXY(3XZNn z8>adX@3)?OTE?!s_H22+-=iXGWJNe{K^LIIZv8l9_1>}i^2Xf6>)PJ4bAei*ykq8dH|6*ZTr%jxn1b zQ?I{ywePS&+l{@reNSVhXvBJ{A=77QexBME@x3PJlW2d@?-M?tG+&HVKC=a+IQrer z$=i*;*dQBA(rSVE(_8=;$NC1m)p7l%rC**|!{fsahQVho z)6Kt50hRJjDNL z0RX(QU_id&?cuqZPyY_HbaLNp=5ilhcoT;y9`mRAf#63)psmG)NZjd;Pd#vWSyDnm zclG^4&{e5jvbM32)DA713jDpb^+fFW1znvI@)?~7Uof=V`mj|B@`+d9M}CyJ{+^$6 z>fgVABF{g^F}~gUvF%QC?1qC2t#e|}y3Ufjh3IJpB^y%rzBdPEjGQN-7|NqnOU}S@m~) znz;WP?%I)iLKa(f%rn8dmNf_7y!K1iU2{?1qND$r`w9=yX3>{aa*a6uT7C{bVeK(} z1+b0-wcgB!X3COKw+vAzREF&9jg6-BxU*^Y$~n_3ucoOJOMu#4ljnX*xNq&qoj=`< zlQ}qb#$jffv#Y{W9w1!X@oZo1QJg% zLjidR(t~kMJ&Sp@_={%sg3jJBzD<-O<&VuJU^>Gh>En>;Ypyeq7?3|RZpQ(siSc!1AJzm3jaK$S(bM#Q7S4XZ z2|<;C@5?HqE#Hy7IWi4IaDSBvUT=$P?PACdWZO?$P2*s`U%T|b3A@V# z8wW{aa2>yrgED|FkVJNOxVe4X!P#YMM|th7?X!LR#ol>%JoxaPm4P@e^7h{$u!M|Z zm{=*0c;Z)p!!}L@);qhrh;E-nZ{BnTszAs4$92Kd#8gfNo-h|+1ikro!0^B3rFSDJ zxIw9Y%3KGk-Z;sDH$!^8oCUX9VE=1rnqYH!8Uz(NY3InnTP#Pn$( z{~*2tyR{`3LHWUeqoOdjYN?fx2Zp&dmvnI|s=jK#3aoDkN62QoY?#$b>V}d-;`stU zb$pPTY`d;HA9%y}yxyl@QTrcvS2Y;n`#Vy^KxkC#-7tnWAk~L4;KG<*V6v(r^S%sT zdSH<_#7kl$kaEWP43`A&em>gE!{w%cfg6azFg+p4)VeDib-vs8U;;qWK^@2NW&ksl zNc*=qDsI2HJKG``po%u>|&jH)G$;*v){ z!hl$jVNg9bM*$P|x%Eg)aAps-N($;Wbl_zOCA39HSNDUjCO0=XZ(N6_a3M>YSfU`y zd8^|IIkO5n<6ahAlV`oWWqA0k=xevele)3Thf}=KImJJ%JN@GoU)PbWy~;&)pCPC!oFXRo`18 zk#f`GJ<@N)T9;f)MZ7>p%Vu=k8N4U7hamqd|lqQk?E^9)!z;7l0%A z)X?w4$T%jFpll9g6Vy@sl0sTG?zdQPtCF+s&PZ=GqrhxxCUZXjP@&4+>iq&?^%^leThqQc){)1EMw~fX~h*#UY<2ee4V_ zK;m46P}kPIwY9aWsVT4*qSNAFU}&Awl01v%Gg|s}7Azl9{=A6Mh$aM3N9uFQW7OZMW?_(VVrgmoSi~)^{DbOe>3Ef<2t^4)6YWM>Goi2 z##VuO#A^pSB9fr?Jdk9YXLVF2~(l^#+ven264>&J%~Urj9a zD|4N>vb0n^e(ctkp128$;e1Snm^fm*Xq}5L1)b>CTl?E0_fVil55k4TbpjoPG;s>!Djd#zwuYiQgFOVQ`k04T8vg?YXnF16+cZU%Orf>t$_5-3bjH-r8dxia8~Hd02%b=2|U% zEi=%-202L1Odd*}uiLv(j%b_+C)9TAEatXv$US`@`sVtJEnRBU zcg}AJtzmtLZSwl|^J{uJIJ^(!%{Tx;x zR33D~59GfEy&=%NEgf=pcK#2yrFW)v9AE2jv|mtAFl`njwMjt(l|_l~e*UZ*zvZWxAfvv(EP^X5rbai!M67DoJ)+i$; zbX^QE0U?DMdD529Y|}6%3c-Lg;fS7{2k~|ur4j6IO9e5gqZlbtx0;KBlaDuxt!Wm$ zzdCXUNWlKhO72g>XLs}e{fqvA1~bF0k6Wd?KkmGY-#-%jGU9qh$`~ZLlS@P>rMElb z$iZSr4FQwz!HXE0u+wp$zhN8?6(u-S3-chpYT||!4rz(pLvf$vI`I*HF$&^8H^)I~^8c6IPuWhmU|hy*u$&y`*;L>!qIOz|T1HjUwo6l$M?c;9iCC}cyYlw`SMXy9m`f7^zp|A;{ZNCPV+V%ziS{IeGY5$|a zU=l$Ho2I5G;g1k67sFYv=t!&q78D_wvc*F7Si1Lrc})ca<@8ZAdn8o=19;cBIHppwSF=5AnOdI54qSLap$#|5OK+IN4nu~=_v zmwswh(9@aU4goyU<{>~IxD13pJZwidO{j%mvXQsavRg9mf!^U z>XkpybUfIEK5d=!339b~?cuEgamxdai-9F}1E?Vcia>Bu9sGb44~t|*er`*fovb~G zJeHb6Z@LiL-3!+SHSW>QJOIV;f0{iE8Q+1zOF_cm11sdImpliHq@YbXA>sj1U*)Ky zA>s-4)y$_WVg#buu%<8uNi9L=;MgAZ&UHNMjG=R#JuCVd)xD@M=ltVW+jEe$b(J4u z_}Lzdp3e`2nPjBiFQXsD#Jm6TJQc2`dqGbVM2BpOAoASUQ^KW)zNM*J+%RTMBj<))(_M?2QKU1m($rD-NovD&4_v?8L<%+dJbacaBshM; z9O?J)3n;<`2oQHpZiqp^1J+?S2*CmPoiAN^<~8!Axc9bL#Gmp0gT>5mYMqdnz;pcE zkZLyw1Q9pHxaJCK8QJ$CP7)rWlTk-$nr_JY2Q>H z5Jf^DCp$n}=7y}*F14ng$L4#nGTW&xC3z0K5VeN<=Z7$Exv__)OnHjI4IajRarm)T z6UvQGJ`Zwlof^d-S z)ZDtq+(~ptD1q-4_-{W^v18r32Vv`iixSS97v*qsl4*Ea0KQ%%8yi8{3TK%Fi$&%1 zB(ZUD=kSS*X!ddvh$|-FacL%`j8xG_^!kgYN^;bOvu4QG+6Rb%g_V3Y_Yt(9tE-?LNgM@OvW9=|HgDGEM`DP7xcq*nuS$@{+rPn**yv6)Ki}@Y>YfSkx-+ zm3IU5ZoA^ur$%Qd(q^HEmoXxL{4()hXXcane}N3L!xBtUpNGLBrpG>LAIOPypG>(< zO#g6`0moLl-X})Xgw3KOTuvtuEj%IMkBF_6mk01d(A=c>K`jt+az8K-pvEG~`!?yO|nds1oAu}Qjqs7^NnMRT5P ztUrwnVOr%nGhPmP3A2RCL5megu~NYC=NHR=6gO#U2}K~YQPYR5z!0DdI+Y~}f%{U!)8mlIZck0iA7DB*l+IP3TK@y5Z%8^5I%B8IY`YY!jl{sL_93x3b zv*gXG%BWNDrW-1g?UrhtoB`Ao{zECh-@@JdLNYZ̾h;IK@z)H^)LkMyU%jJbPw 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

G)@i2v z=&)0fOhW1P;#pFvgm6@}H?~lm${5 zIJ<+WAmO6XP>NE9mtI^(n%}`x1)f5sm?~#;8Q26vW;a>%l!XTbgXRO-8VUaxotM=m zMm@9O+uZOd(}D8INqso?Lm=Zp4;hRVvs&>ZweyLWaB)Cv7Xxa(2y)!U^6btI2n@gx znM~%z#~~AIB>8(vfHq?ATi9r4c{e?OtO=$4Mg0N@RlRxhCXgg2BQ0{v)rpM zgtm8*zW-jWQxhO$2a`qGzWGn@F5l>$7BO#cP$d+Xlz^)%u;;b_2|S5)E#uCZpRC99 z0uNxZ1$d@p*lJzNJJ(cv;X+{IS-svD4UAn+8w4k3nEU*Lnca<_g&uG8fDjR(a3w?W zHRM=YBJ|1TdfXp z_Lr4yZn4PuUDOxao`FnM5V}z$PvLa4CBAbJcH=@rWKV0Yayg1tf(jfBgI|FqE8WEx zauhvg@GSnz9|2HA;HQ{!iHeBOv!Z<)T>`HW5JyaPM)7VVRW@R~_W|8%c3wR#5eXJg zG?b%b!k<(u$43%2Z7<8A(&z&JZVBJke)Cz#-Xf@4Uio$kkulsy;PH zd&|I2#Sy|ih@N*PcLHBJc`5rdL3M&1_r^saJ;cvn&>ey& z4!tJ|Ooi41pNP!dbuzt7uC0O5wx_FPjwEE$Bb-ShW?J7a`Av7kXj_S0>ArnqV}D0@ z|IE3+4y?l=E)TM7XyP2?;qr4iB%}nnQG|qXP`HOZJ6DxMeF-ZMBMS%#qY=uV_&ofT zD*@B4h8Gb_)P{3?Jt2B8UMcX|qucA)G%zj4bLbkulSsWV{Y;ZQZ!`FN zxPX17EeB5qZ8cYQaRfcN>}KJ@-fWrQB|pIraWvGZ3&Yt&3}2!MtHuwjofkcb45FST zDA^()dX2M?1gT@qb@)Q#R0LqPG&u|@Sv9KXVzB5Ws54p8?5?-7+r$h`V9JWNSU;C| z`E)l&3Xi%8q9?)*NE`@ITrFV0Rdt9&&xZTm!o%9Ef_D=(pWTB7sJ}xrV78a#dz|#v97jOJq=$B^NE?bgoEoHTBbR= zbpxf~uU}GZ8zZ$Jn*Ov|kF_ni_+6g}VHv1eeD5r(mV)1k3cEP3rxH%48;qrRLVBiM zr*-{+Hli9qF;=^auE4js9LrTYwt~h;C1#0u5=w&6%g|mR4tyos=3aWsO@GVlo>;&dpnC_ zs_?~C?;^7JLdRowR)<`QRE9o(#sg#s0lMQE2SHl0#7!2zNLZ%1j1`TJyF@j*XYDR; zY=BRm+GB->rPS7;A@NS!7;LALxLKEzIx(2~@?&ID>HC`Da#!^uL<>6!lj+iu5;w#4 z4}er&5<+cLvU@cXM1AhYDDffoE}AO;y3!dN8nOmDzDPSzB^y|X_i#xk*VdstTGTG7 zOH@}^Tjazy+}6HPe|TVaW#v8KlJVA%!nztjz2I1`rDiegWv6LtN~imPzdG{6OGb5Y z_n@m<<#1!c)lMf31e~g0z&^@~4vg*kYyfm&{gQF38yik}m85dUR+WD+l?R)FfdwUBDt&A_8Fz~>41V3JDQy*3zd9QwW zE4F*OPt@4&bS6z#XyoG&JByRI@P*`(5)BEkb#8@&TVQl`HD~ z1Of~V330T?@bx$ss@;<(Rs|NWac$nF>Hdom{vc1Vb#}xI1CI6IzJXSMFH@|=r$e}F z98^@nlM}=qYPZ zQ!b`-`2z)eLiud*ZG}CMKy8`x+KDrP4*3{TIIU)XLcJPhjq6I0@n>k9{)7nN>?d_%rvG~%{`_gc7Xt67mkiG! zUnbJs-JPNu0ULzq0l^KmDcL3L`DB8;431-#6T1Fye|=8wsIr0$-v!&xCQ=97rPP{c z24dCg_IK{ZwO!m;ZI=(;6He}h?fU!>#hF6Rln%Co?+i`=Rj1D}=mW!U^o!Eig~Clm z9@#1JUfB5>u=W3an53 z_GAK<|CIvM01}NOYJ{i0JwX9WD;3B}6YL`P)J>myzN$sMOjPs{Epx3rjNlw36G`Pt zdl$~@me-OeD#-OGH5&u+Nfi#l%HFF#ehk)Yv5c7PJH70DJtAp_To?#3?POM#&ELl; zyE|Au-A`m+>3Ng*=6>~&2J-1`aFeUy+@?8e%?@$Kd4mLce|aq{QSLQAqKN00)}^7y z)1$#**IJPK3)4F{<5pDTR!aA1alY-D$X53!Sp`~hS5L2h^Qi9^x2IfKd+&7GTD$TV zYxz-&3TW_P3L^b6G#Ku|r8kYM!F_`IYA@#c%urTa!Owqoh!H)}ukE$8aG)TB4QYp3 z^78ICw~QZ3=d;6O9S>GJ_|aCsybB;l*K0XK1f+=g@f&v9zx{d}Fd6fjEd97tG%UfHe1_71g*Z0e?SmZPJ;j($LM_Uw8JQt&yh|7C=85kHQV#U$>Kpds3ajRHJ;8PvQihkAy`xd-dMqDK zF&&Z|yL_#_8ZQWx@pU1Ob3q)}eNfC!>d>IUAnKhL9}+E<(@Tyf#y=fu2Aye$b( z$Qk0Z865E(!n1Cu@r~Zej9lyyJO06bq-^Qo2luZ}8jb}I*96~aaS{Rq+0h?OJ^<(x z0GZOGs{!|n%c}?6;)&fIk)YhoL0ROyzVv*O+1Y}8{rOt`T4YS)XM@B;6--{szgmJI zm6p6Za`6e^rX|aAGdt*LevOV`R$Z2w50R)dhr$tWhv9**|FD5V~sPWtNqN*MO7{P!zYA9zvh-}@bU+f0CQ<#1jQhDUZ3gb!K@r=HO zzk!8SKZ5ww`k>#1jiO7Hh92iXA)XKp13W>tMs3;KR}aG;=}LM#{&UNx>-9P*|5}=S zPSf>vR;g^JCPR&4fNiGlZ1!K2)oqBOp5Er1(cT=hdp}m@Y!88yhzwm1FtQTMT>RYR zqjmS!z_SLh`k1uC4tyJ_(dY_Np?bJ{B0jesGq=MaZvo}lE^2gY z`$y2{ka}z_BT{~oOZ;+IwB7-+O4CD}hGIQj#zqDk2X~ zpi-$GQ%}F$aLggjy>QY1zpWpqq4557Ave3iACsIuq%(>pp&ZIDmfD~Oxa-~D5cdR4 zzz@E)`oZNk@@FBi^8{0*aOrJ2)HA+LWKiD#zsI}Zci6AB@WF{RQ?-{JZKw24w|BSu zPwF`STw6P#kg83tM5t7_e_(dS4ZxDNOfQKQhfxC&6{M^0*UJBFKWjK@X*(IB`@K;u zKYiFmfbVMrxljK9n0Z)G?C5|DoTm0hnzo5VWemKywDf@wT)sLo~>l>&&=RWS;i{zh(fdy>>ReJl;b2 z>va)ypVo(vU8839jncUdrm?_oc)9Q)3QSSFXP<AAoUPuaD5ZK}3;3@sB*TQfvg=ZY*sYuz(cQ5Y-Kh?v$sFV#8F$D9Y*VMJ1sjZ>z>hE^w+9Je30vt3lg7)UuAFaOaoBqrEIt>r@8+K+r7v=J6w ze+u_329OUT0s-%qP&AbS#h}stW@%T{x=`Ll`0Kvex59m)&-);kaM8>EdB=pUZi^gu z82~4`u94Br_6rtz8M!SNF3r_>6Mz_7c=yJ0PSO!?Q@^>>S|2*09LZt@^2BEj$F0DP zEx8lih@i`O%uYox>%%gS^G`aS^VJ^rASCSEMv9_=eu`(cKj@i@Mw9wMtTpXgh9XP= zkzPL7WXTUFDHRy^ilwF6)nXm*{a5a}eGD<IWJpmsI()QFjFS?Uj26VgPE9A5%68}UGwNzcNuFM&zGc!xJ`dEGB7mI zWl{ovw}X}}qA=Oh7^xwVUap=3$X7^e1vHTrQHUn?Y~#tWhf|v!gH7s(Qs863aBm{g zE-kQuG+%t4?^INZ7hzE7;R*C3=5`r#!1EEK&A+IDK}3dh>gt{T`9+AsJ_GEl8KLekkQePtdoMeE=hx?^zFGOowig{v>I~RiWT))b-m18Qw1JZ@$zkU3k+kpCM!PlR z3-ecEHh&)D{{obGHkLh4`x3S>?_Tf;h&|#H9`I`+lw;HKge*_Kbu2IJwcmHK| zg>NtTJLf^pa!n!5oo?cJt<%0lh1p-|2M~56eK68>zT|iiJqTm{{@hf1L{n4aa%Xgl ztA^A==R7{RWIE^)`Ny-yzd#MlpQ(+s)t0ax2;V{OF^smG0G4qnY+3}fw;s2C^Ks*? z@iT0pWbgmzw(ZYvPTx3r35flJx~FeGZ(nCl8yOnDq19zf-FWUlG4=ny{>4m(?Sjic zCGhEju0~DmDatFgB>pU9Z3O{gLbN-y`=2&>XBFS{IeNbjY)tmQOLo6#Z}%&bu>6QY z3}181GX$>?x1^SmY%+T|n{$q{pOkl>ZUEfVAvz`|2K?tm1V#k4b?J6@d`@UP@;@y= zM|7T#9vwB>NXylx|GwH@Gn{7o51?Cm7oC-BPd9&AG#DFhG?4iR-Ep{}j5_3++E)9x z*1*Up#o3&E)!Po7ys?1i3%XRx3#xv`sV;t%+4#bEu{Wo-S3aIMcMg!Hm^kO~fTLzA zB_$;aR&oxJYkI;;%YViJ?Ki#s#{HGcyg(u1Z&foA?Pg-J-B7dQ(&p z40{W!EDBBKEKa@D>#j#{ z3F0F^%H7qw_I@$cM+zIV0fCWt)1$Q69%+H>esJd3E+SOAJYCq&F+CPj{QfGy67{mtQ3TL>33{Ik$@u?xN^lZHA{$dlLEJBA{@^5!v4@oK|mB zF5rK#m@-r~4vhDn-P2ifkQ&eI(3S3$gt*r`n|~*a;*fi+L_;G#hdpZg&W;;VQBmgm zV)Rqn8@wr0R1m{zFcjl*F=qE78n?qX`)2hfUzGBjt!j(DM3cs zT{Lq?xt+9r*hI!Y_(6F1L;PvHxP%DVUg*qi!!20iI|-biH6r^voZyxEw8?}B^A9j3 z<*<#}(Fst{b%L?+I81{}S!v|>n?>K3ZSCEDMS0retq15kS7Lf~ACdsUIigUnnxYGT z9UC{;SjUL8e75e+|Cb)ONAKQTJLxi3AZq#4!yw!Sk&DJ!qf=Q1aKZ{IjH+6*l@+%p z*S)!L2&b;R_#AlGcIR$~*#!uZt>2;!;n0FyVrBnF)44}8{l|ZNm6%HzNlU`YWlEUD zNG>aisH_mVCUV!@$)#9`p_ogqp{ZPR&;6DOxg`_JEiw0Dn7iNm`}>`r(;r>ViG8-u z`}4XypO5E_#@DOjDuZf!`@kP68lmrqg#_NERajpGGeE2p4@k}h$xE3YQ^6J zXfD>3XIiqEN$=sP>~5u7co<LTB^j^L%>Fw$ov&Mf+=anKdH-M2#*v@6*(6Vtqq>gs=8G^o%1!Ofr71TH*F(LNWJC%kO;v zlAoJvI6tty4(k8jCIRaY*iIYgsJ+>{L91P^LEMg}-M-89g^skvUM9>3-2YVh;oq>o zE|u4Ez9}BNQLIB6u9)3<$(!{+E;^f1s>5e3h*ufzA z#z)Z6s^7rmMOe3u900cqM z<}*J(zaVe6&QwL$(Iu}(UsHIvdac@!m+~A0+8p%h8_&g_7$k7Vq*%dW;7utX3O7UQ*BVPJOWB!b;w!0aj^#@Yw1-ZHNJEGb-_IJQI9Ls<7 z>3<}FYh-BX@uyEee!2c4B|e=t;J3H2I8U$NiGH6wbGY>r_N2At1F6K$0Y5$D>6-ms zc_2deO^=!U7jTOq8fsZyOmVP=VbrUZn=&j+XY|iFj@Ada znwt9qI57Y~U{EezHUC|mWtYlG_^|+P#5WeR)JJ^hX#VhR`iTf{|tu(kvrYrJ;IQ`1k=cXs?L6$bTaCsjrz4Lms#StEEiWI;WJi?=L4< zV&G3J2NglNsw4TY7o6aZKbF2EVx#-ZOr*h<&uYI_NrDK@3IOmo8Vfo&`)eC=gn+O$ zUYTgwk?JJI0$c6A%)wLx`qa+{l8BGKGuwcmUsXoI3f{eQ$HirdjLXlR+hRNgm!3EH z^rW=3bm|I93-Q~f(!B}zbjjb^+h1Gmvd5CG*C@kQ$yO`DuBqWGmDJX(WLnkt``ugl0OW9*bNdk}*MZO#`wjYJTwRj;aVd|7$D0EL z$rp(F@AK6=xX4LztYdT4g^o4G^XEBb$gmLX>o*uNj&GPR08pDG-?d!4)7Ul^nDo4HYKF^12%a_K zfT{|2AfurtbS3*ry}Dod053#li4?uM`>JABKk(_x>-EdWWP4JS6{D=V4#`<8(U;07 zuc^j` z)Y3st67*U794RK!o25^C0zsix8^G8AF7pD|<8+B^P#OmTfoYCCs3q|*($5m96Y;X$ zc)qsP?cai-ph-pG6_Qci$ZLYfjgx~9bEqT+sOh$_oL|h6dJua{Qsgn&?$~APg7N{1 zGL^fI63XjTW?!?kvSL+3vEyrH4|Xxmlx>nuq68@CRR^x@g4WP{+*R=rRO7#WFM#4cFfib2b*VW7 z%Qwthw7t*w>iN4^bh_?GtRWWQ&lG0Uo`7S!sWnNye##JN|WfEN1# z;)2ppT#OkynXVnP)%e<9a)j1Up`)EBS0-(S12{@XuXV$ z#h@o&n;8{>M>g3fO!*467W09-n-R3)PI_Pl9CMg(tauOOW{eOpv*96Lef>}#9TcK5 zxWXBv%yR^PzLFp}ToFaz(T9VDk1|FR9;y#NY<;jQb5KI7o7t&wj_PYP8D)AJI9EIh z#>M7nz?BP8H>6iOxLcknzvBvPK}N)aABh7&&ej)f%St3-@i;!saaB6@{v7Y6@}1a) z9dl^rhx)Iz9w{DLujxDeb#;rj=lxs`*(C#5u#tfQ@G*=yRORMISgM?kk+fE1q*Q;F zk&y}7U1=L|uqoS`rn&;I+u7?rD&0RlWZ~a%rbZ_jwPD;sH>?)Eq!Wrkf74Af!mOn-ylFI(c~QNHl0PmA zjI9A6Gw~f0J}W3FC?sukG5n1%OQV3!yW0{@bKB!H&nhaPmcPYH^LrPvd?bqN|0@LZ zXNkM2TPp(>wLX{H)TkrXpg>FSq3}pL(PUmWqJDcWZ^b7z$KGtPrBC+tjcF{JwJVA%z=}fdG z`qc~H}s(#&koJF@i|nus+t zxFQhsQ{EXIktraw9@>YsHJ-lJW}Iy7n2o*@`*5x9b`yJcuikd5yvpmz5f^U{H!cY1 zi2j`&yZT!=rj6JOjC|9m7+)fcHh%Z-?}^P|5s=4LcBk~mZ0B>tpH?C)E2^DQJ8KeL zd_*TbHT@3RdT{xxX6bovnz3!Z=Vz%@COo^#>k;@k7|c)2ZERH71MJolIsV#@ge#sP zsIfCkiUc!GsQR>3F)xd^f;*6;AfElm0>%0ABT+uxGeQ0j45pfznrurKhbt1#-FZv~ zWdF#la5-h6sI;Ri%V`-py<)sysXnjIBlNl7|^8r!HanZ1}VY#VS2>)f6qDxn!}TR_Kjsorl%QjjMUS^S`f6_ z!i&HYfRhxn{$Y=YBA`w6G+46;bU(B|xl#RjXI+40?=3Kod)$t5P2@J#AyD8lIB z85;zC_<~~^RPbS*87l|*xA*U7V~SeWXSlvzh&Y${=pRw3_w&D~U|6UX0mh5nNWF?E zij!A|k{(F^{5~)Pf#6YMP^*RMdNkc6HPfGndZT34|PhT8*)T*dKn# zo2T}vqS%PS`P^I_{w3H{t;iy53}C^4i*}*M8UpcEt1>ci)IwV8o@R%X3_~Eny(zj{ z`g|7)kO=U){N+8tgi)G2z+@MPLuesKAYToxv^=mE!+&9_vW@TTi*&xbIhc2)=^MP0 z1U)=Dd>2@VImclZ4WeTn!Q7!VGTO7o=sr#e#vy;a;3t zbwvovAxMeTRV5{!)DsxEJB9WF_BelbI2ucD@0U>9U$!9x*~OiIl}*uUQk?X6)pL zsbGS}=ow3E2x3fk4b8Uu)v-b}SUO8AiM$xl**HpVGSm(j^oE_lN~%>boCJAqzUF-Y zCJqG2efW?&KO8>^2}VZ*WL$AR(e^sQuXJdm#M@PKj9Hm->BjPG+{bj~tXveDU zZ}sd?9&8D>O@4mBi}`9^@P}~3TIcj3h-}0)wS{5IVz^3AWHT7|Mtd78!(-ZLG}n}h zb-2}!+gabZgS)&+hn!5MAN6}_r$UEnbRR3GOAuKDe|tF>U;K+s?Xoo+tQwZS4PMc3 z;ajXocosSs>RB6C_smZg^ZM=Zq0;9FLIrSD4FC0*1*vt)>E5EsYwADi{tw6S4ZC4rruKYeVa`oRlgH-U zfIp6pU3$!-RyZoOZU&`gpX{t~reJ+`CPr96!pt%Z@+>e=h(!Z_ z10c91gF$kIoqTmw-Rn3}j>#-!7TRZhGEYjovqVKj=}z3gna$1Bzvns`vmV>~ySvjH zly~db$HrVLOxLz7@0}!}Y-I&y$)VXi_fzW2U7`l%A?xW1;wurmJDuP^W z&`IzyP!6109C038>HBYD{&%S`_re%MGW$RCr=Qox`@%f%>S$@-OF+-F7;)Iz&EN0m z1CS2kIf!HXy0BC4GM6Q#>bpxsZ7lRlG;HmReYK0Mr1$s^ZvE)j>JdL-z2>8w(nEv1 zh`Dajkp#;sypY)bMwDIaf&EF%%s#(5^Yetd##32g{FZnU)`b9yo#s!A${D^cLf$?; zGaN}GP$)TXFGp z5mC}!SG$!mMUS6z_84cQju>jkA9G72ycPX?h3s%St;=-7(U|XMTN|{g_3`Xhpp0MB z&aB7Z=YfNs$LLwIe6@7+DIFxKrdk8eNWVxTXQQmk^7DEcc31m`TKepMt#}1qX{f2% z0*Li&w4shZCcoIAevbL9xRHYfL545~*aG8neN)hm4*_)OTig-&YnkYA!~%ZHyB zYoSb}_)Wj(<`Q{bme?W7wd2#<{O9Gp$OZ!y1cxL)}WGk z`c#6kRhygKqjpeBugS{;5EO5l39N-mhmZ<-B)-+5eAtE4r~;H)Xx?^^_GQf1y1UwJ z_83VrAFtW`H{>)uW02}T#!NG4?D|ESFNo8rb~>bEPptquF}VBl=g)n<9?bM*&(A-4 z`b>_@^3sS;bF8z%Ic@EHk9(U8&VJrxK4vX3D6oxwap>TgBt5hP`~~0pjQx4~&ZW%^ zf#8G2O9#tm_h+@=ABAB!4CJx)$yLqM+yp9mI_qdb(Dx(S8A{OV_pCSvSK@ma*9 zLfJ%1UC@`1KldQWqRVgy`uL7Ro)$F)A4~hhb8%*$`rlv9Tva`Y`Mu@Bwdt} zlSweKJ_OP0XVG|L^RAfOrG}=ZGN#-l@q8Hhv$Wa}imh>|lK}2CS~F&Xs%?zyQiAnDh`(6)p~A%xqa@ zH2P~*&A>2AdZLZ7KA-cTmX&C{DBQ-Fva&zv?ij_3RrOngLSC?s<|{63X~*e0j+9-Y z2_oFQymE-Y7rjzB38-eI9v0u&I(1ZQ^WQ%L)-535NahHYdYScEH*GMH;0s6eFw06> z`kqxitT5wzc@iTibT-jOTQ-YmVi_289np9Q^752|r+XkSS~fb{ zr_Q|6>INR_{g}vETFk-D9auSRrXL?3v^=dtGyxGD78K)imrP;^U`!aHn9Mi>% zUT0bQfFjVhMI^726;OhrJn@L z*wXooBmj*^yr#ZWR54ak>oiEt{_L1V!u{;*HtDoiFJoY_B}Q1) zgSFBM$9T%A#8Z^v$?VArXLb@6>P;f*koEsmT!MU(>Xco}Mmi(|-yj46BfmTa(^bj1 zKtgF9pY-weKE-O4U{e`c6B4plKWU?nfl6k>^&JZ;=Ele0BP(h~jw6180gV?yPN$gW zi%U%~u#W;Uc(A{HJ~!Am0xWLzDHMc!u4%QD`B2V(9v(X3^+@pSS%K`QrN+hygM*b} zY-}m(w#sKNlZOjC*+N=cju4jp1JkCqz{4*~_Lq($NKeZl*8A>lFD(4%n!Xt_F|SxO zi5>!y#^=u=&BB2`zWyGdn4_6K0uB{B`B>0>87h_=gx+iRkFmrm47gSKt!~D3Mn*2$ zhVdvEw&F0*Q7Y9vlGxIcy|wN+=FM_~>+J(M?fc~4Uv=xJiC=MYCBtiKt5*ZmUW1ExWXzRXG4I3o%B8W7c`X>KVRtC}Cz>O>zyH2> zyhlLrg9u>nv#lHwa1^Yk=s5_hpwB0nb``OP91`=Wq#lAsQL<+}R0J%{Yw5!k&eV2~ z67zz9u`u{n{g}L&L44piqwom7|7!ar7}Wdkx1J(k3CpcJ%9|kE2pyV{{1lPGsc7s19JeH0AN}1hS1CbKlVe7Z*Gx*A_bH(>B2&Se@rc8 zmO#(_SQh>PEJQU`1#3ZinAIfc%HLO<4)D9;R@)_jUp>G(Ffh>Hzk0+aXsh#JB1|}N8D8^9O1f~mu$rL~DhcYJo-oSr zNX2`i7H;OS7@Br4-LqdlvoqpC%W6vidbBE)Yu8$Vm(Uyt9>Cn_q$Wxr>W_LZeQIio z^k@?TAy2N@mLl-qa6o7PI}E%ln@cr`zUl7Wz$bX;qse@i?c`2<%f+gKoHH!}e8vwQ z4~%tQ1YQ_<39HfM0Bk=9ViU518&Gf?f3}PmI_3W!vR8lkz~~@h?~T_&?(%`rHOS!u zyiVN#J1g|O&KK)5oRT9!F07%b8_+Cn`RjNQYl4!R7zt*A7eR1YVlfr#Kp>#`A}85V0`ijt$OxjBmwy81Rlk?oj zD3LyDv6}AfoL43grG@#fNTV^fOwW{FoSSkOC<95zm~gp_djgsh9?GX}-?brazA+xg zej~;rqf4dE9%I!OWUCKDOamT25@dNIqeEMoL^==07(>8PI8*fYBw8pcw6qq(3OQNFhozQ~*8-KT)luH{U z%)tZ7E|2`Mhha8cOWPto?y=S<;x&?J#tGsSJ6${dc;~?Zz4P&I;|>@*Y6Xo(1CvpL z|CswbNwYz1lHcg%jt_h`#;v#{vDd|3mDJHoOLMs{!@!+af}GDSOc`eEmJBa0b`enX z>j2GOJ?qmMpazeTI7>@)hrFjhw+EZgzfUx=b4?;wRaGOJKNaSc^`26Hvct#LLTZJn9X(e(4GKuv{=&PMiJ zhU6135HLEXTwms%ul%3*BDWBRuNN-UdrFu%dlQPDihaOqg(UqbC3yQA@prD5aB!3|2V^H`;@SchSIiLQx_Upz_HhY6pU%phds=e6t|CsaNfCd=Tx3e+tnvl#(WxZdA%c-V6`!^=+2V8kbs*} zzf3;j1YaR?nCf-29vqN2*mR+cg+=<=v%+0PV6uE|>`V+fZy-X>MA37MNhld`xSXsT zD?f3K`|!ccOfR!`#LE%!53tr45=w|>i>%tIVz_^D|hn*_6EMKtWk{V=J*;*#zB|X>X6BcSZewmG=VX9DD7W(DZd>EzS5}+A z#}`i;>TBouVp;s~7SO!OlQ}YhrpBcRNO6P4u5|g8Z>UhbfP`5)t~wu?9i8!8zRRH; zwDh1aCp3SMx^SacMA+2KjHp>`?mC*$&`@8yy)wlOu7gM|bx}yw&&S7S69}T3>|mjp z13C2PV?bu$J;@sUx~;Y)E>4!KUnO$#ADHUkV!LQY^>lAD*Gs?i4dIg`6^&4OMasGx z2~1T4h0g-nt;fN*I?ug zQj;YaKXPii65N-tSN%rsV+bhi*ax0wgXLE$T;{U(juc#B)D1Z$aIcqdY1d7L7p$#rNWYG&tJ{<1kR)ZO_~n-?P=0LKYQPK)rUVNo+rK&r zSav;8359}!L~S|$sBb!>!rj8qz+ff4A%IEIM+Gvephm4}dN$5-%ZhKKR&m(p$NWxx z{srhggF%D)i3Yy@{(PHFad%Zu$9x2-5UX>!iE`SLInI%f0pN&p`Z8yuTUF{E34Cvs z6letB$Z-X?E{?QLk>336qAGe~aWWYjL9gFZz1@$FVr%JZU%|n?-ITbA<2}Net`=19{Y6;IDgn?} zJX0@|=SsZh5=FKDii)#b*-N9t?}v!PeBJN-CH-g=u&yVgHN-4$E(iR zqN}LLwa}u$xAS@NkV|CA4R}|P45MjzW2vI>4CFR z2f8bw!?2-!c3Bp|#8DU!AD%zo0Sc`tH$BPc0EAt>vA5F+CLRTYDI!pilo5;G+hz2q z?ks?;hlQtr;!Cfoa5lX*y<^@lPw-v7exdVm@h31}`)qPL#+T3swkOqvXAgP<(fh^< zknbmVm|=N^FKNEN^dHOS5S44FH!CDIUmV(-xx7;()X;;0sD0-*W2}vhLe!zDw4T5j zF<`sb$AnK#d!=3^LDZLG06?JJMG?=Ai?xuj!{rH+L`lDx*Jx{dmfyY=R^qZ=#i&|` z{do!FS-q>cndAx)Jips=AMn_r7bVp~zoVWt@atgVk>G^W}_ke$4oEjgBMY!(@vrXbN?dSl@!wp_nSK*0<{| z$p5NnZyMca>_o7njg9f?g5exoW~}E3(Pkr-fia}6BCDID^6w60t^N`&5SL}4V?$=ZORO#MNX)r8qm;50T(x}kC|mOCv=9caM{L~-)87n7Z{e+*SjQ}C|jK*b+_UI+!;$FU^=U5 zoPhZrBTbBiwJeMvr zB$VV9W+6fC$8tK`B5=!q@72wlVJThJxjLBeD`X}}0FD#wX1t^b0EVWDsK4*48W!M7Tl#>_jalYX;mRQuAi|L>tsQfF_)JTs$-E0%n^Lk4YZzQ18gA zmM>{wm6GuK&Ef3Sabj61n{7L1!mmb|FoxT>dv z1>0gQPLNNna}~)ka(i~;PA%YSc#eRZ4uh`%Ny47a)ZMPJ-7c@n6aWa$Q@YXH-UIof zM`f)CE_#{xZU!G@{KE}>KJCwQ)nGdteO^&Fy!rQMJFub2Mn@o6G+?YR>Cj8Q3D=>5 z-oF`eahAj3JnXxTj9I@rFO{3ynUDCh+Td-tSR19_FSNQ?4$L?o0TL_%g#|lPl}b-Q z8eeuG#lT6DPRDhJg-ie;>(h*&iiU<5gj+EjA6qyti}CE|)9iC!dcSjgCyHGQeyXN< zLSrvadsDg9qjl6Zga#Qe%7QFP~dkZo37$_i& zsza~!Jl`B|dYTci2s#w0;L!-zXsdEa&Ov$!F_cI3#7{si+x{D0 zR)1!4AD<#+0%D}8-=5_K(+F`U-AaBOKyy5p%R31 zbBn!E9JzUg0#eVOLPUrj&UpmM&a6{^|Ly_ObyEnNjd70e25^CRnkfn%2W_TT>6KyG z7=4|{kwW_vaMuFZ)j6(U5w23H=d1tXy1dS8zI?E{`nQDcORXT@Lwxh9IR-wXwX$4s z^1!#Von5zg1QUL5uW5hZKX4C(t<(pAqH0<}`)AO4(LRZ|>KAyHwaH)AqKM*YR(>{U zdtnyfURYZ)kHGDmKM)z6ol-r2<=I=lD-F(9^I{J>cIH;ch*`-;pE%XU$s<4f&{2u* z>Qacnlas+?48$^e=MCtrtxivGul`*fm=^{$%j)j#B2b^ZcvHIonhqHav`#s3?fd(x zFUG<5qFlf{6O?G!Y?XZ+=$ z?5T#1dkBdnR*h!?*SxzARZ2tuQ$n0FK;XAi-GDIP}_3q7TaEFcJ2ivY=5Ot&UKaM7{)_mt@e7QzWEg9aL z3I$maL1V1yP|4Qp2@$Sr?l)aA6Bhr@&t|wUoqNEJfF5G|>meX9i1})<_3{ zb0m+I?=Xn>WksK7-_XmM!tawrUX<}BS(3_OhY_X#|7FnJ-WIk0Tkjzxsu*g;`M$i7 z2@cJa>J^okdpeT(tLACk5Ls4BOxj8KAr^$3R=}`w6?%Bi*$!t7^E1p+6E}Yk)j6_gp8OaK<{Oc=pBf+xSzo*?vO^JqmC?i9G#^39b*7tLE z`RnfnJ?my#ZR?bRnBbu2kUaFFC;eJMUNw>v5Nof%5IRZyZQNnkUqHqAFqSVDUwvb_ z4k7ID%PT~LAUP0t$YGLb^KyOgtly}ouYx+NV4$z23%k`KbKVY%4WYgUu+H<_+Ao*&G*o%s(0(X0B z$WPJ01p6U`G5%*jb?AcN@jb4r+Tu9qgPF{$$9((ogSLeS(?T;2&%6K zEz-~7dpc|(8gSNt9t2D6DU;6tbC!iX6?wHA5O2h@*~NWS1Y*e9xw++r8u0F%(p;BV z(b?e*puwP-a)`ZRfujAa;Wx1xMn*sb1KxE6-Xxnx-E5E^;oL9p+y+FnUAxsTxm~s= zH1%V@X{Qp}tj8D#7CmZ2eOow8M}b=2=HCtWwVK5z>P)2#haD_m(s#6D^A%I5Dc}yy zD{<@P4tsd*>hoUtW3-Wpi9WB&D-=JW^DIxdL|#uy-F8>}yP9-`Y4xK! zDN`b4Rz$&eNc5xwF7fW>j4VfsR8LO-kjz1wn$p#)w_~5k!k6pwI$~jeJpUYiBW|C1 zqx;HN(@{xM1+@$0w=u_p2AOrJY0y-HL3X8gCFQqNyMK=>br@drwQllkB}EIjwhuas z$j*}dKgz!Z-2L5nZ=&c*u8+ds^x2{X_-v}E&Lb_~V7@@Ab4`fwp)cvZyk6+m^31X< z0dwPvVTTxe+Bcnc+UnoJzaIiMRF|D}HNRbvh-@ako4qNeE7|gKl%&^H%=f0z(e{;M z+7>^EEPUEO>!fg2Ph5ymA{9AlhlT?w#@xE2wH|B}6Fxr=O2AsbJs=dy`EwH1$UH@- zR%pRL0?rm_)eQ{RQ||}&i-H+G8`};Gz~|hM>BwF4=YF^|*Cq_ZQ-Zg4IjmA?#{FfP z^cqKf-nJ0`dk;u*I+9|q)S)}|l|xQHX^O!B zPF3)j8Cn;v<(qCDOwPvfN!TZ_y*yZ+2x-Z-mi(u--=em54WNFk3_vP7VHrFERi>{v z&+nM)6ED$U6ax);pu2N^RbAB;io9owFSpc8bw#1WDU5}YXB$;iyWonA!Ifi!WOWwW z;2;#kVmT;JD4DRF`CdxEK2^I8ZD{amFfEv?KKCo7+m=Qj#Xv(uzL0NNJ&CG%BxPRb zXJ&MTjE*=@I7=Iy3^-Wbq5l^E2OOb=MMV}3f$>j=z-8W@p5EPS{p<2J$5`;D6?|!N zQ4F`*nrI;oaCxtb4R2L7G#o6nOT46CLti^{oHd=MEr}WXh-a|^51Q*h9Khbp!uHZ4 zJ|0$LZ-QZmjBihGyA=Dc&$Vs&2jYD9x4SM{zrfCcIZi<`04UIpk``Rb-zRagSz9}e zxkKMm6nfb7;VXsSe>8iT5D1|0TK{5}*n=ekkT46dXc!pyrk^2s)nwV5WUh_wH#O~p z^?WsNEQ12?O5#RfF>*S>s(v%N2ghHY1c%NCTq?w}vt&2?nG>~wev}q4=-GWH0r;83 zq1m*ajO%uhS*Fs7-rkXUc_3ItI7$or7EFoO9T*#3)DaipC{6n186_JriH^t)2?@a5 z(&xK&swN9Kg(Ood5cpm93)^Z!g<9UXA(dN4ncoFopuEJrog43xe;jZtjKvtNvK`wC z!cHB;d9Wea{%y4!dvUdgExdkSR~GTTX*?|g7%>hvKp;yAOJu@5HOq7wPcRe#?~i#D z$$c8hl;Fdx)p;;Gm;oeFOs~ldW-?ghnS}SoGb68>&%0qBvYZHy{3G7Ng6~^aHltAR zNm0U1`kCxz+2DVws(!@}mm)fh@oK7-Y5}#(c}}jVVwUsP`DgOZ6r7#=cmC(ve)(kz zGeFIf42OU%7#Qhz9)s{=WFyX2enslEU9usN?0>-fhq+3el;1rQD~~mF>;{GgR5L3u zr1=gijY3H*koUxm;BnOsmaHbrM&HWOrBs5B<19r|pHD|}Ilax9?fpL+9z5UVp_ zFa^T{tzjHGIv``Ez72m*N2OzlY6~qub@R>F+x!SS5B)<3g0t{o)O8M(9fCj$w#{!z zLLlA$o)BJV*~tqW)vznyfS-v1I~4Qqb{{uyZ^r_#@||7j>-#T!{UZ5O?gd58&9#0S zLH{G0r|X?*-^o50UuD`yY5Vr zvR?F~PjWrkEY^g0IcF-|y39-1CN2jEeuZzuN)vCgzEn#m0kn!#u{>tBEQ}e#w|&59j#L! zTZYRbCRgC6}QX}-hdXRY}lBKR^&dU`tW5axUa2TcTQ_~cP~b(d`j zV%1-bE5uCym!1*-6oYoRpxij&V8CLpr*mqq=wQ1DrKKIquL*=kf6+WyJ&ZD`&YTG{ zeC*@o%GW{%$!|j~Y^6g4%Pius8rbpI`R>nh5>}{{MLd{;wz2(1OIZlz&d1U&+b~pm z7ugD)mXYCDAgto^42SEBOxLe?DD~&e2@LS($BKFmAxX8p+4xa&ix{$Xn6-4rPvbm> zitw?}EP7{k2Sf1Cj6m#Qk;Nm&IMISm;MT_XI+S<({Bc-alB$N@+@GrK$!JK@vjt7K zK5tki_oc7Z$ugAAzGrKoMX&Q)=YV&@ce+5*-0a7m_yMEDQ@+YG&+ka~Ytg-4p(yN+ zTVx%mWM)Wp;a~JinCkvN9A6u7Q>M7qkESddTT9azeRgll231KZQVgekYZm7 zICE2yAu6IMHW1|rl!?2R1dSJ;#k%v=M0QUE|T(|#8`9q!0Twees_T$r!2b=_UPS`|TpjI=b@3kc*`nSlTZU=uj*ZmkQu@n4Tn zNiBHf8};%0)1IhFIL0)=hFSqaF~NyCUk$<~clJS{07Y~FUD^{cmGoBw$qcmGG+pt| zsp{Md);|D?mx~pcE$M$AGM1Nn+m%5`U96}Jm5lI1t^?+yaYFYRouCVJFN;s)w!9BO zgQMf%{GUzpX%TS4%+7aYxi$UM7X)Oq93WE=1E3XP7&0xGLX9aA4nfYk(rpk2##Vd4 zu61xHI-_G~G3<7UXgUv^ySWQJk2+BMqU z1GYoqA~)a&yzC8@6V_4pI~}b@Tn1mSBV_TGT3}lW7LM9{ZN)W?;JNUEQSR?_2l4`H zrFivV)*25(lFC7EOL$qjQJusN#ANNi_rDcwtxVJi3s@r&6amNg)<;3s_IX%KBLjti zXgCu1Ie7BRwnQG4Fau6~Yczpes-=B95iMS~vMSFEh+&%EB9SnFX9wm*GNLcO(EW6mUVpNJpCfeS z{xoUu*;j#PKQ_9B@RdpZ{ra5Xt4z9n#unkH>~g6TXI6Nm&^ag%$L@I3&=8O}I$vc$ zKqwgX)3@W2?(G7akxawR($!HM3xej{Uy(P^@z!7xT_T_k$wH>y`AAMmXEwrvUms;v zSC_ohiPdgLYL|i$Fb_ZLAsb!EA>1eU7`$kk7c~beWHD`mZpr z$J0^4uj#(o6XP>8Gn+F=E`JuQ!E)FO^y?#IPty~hRz0@>BKI6)X`^WC`Pvkn*+sAW z2JzTo<~0Hi#xmK5>@HdKdRopN{2jrQo9mQZLEi!gGo%X0fl;iWN$XJQu{M#kCSW@> z^}?)Rnt_6C8Ze)9@2?FFiYZYaCq=aZrT+#PO^D-BF)%5To3h*B(Q@aHA6%%0w_A~V zvESZh?$l@Kk}dpKT3spwm`iEI4zY$Q(E0d+wK1OtlxRpXNvttSuo=6%pnLECwE&

At!00{paGEtazI!w^Z5 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

pGBa+&oF=xhI^=uj}vbEvF$#{jp$5Y27B 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 Y|95eTNMTu_7XmK1m&($m2$RtN10b5Oi2wiq literal 0 HcmV?d00001 diff --git a/www/mug-thumb.png b/www/mug-thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..012c8ab7f88986b28b49228b22d678191c5a0ba3 GIT binary patch literal 43922 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 +#+style: + + +* Mug +/Mug/ is a toy/demo user-interface for =mu=. It is not installable, you'll need +to run it from its source directory. + +Mug comes in two flavors: + - =mug= (in toys/mug), old simple UI, only adding dependency to GTK+ + - =mug2= (in toys/mug2), the new UI, which requires GTK+, Webkit and a + recent GLib. + +The plan for =mug= is to be a testing ground for the widget-code which will +slowly evolve into a full-featured UI. + +#+html: + +=mug2= supports: + - HTML email + - attachments (including in-place opening, drag & drop to desktop) + - bookmarks (see the =mu-bookmarks= man page, the UI will load these in the + left pane) + - view source + +#+html:


© 2011 Dirk-Jan C. Binnema
+#+begin_html + + +#+end_html + + diff --git a/www/old-news.md b/www/old-news.md new file mode 100644 index 0000000..04178e4 --- /dev/null +++ b/www/old-news.md @@ -0,0 +1,90 @@ +--- +layout: default +permalink: code/mu/old-news.html +--- + +# Old news + +- 2011-07-31: mu *0.9.7-pre* is now available with a number of interesting +new features and fixes, many based on user suggestions. `mu` now supports +/mail threading/ based on the [JWZ-algorithm](http://www.jwz.org/doc/threading.html); output is now automatically +converted to the user-locale; `mu view` can output separators between +messages for easier processing, support for X-Label-tags, and last but not +least, `mu` now has bindings for the [Guile](http://www.gnu.org/s/guile/) (Scheme) programming language - +there is a new toy (`toys/muile`) that allows you to inspect messages and +do all kinds of statistics - see the [README](https://gitorious.org/mu/mu/blobs/master/toys/muile/README) for more information. + +- 2011-06-02: after quite a bit of testing, *0.9.6* has been promoted to be +the next release -- forget about the 'bèta'. Development continues for +the next release. + +- 2011-05-28: *mu-0.9.6* (bèta). A lot of internal changes, but also quite +some new features, for example: +- wild-card searching for most fields: mu find 'car*' +- search for message with certain attachments with 'attach:/a:': mu find +'attach:resume*' +- color for `mu find`, `mu cfind`, `mu extract` and `mu view` +Everything is documented in the man-pages, and there are examples in the [[file:cheatsheet.org][mu +cheatsheet]]. + +- 2011-04-25: *mu-0.9.5* a small, but important, bugfix in maildir-detection, +some small optimizations. + +- 2011-04-12: *mu 0.9.4* released - adds the `cfind` command, to find +contacts (name + e-mail); add `flag:unread` which is a synonym for +`flag:new OR NOT flag:seen`. Updates to the documentation and some internal +updates. This is a *bèta-version*. + +- 2011-02-13: *mu 0.9.3*; fixes a bunch of minor issues in 0.9.2; updated the +web page with pages for [mu cheatsheet](file:mug.org][mug]] (the experimental UI) and the [[file:cheatsheet.org). + +- 2011-02-02: *mu 0.9.2* released, which adds support for matching on message +size, and various new output format. See [NEWS](http://gitorious.org/mu/mu/blobs/master/NEWS) for all the user-visible +changes, also from older releases. + + +- [2010-12-05] *mu version 0.9.1* released; fixes a couple of issues users +found with a missing icon, the unit-tests. +- [2010-12-04] *mu version 0.9* released. Compared to the bèta-release, there +were a number of improvements to the documentation and the unit +tests. Pre-processing queries is a little bit smarter now, making matching +e-mail address more eager. Experimental support for Fedora-14. +- [2010-11-27] *mu version 0.9-beta* released. New features: searching is now +accent-insensitive; you can now search for message priority (`prio:`), +time-interval (`date:`) and message flags (`flag:`). Also, you can now store +('bookmark') often-used queries. To top it off, there is a simple graphical +UI now, called `mug`. Documentation has been update, and all known bugs have +been fixed. +- [2010-10-30] *mu version 0.8* released, with only some small cosmetic +updates compared to 0.8-beta. Hurray! +- [2010-10-23] *mu version 0.8-beta* released. The new version brings `mu +extract` for getting the attachments from messages, improved searching +(matching is a bit more 'greedy'), updated and extended documentation, +including the `mu-easy` manpage with simple examples. All known +non-enhancement bugs were fixed. +- [2010-02-27] *mu version 0.7* released. Compared to the beta version, there +are few changes. The maildir-matching syntax now contains a starting `/`, so +`~/Maildir/foo/bar/(cur|new)/msg` can be matched with `m:/foo/bar`. The +top-level maildir can be matched with `m:/`. Apart from that, there are so +small cosmetic fixes and documentation updates. +- [2010-02-11] *mu version 0.7-beta* released. A lot of changes: +- Automatic database scheme version check, notifies users when an +upgrade is needed +- Adds the `mu view` command, to view mail message files +- Removes the 10K match limit +- Support for unattended upgrades - that is, the database can +automatically be upgraded (`--autoupgrade`). Also, the log file is +automatically cleaned when it gets too big (unless you use +`--nocleanup`) +- Search for a certain Maildir using the `maildir:`,`m:` search +prefixes. For example, you can find all messages located in +`~/Maildir/foo/bar/(cur|new)/msg` with `m:foo/bar`. This replaces the +search for path/p in 0.6 +- Fixes for reported issues #17 and #18 +- A test suite with a growing number of unit tests +- Updated documentation +- Many internal refactoring and other changes +This version has been +tagged as `v0.7-beta` in repository, and must be considered a code-complete +preview of the upcoming release 0.7. Please report any problems you encounter +with it. -- 2.30.2